@@ -61,6 +61,7 @@ STATIC bool never_reset_i2c[MAX_I2C];
61
61
#define ALL_CLOCKS 0xFF
62
62
STATIC void i2c_clock_enable (uint8_t mask );
63
63
STATIC void i2c_clock_disable (uint8_t mask );
64
+ STATIC void i2c_assign_irq (busio_i2c_obj_t * self , I2C_TypeDef * I2Cx );
64
65
65
66
void i2c_reset (void ) {
66
67
uint16_t never_reset_mask = 0x00 ;
@@ -136,6 +137,10 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
136
137
i2c_clock_enable (1 << (self -> sda -> periph_index - 1 ));
137
138
reserved_i2c [self -> sda -> periph_index - 1 ] = true;
138
139
140
+ // Create root pointer and assign IRQ
141
+ MP_STATE_PORT (cpy_i2c_obj_all )[self -> sda -> periph_index - 1 ] = self ;
142
+ i2c_assign_irq (self , I2Cx );
143
+
139
144
// Handle the HAL handle differences
140
145
#if (CPY_STM32H7 || CPY_STM32F7 )
141
146
if (frequency == 400000 ) {
@@ -163,6 +168,13 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
163
168
}
164
169
common_hal_mcu_pin_claim (sda );
165
170
common_hal_mcu_pin_claim (scl );
171
+
172
+ self -> frame_in_prog = false;
173
+
174
+ //start the receive interrupt chain
175
+ HAL_NVIC_DisableIRQ (self -> irq ); //prevent handle lock contention
176
+ HAL_NVIC_SetPriority (self -> irq , 1 , 0 );
177
+ HAL_NVIC_EnableIRQ (self -> irq );
166
178
}
167
179
168
180
void common_hal_busio_i2c_never_reset (busio_i2c_obj_t * self ) {
@@ -229,15 +241,46 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
229
241
230
242
uint8_t common_hal_busio_i2c_write (busio_i2c_obj_t * self , uint16_t addr ,
231
243
const uint8_t * data , size_t len , bool transmit_stop_bit ) {
232
- HAL_StatusTypeDef result = HAL_I2C_Master_Transmit (& (self -> handle ), (uint16_t )(addr << 1 ),
244
+ HAL_StatusTypeDef result ;
245
+ if (!transmit_stop_bit ) {
246
+ uint32_t xfer_opt ;
247
+ if (!self -> frame_in_prog ) {
248
+ xfer_opt = I2C_FIRST_FRAME ;
249
+ } else {
250
+ // handle rare possibility of multiple restart writes in a row
251
+ xfer_opt = I2C_NEXT_FRAME ;
252
+ }
253
+ result = HAL_I2C_Master_Seq_Transmit_IT (& (self -> handle ),
254
+ (uint16_t )(addr << 1 ), (uint8_t * )data ,
255
+ (uint16_t )len , xfer_opt );
256
+ while (HAL_I2C_GetState (& (self -> handle )) != HAL_I2C_STATE_READY )
257
+ {
258
+ RUN_BACKGROUND_TASKS ;
259
+ }
260
+ self -> frame_in_prog = true;
261
+ } else {
262
+ result = HAL_I2C_Master_Transmit (& (self -> handle ), (uint16_t )(addr << 1 ),
233
263
(uint8_t * )data , (uint16_t )len , 500 );
264
+ }
234
265
return result == HAL_OK ? 0 : MP_EIO ;
235
266
}
236
267
237
268
uint8_t common_hal_busio_i2c_read (busio_i2c_obj_t * self , uint16_t addr ,
238
269
uint8_t * data , size_t len ) {
239
- return HAL_I2C_Master_Receive (& (self -> handle ), (uint16_t )(addr <<1 ), data , (uint16_t )len , 500 )
270
+ if (!self -> frame_in_prog ) {
271
+ return HAL_I2C_Master_Receive (& (self -> handle ), (uint16_t )(addr <<1 ), data , (uint16_t )len , 500 )
240
272
== HAL_OK ? 0 : MP_EIO ;
273
+ } else {
274
+ HAL_StatusTypeDef result = HAL_I2C_Master_Seq_Receive_IT (& (self -> handle ),
275
+ (uint16_t )(addr << 1 ), (uint8_t * )data ,
276
+ (uint16_t )len , I2C_LAST_FRAME );
277
+ while (HAL_I2C_GetState (& (self -> handle )) != HAL_I2C_STATE_READY )
278
+ {
279
+ RUN_BACKGROUND_TASKS ;
280
+ }
281
+ self -> frame_in_prog = false;
282
+ return result ;
283
+ }
241
284
}
242
285
243
286
STATIC void i2c_clock_enable (uint8_t mask ) {
@@ -294,3 +337,48 @@ STATIC void i2c_clock_disable(uint8_t mask) {
294
337
}
295
338
#endif
296
339
}
340
+
341
+ STATIC void i2c_assign_irq (busio_i2c_obj_t * self , I2C_TypeDef * I2Cx ) {
342
+ #ifdef I2C1
343
+ if (I2Cx == I2C1 ) {
344
+ self -> irq = I2C1_EV_IRQn ;
345
+ }
346
+ #endif
347
+ #ifdef I2C2
348
+ if (I2Cx == I2C2 ) {
349
+ self -> irq = I2C2_EV_IRQn ;
350
+ }
351
+ #endif
352
+ #ifdef I2C3
353
+ if (I2Cx == I2C3 ) {
354
+ self -> irq = I2C3_EV_IRQn ;
355
+ }
356
+ #endif
357
+ #ifdef I2C4
358
+ if (I2Cx == I2C4 ) {
359
+ self -> irq = I2C4_EV_IRQn ;
360
+ }
361
+ #endif
362
+ }
363
+
364
+ STATIC void call_hal_irq (int i2c_num ) {
365
+ //Create casted context pointer
366
+ busio_i2c_obj_t * context = (busio_i2c_obj_t * )MP_STATE_PORT (cpy_i2c_obj_all )[i2c_num - 1 ];
367
+ if (context != NULL ) {
368
+ HAL_NVIC_ClearPendingIRQ (context -> irq );
369
+ HAL_I2C_EV_IRQHandler (& context -> handle );
370
+ }
371
+ }
372
+
373
+ void I2C1_EV_IRQHandler (void ) {
374
+ call_hal_irq (1 );
375
+ }
376
+ void I2C2_EV_IRQHandler (void ) {
377
+ call_hal_irq (2 );
378
+ }
379
+ void I2C3_EV_IRQHandler (void ) {
380
+ call_hal_irq (3 );
381
+ }
382
+ void I2C4_EV_IRQHandler (void ) {
383
+ call_hal_irq (4 );
384
+ }
0 commit comments