@@ -36,6 +36,9 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
36
36
{
37
37
uint32_t i2c_sda = pinmap_peripheral (sda , PinMap_I2C_SDA );
38
38
uint32_t i2c_scl = pinmap_peripheral (scl , PinMap_I2C_SCL );
39
+ PORT_Type * port_addrs [] = PORT_BASE_PTRS ;
40
+ PORT_Type * base = port_addrs [sda >> GPIO_PORT_SHIFT ];
41
+
39
42
obj -> instance = pinmap_merge (i2c_sda , i2c_scl );
40
43
obj -> next_repeated_start = 0 ;
41
44
MBED_ASSERT ((int )obj -> instance != NC );
@@ -49,10 +52,11 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
49
52
pinmap_pinout (sda , PinMap_I2C_SDA );
50
53
pinmap_pinout (scl , PinMap_I2C_SCL );
51
54
52
- #if defined( FSL_FEATURE_PORT_HAS_OPEN_DRAIN ) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
53
- PORT_Type * port_addrs [] = PORT_BASE_PTRS ;
54
- PORT_Type * base = port_addrs [ sda >> GPIO_PORT_SHIFT ] ;
55
+ /* Enable internal pullup resistor */
56
+ base -> PCR [ sda & 0xFF ] |= ( PORT_PCR_PE_MASK | PORT_PCR_PS_MASK ) ;
57
+ base -> PCR [ scl & 0xFF ] |= ( PORT_PCR_PE_MASK | PORT_PCR_PS_MASK ) ;
55
58
59
+ #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN ) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
56
60
base -> PCR [sda & 0xFF ] |= PORT_PCR_ODE_MASK ;
57
61
base -> PCR [scl & 0xFF ] |= PORT_PCR_ODE_MASK ;
58
62
#endif
@@ -63,12 +67,14 @@ int i2c_start(i2c_t *obj)
63
67
I2C_Type * base = i2c_addrs [obj -> instance ];
64
68
uint32_t statusFlags = I2C_MasterGetStatusFlags (base );
65
69
66
- /* Return an error if the bus is already in use. */
70
+ /* Check if the bus is already in use. */
67
71
if (statusFlags & kI2C_BusBusyFlag ) {
68
- return 1 ;
72
+ /* Send a repeat START signal. */
73
+ base -> C1 |= I2C_C1_RSTA_MASK ;
74
+ } else {
75
+ /* Send the START signal. */
76
+ base -> C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK ;
69
77
}
70
- /* Send the START signal. */
71
- base -> C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK ;
72
78
73
79
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING ) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING
74
80
while (!(base -> S2 & I2C_S2_EMPTY_MASK ))
@@ -81,7 +87,6 @@ int i2c_start(i2c_t *obj)
81
87
82
88
int i2c_stop (i2c_t * obj )
83
89
{
84
- obj -> next_repeated_start = 0 ;
85
90
if (I2C_MasterStop (i2c_addrs [obj -> instance ]) != kStatus_Success ) {
86
91
return 1 ;
87
92
}
@@ -179,39 +184,64 @@ int i2c_byte_read(i2c_t *obj, int last)
179
184
{
180
185
uint8_t data ;
181
186
I2C_Type * base = i2c_addrs [obj -> instance ];
182
- i2c_master_transfer_t master_xfer ;
183
187
184
- memset (& master_xfer , 0 , sizeof (master_xfer ));
185
- master_xfer .slaveAddress = i2c_address ;
186
- master_xfer .direction = kI2C_Read ;
187
- master_xfer .data = & data ;
188
- master_xfer .dataSize = 1 ;
188
+ /* Setup the I2C peripheral to receive data. */
189
+ base -> C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK );
189
190
190
- /* The below function will issue a STOP signal at the end of the transfer.
191
- * This is required by the hardware in order to receive the last byte
192
- */
193
- if (I2C_MasterTransferBlocking (base , & master_xfer ) != kStatus_Success ) {
194
- return I2C_ERROR_NO_SLAVE ;
191
+ if (last ) {
192
+ base -> C1 |= I2C_C1_TXAK_MASK ; // NACK
193
+ }
194
+
195
+ data = (base -> D & 0xFF );
196
+
197
+ /* Change direction to Tx to avoid extra clocks. */
198
+ base -> C1 |= I2C_C1_TX_MASK ;
199
+
200
+ /* Wait until data transfer complete. */
201
+ while (!(base -> S & kI2C_IntPendingFlag ))
202
+ {
195
203
}
204
+
205
+ /* Clear the IICIF flag. */
206
+ base -> S = kI2C_IntPendingFlag ;
207
+
196
208
return data ;
197
209
}
198
210
199
211
int i2c_byte_write (i2c_t * obj , int data )
200
212
{
201
- status_t ret_value ;
202
- #if FSL_I2C_DRIVER_VERSION > MAKE_VERSION (2 , 0 , 1 )
203
- ret_value = I2C_MasterWriteBlocking (i2c_addrs [obj -> instance ], (uint8_t * )(& data ), 1 , kI2C_TransferNoStopFlag );
204
- #else
205
- ret_value = I2C_MasterWriteBlocking (i2c_addrs [obj -> instance ], (uint8_t * )(& data ), 1 );
206
- #endif
213
+ int ret_value = 1 ;
214
+ uint8_t statusFlags = 0 ;
215
+ I2C_Type * base = i2c_addrs [obj -> instance ];
207
216
208
- if (ret_value == kStatus_Success ) {
209
- return 1 ;
210
- } else if (ret_value == kStatus_I2C_Nak ) {
211
- return 0 ;
212
- } else {
213
- return 2 ;
217
+ /* Setup the I2C peripheral to transmit data. */
218
+ base -> C1 |= I2C_C1_TX_MASK ;
219
+
220
+ /* Send a byte of data. */
221
+ base -> D = data ;
222
+
223
+ /* Wait until data transfer complete. */
224
+ while (!(base -> S & kI2C_IntPendingFlag )) {
225
+ }
226
+
227
+ statusFlags = base -> S ;
228
+
229
+ /* Clear the IICIF flag. */
230
+ base -> S = kI2C_IntPendingFlag ;
231
+
232
+ /* Check if arbitration lost */
233
+ if (statusFlags & kI2C_ArbitrationLostFlag ) {
234
+ base -> S = kI2C_ArbitrationLostFlag ;
235
+ ret_value = 2 ;
214
236
}
237
+
238
+ /* Check if no acknowledgement (NAK) */
239
+ if (statusFlags & kI2C_ReceiveNakFlag ) {
240
+ base -> S = kI2C_ReceiveNakFlag ;
241
+ ret_value = 0 ;
242
+ }
243
+
244
+ return ret_value ;
215
245
}
216
246
217
247
0 commit comments