@@ -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