summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal/i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal/i2c.c')
-rw-r--r--stmhal/i2c.c304
1 files changed, 257 insertions, 47 deletions
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index 07269bce5e..29c350d22f 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -45,14 +45,6 @@
#define MICROPY_HW_I2C_BAUDRATE_MAX 400000
#endif
-#if !defined(I2C_NOSTRETCH_DISABLE)
-// Assumes that the F7 firmware is newer, so the F4 firmware will eventually
-// catchup. I2C_NOSTRETCH_DISABLED was renamed to I2C_NOSTRETCH_DISABLE
-// in the F7 so we use the F7 constant and provide a backwards compatabilty
-// #define here.
-#define I2C_NOSTRETCH_DISABLE I2C_NOSTRETCH_DISABLED
-#endif
-
/// \moduleref pyb
/// \class I2C - a two-wire serial protocol
///
@@ -104,13 +96,6 @@
#define PYB_I2C_MASTER (0)
#define PYB_I2C_SLAVE (1)
-typedef struct _pyb_i2c_obj_t {
- mp_obj_base_t base;
- I2C_HandleTypeDef *i2c;
- const dma_descr_t *tx_dma_descr;
- const dma_descr_t *rx_dma_descr;
-} pyb_i2c_obj_t;
-
#if defined(MICROPY_HW_I2C1_SCL)
I2C_HandleTypeDef I2CHandle1 = {.Instance = NULL};
#endif
@@ -120,22 +105,32 @@ I2C_HandleTypeDef I2CHandle2 = {.Instance = NULL};
#if defined(MICROPY_HW_I2C3_SCL)
I2C_HandleTypeDef I2CHandle3 = {.Instance = NULL};
#endif
+#if defined(MICROPY_HW_I2C4_SCL)
+I2C_HandleTypeDef I2CHandle4 = {.Instance = NULL};
+#endif
+
+STATIC bool pyb_i2c_use_dma[4];
-STATIC const pyb_i2c_obj_t pyb_i2c_obj[] = {
+const pyb_i2c_obj_t pyb_i2c_obj[] = {
#if defined(MICROPY_HW_I2C1_SCL)
- {{&pyb_i2c_type}, &I2CHandle1, &dma_I2C_1_TX, &dma_I2C_1_RX},
+ {{&pyb_i2c_type}, &I2CHandle1, &dma_I2C_1_TX, &dma_I2C_1_RX, &pyb_i2c_use_dma[0]},
#else
- {{&pyb_i2c_type}, NULL, NULL, NULL},
+ {{&pyb_i2c_type}, NULL, NULL, NULL, NULL},
#endif
#if defined(MICROPY_HW_I2C2_SCL)
- {{&pyb_i2c_type}, &I2CHandle2, &dma_I2C_2_TX, &dma_I2C_2_RX},
+ {{&pyb_i2c_type}, &I2CHandle2, &dma_I2C_2_TX, &dma_I2C_2_RX, &pyb_i2c_use_dma[1]},
#else
- {{&pyb_i2c_type}, NULL, NULL, NULL},
+ {{&pyb_i2c_type}, NULL, NULL, NULL, NULL},
#endif
#if defined(MICROPY_HW_I2C3_SCL)
- {{&pyb_i2c_type}, &I2CHandle3, &dma_I2C_3_TX, &dma_I2C_3_RX},
+ {{&pyb_i2c_type}, &I2CHandle3, &dma_I2C_3_TX, &dma_I2C_3_RX, &pyb_i2c_use_dma[2]},
+ #else
+ {{&pyb_i2c_type}, NULL, NULL, NULL, NULL},
+ #endif
+ #if defined(MICROPY_HW_I2C4_SCL)
+ {{&pyb_i2c_type}, &I2CHandle4, &dma_I2C_4_TX, &dma_I2C_4_RX, &pyb_i2c_use_dma[3]},
#else
- {{&pyb_i2c_type}, NULL, NULL, NULL},
+ {{&pyb_i2c_type}, NULL, NULL, NULL, NULL},
#endif
};
@@ -161,7 +156,7 @@ STATIC void i2c_set_baudrate(I2C_InitTypeDef *init, uint32_t baudrate) {
"Unsupported I2C baudrate: %lu", baudrate));
}
-STATIC uint32_t i2c_get_baudrate(I2C_InitTypeDef *init) {
+uint32_t i2c_get_baudrate(I2C_InitTypeDef *init) {
for (int i = 0; i < NUM_BAUDRATE_TIMINGS; i++) {
if (pyb_i2c_baudrate_timing[i].timing == init->Timing) {
return pyb_i2c_baudrate_timing[i].baudrate;
@@ -177,7 +172,7 @@ STATIC void i2c_set_baudrate(I2C_InitTypeDef *init, uint32_t baudrate) {
init->DutyCycle = I2C_DUTYCYCLE_16_9;
}
-STATIC uint32_t i2c_get_baudrate(I2C_InitTypeDef *init) {
+uint32_t i2c_get_baudrate(I2C_InitTypeDef *init) {
return init->ClockSpeed;
}
@@ -197,15 +192,13 @@ void i2c_init0(void) {
memset(&I2CHandle3, 0, sizeof(I2C_HandleTypeDef));
I2CHandle3.Instance = I2C3;
#endif
+ #if defined(MICROPY_HW_I2C4_SCL)
+ memset(&I2CHandle4, 0, sizeof(I2C_HandleTypeDef));
+ I2CHandle3.Instance = I2C4;
+ #endif
}
void i2c_init(I2C_HandleTypeDef *i2c) {
- // init the GPIO lines
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
- GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
- GPIO_InitStructure.Pull = GPIO_NOPULL; // have external pull-up resistors on both lines
-
int i2c_unit;
const pin_obj_t *scl_pin;
const pin_obj_t *sda_pin;
@@ -232,14 +225,23 @@ void i2c_init(I2C_HandleTypeDef *i2c) {
sda_pin = &MICROPY_HW_I2C3_SDA;
__I2C3_CLK_ENABLE();
#endif
+ #if defined(MICROPY_HW_I2C4_SCL)
+ } else if (i2c == &I2CHandle4) {
+ i2c_unit = 4;
+ scl_pin = &MICROPY_HW_I2C4_SCL;
+ sda_pin = &MICROPY_HW_I2C4_SDA;
+ __I2C3_CLK_ENABLE();
+ #endif
} else {
// I2C does not exist for this board (shouldn't get here, should be checked by caller)
return;
}
// init the GPIO lines
- mp_hal_pin_set_af(scl_pin, &GPIO_InitStructure, AF_FN_I2C, i2c_unit);
- mp_hal_pin_set_af(sda_pin, &GPIO_InitStructure, AF_FN_I2C, i2c_unit);
+ uint32_t mode = MP_HAL_PIN_MODE_ALT_OPEN_DRAIN;
+ uint32_t pull = MP_HAL_PIN_PULL_NONE; // have external pull-up resistors on both lines
+ mp_hal_pin_config_alt(scl_pin, mode, pull, AF_FN_I2C, i2c_unit);
+ mp_hal_pin_config_alt(sda_pin, mode, pull, AF_FN_I2C, i2c_unit);
// init the I2C device
if (HAL_I2C_Init(i2c) != HAL_OK) {
@@ -254,6 +256,29 @@ void i2c_init(I2C_HandleTypeDef *i2c) {
const pyb_i2c_obj_t *self = &pyb_i2c_obj[i2c_unit - 1];
dma_invalidate_channel(self->tx_dma_descr);
dma_invalidate_channel(self->rx_dma_descr);
+
+ if (0) {
+ #if defined(MICROPY_HW_I2C1_SCL)
+ } else if (i2c->Instance == I2C1) {
+ HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
+ HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
+ #endif
+ #if defined(MICROPY_HW_I2C2_SCL)
+ } else if (i2c->Instance == I2C2) {
+ HAL_NVIC_EnableIRQ(I2C2_EV_IRQn);
+ HAL_NVIC_EnableIRQ(I2C2_ER_IRQn);
+ #endif
+ #if defined(MICROPY_HW_I2C3_SCL)
+ } else if (i2c->Instance == I2C3) {
+ HAL_NVIC_EnableIRQ(I2C3_EV_IRQn);
+ HAL_NVIC_EnableIRQ(I2C3_ER_IRQn);
+ #endif
+ #if defined(MICROPY_HW_I2C4_SCL)
+ } else if (i2c->Instance == I2C4) {
+ HAL_NVIC_EnableIRQ(I2C4_EV_IRQn);
+ HAL_NVIC_EnableIRQ(I2C4_ER_IRQn);
+ #endif
+ }
}
void i2c_deinit(I2C_HandleTypeDef *i2c) {
@@ -264,22 +289,187 @@ void i2c_deinit(I2C_HandleTypeDef *i2c) {
__I2C1_FORCE_RESET();
__I2C1_RELEASE_RESET();
__I2C1_CLK_DISABLE();
+ HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
+ HAL_NVIC_DisableIRQ(I2C1_ER_IRQn);
#endif
#if defined(MICROPY_HW_I2C2_SCL)
} else if (i2c->Instance == I2C2) {
__I2C2_FORCE_RESET();
__I2C2_RELEASE_RESET();
__I2C2_CLK_DISABLE();
+ HAL_NVIC_DisableIRQ(I2C2_EV_IRQn);
+ HAL_NVIC_DisableIRQ(I2C2_ER_IRQn);
#endif
#if defined(MICROPY_HW_I2C3_SCL)
} else if (i2c->Instance == I2C3) {
__I2C3_FORCE_RESET();
__I2C3_RELEASE_RESET();
__I2C3_CLK_DISABLE();
+ HAL_NVIC_DisableIRQ(I2C3_EV_IRQn);
+ HAL_NVIC_DisableIRQ(I2C3_ER_IRQn);
+ #endif
+ #if defined(MICROPY_HW_I2C4_SCL)
+ } else if (i2c->Instance == I2C4) {
+ __HAL_RCC_I2C4_FORCE_RESET();
+ __HAL_RCC_I2C4_RELEASE_RESET();
+ __HAL_RCC_I2C4_CLK_DISABLE();
+ HAL_NVIC_DisableIRQ(I2C4_EV_IRQn);
+ HAL_NVIC_DisableIRQ(I2C4_ER_IRQn);
#endif
}
}
+void i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq) {
+ I2C_InitTypeDef *init = &self->i2c->Init;
+
+ init->AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ init->DualAddressMode = I2C_DUALADDRESS_DISABLED;
+ init->GeneralCallMode = I2C_GENERALCALL_DISABLED;
+ init->NoStretchMode = I2C_NOSTRETCH_DISABLE;
+ init->OwnAddress1 = PYB_I2C_MASTER_ADDRESS;
+ init->OwnAddress2 = 0; // unused
+ if (freq != -1) {
+ i2c_set_baudrate(init, MIN(freq, MICROPY_HW_I2C_BAUDRATE_MAX));
+ }
+
+ *self->use_dma = false;
+
+ // init the I2C bus
+ i2c_deinit(self->i2c);
+ i2c_init(self->i2c);
+}
+
+STATIC void i2c_reset_after_error(I2C_HandleTypeDef *i2c) {
+ // wait for bus-busy flag to be cleared, with a timeout
+ for (int timeout = 50; timeout > 0; --timeout) {
+ if (!__HAL_I2C_GET_FLAG(i2c, I2C_FLAG_BUSY)) {
+ // stop bit was generated and bus is back to normal
+ return;
+ }
+ HAL_Delay(1);
+ }
+ // bus was/is busy, need to reset the peripheral to get it to work again
+ i2c_deinit(i2c);
+ i2c_init(i2c);
+}
+
+void i2c_ev_irq_handler(mp_uint_t i2c_id) {
+ I2C_HandleTypeDef *hi2c;
+
+ switch (i2c_id) {
+ #if defined(MICROPY_HW_I2C1_SCL)
+ case 1:
+ hi2c = &I2CHandle1;
+ break;
+ #endif
+ #if defined(MICROPY_HW_I2C2_SCL)
+ case 2:
+ hi2c = &I2CHandle2;
+ break;
+ #endif
+ #if defined(MICROPY_HW_I2C3_SCL)
+ case 3:
+ hi2c = &I2CHandle3;
+ break;
+ #endif
+ #if defined(MICROPY_HW_I2C4_SCL)
+ case 4:
+ hi2c = &I2CHandle4;
+ break;
+ #endif
+ default:
+ return;
+ }
+
+ #if defined(MCU_SERIES_F4)
+
+ if (hi2c->Instance->SR1 & I2C_FLAG_BTF && hi2c->State == HAL_I2C_STATE_BUSY_TX) {
+ if (hi2c->XferCount != 0U) {
+ hi2c->Instance->DR = *hi2c->pBuffPtr++;
+ hi2c->XferCount--;
+ } else {
+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR);
+ if (hi2c->XferOptions != I2C_FIRST_FRAME) {
+ hi2c->Instance->CR1 |= I2C_CR1_STOP;
+ }
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ }
+ }
+
+ #else
+
+ // if not an F4 MCU, use the HAL's IRQ handler
+ HAL_I2C_EV_IRQHandler(hi2c);
+
+ #endif
+}
+
+void i2c_er_irq_handler(mp_uint_t i2c_id) {
+ I2C_HandleTypeDef *hi2c;
+
+ switch (i2c_id) {
+ #if defined(MICROPY_HW_I2C1_SCL)
+ case 1:
+ hi2c = &I2CHandle1;
+ break;
+ #endif
+ #if defined(MICROPY_HW_I2C2_SCL)
+ case 2:
+ hi2c = &I2CHandle2;
+ break;
+ #endif
+ #if defined(MICROPY_HW_I2C3_SCL)
+ case 3:
+ hi2c = &I2CHandle3;
+ break;
+ #endif
+ #if defined(MICROPY_HW_I2C4_SCL)
+ case 4:
+ hi2c = &I2CHandle4;
+ break;
+ #endif
+ default:
+ return;
+ }
+
+ #if defined(MCU_SERIES_F4)
+
+ uint32_t sr1 = hi2c->Instance->SR1;
+
+ // I2C Bus error
+ if (sr1 & I2C_FLAG_BERR) {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_BERR;
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR);
+ }
+
+ // I2C Arbitration Loss error
+ if (sr1 & I2C_FLAG_ARLO) {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO;
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO);
+ }
+
+ // I2C Acknowledge failure
+ if (sr1 & I2C_FLAG_AF) {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ SET_BIT(hi2c->Instance->CR1,I2C_CR1_STOP);
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ }
+
+ // I2C Over-Run/Under-Run
+ if (sr1 & I2C_FLAG_OVR) {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_OVR;
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR);
+ }
+
+ #else
+
+ // if not an F4 MCU, use the HAL's IRQ handler
+ HAL_I2C_ER_IRQHandler(hi2c);
+
+ #endif
+}
+
STATIC HAL_StatusTypeDef i2c_wait_dma_finished(I2C_HandleTypeDef *i2c, uint32_t timeout) {
// Note: we can't use WFI to idle in this loop because the DMA completion
// interrupt may occur before the WFI. Hence we miss it and have to wait
@@ -312,6 +502,9 @@ STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
#if defined(MICROPY_HW_I2C3_SCL)
else if (self->i2c->Instance == I2C3) { i2c_num = 3; }
#endif
+ #if defined(MICROPY_HW_I2C4_SCL)
+ else if (self->i2c->Instance == I2C4) { i2c_num = 4; }
+ #endif
if (self->i2c->State == HAL_I2C_STATE_RESET) {
mp_printf(print, "I2C(%u)", i2c_num);
@@ -338,6 +531,7 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, mp_uint_t n_args,
{ MP_QSTR_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x12} },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_HW_I2C_BAUDRATE_DEFAULT} },
{ MP_QSTR_gencall, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_dma, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
// parse args
@@ -358,11 +552,13 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, mp_uint_t n_args,
init->AddressingMode = I2C_ADDRESSINGMODE_7BIT;
init->DualAddressMode = I2C_DUALADDRESS_DISABLED;
init->GeneralCallMode = args[3].u_bool ? I2C_GENERALCALL_ENABLED : I2C_GENERALCALL_DISABLED;
- init->NoStretchMode = I2C_NOSTRETCH_DISABLED;
init->OwnAddress2 = 0; // unused
init->NoStretchMode = I2C_NOSTRETCH_DISABLE;
+ *self->use_dma = args[4].u_bool;
+
// init the I2C bus
+ i2c_deinit(self->i2c);
i2c_init(self->i2c);
return mp_const_none;
@@ -380,7 +576,7 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, mp_uint_t n_args,
///
/// - `I2C(1)` is on the X position: `(SCL, SDA) = (X9, X10) = (PB6, PB7)`
/// - `I2C(2)` is on the Y position: `(SCL, SDA) = (Y9, Y10) = (PB10, PB11)`
-STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
@@ -514,9 +710,11 @@ STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
uint8_t data[1];
pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data);
- // if IRQs are enabled then we can use DMA
+ // if option is set and IRQs are enabled then we can use DMA
+ bool use_dma = *self->use_dma && query_irq() == IRQ_STATE_ENABLED;
+
DMA_HandleTypeDef tx_dma;
- if (query_irq() == IRQ_STATE_ENABLED) {
+ if (use_dma) {
dma_init(&tx_dma, self->tx_dma_descr, self->i2c);
self->i2c->hdmatx = &tx_dma;
self->i2c->hdmarx = NULL;
@@ -526,19 +724,19 @@ STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
HAL_StatusTypeDef status;
if (in_master_mode(self)) {
if (args[1].u_int == PYB_I2C_MASTER_ADDRESS) {
- if (query_irq() == IRQ_STATE_ENABLED) {
+ if (use_dma) {
dma_deinit(self->tx_dma_descr);
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "addr argument required"));
}
mp_uint_t i2c_addr = args[1].u_int << 1;
- if (query_irq() == IRQ_STATE_DISABLED) {
+ if (!use_dma) {
status = HAL_I2C_Master_Transmit(self->i2c, i2c_addr, bufinfo.buf, bufinfo.len, args[2].u_int);
} else {
status = HAL_I2C_Master_Transmit_DMA(self->i2c, i2c_addr, bufinfo.buf, bufinfo.len);
}
} else {
- if (query_irq() == IRQ_STATE_DISABLED) {
+ if (!use_dma) {
status = HAL_I2C_Slave_Transmit(self->i2c, bufinfo.buf, bufinfo.len, args[2].u_int);
} else {
status = HAL_I2C_Slave_Transmit_DMA(self->i2c, bufinfo.buf, bufinfo.len);
@@ -546,7 +744,7 @@ STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
}
// if we used DMA, wait for it to finish
- if (query_irq() == IRQ_STATE_ENABLED) {
+ if (use_dma) {
if (status == HAL_OK) {
status = i2c_wait_dma_finished(self->i2c, args[2].u_int);
}
@@ -554,6 +752,7 @@ STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
}
if (status != HAL_OK) {
+ i2c_reset_after_error(self->i2c);
mp_hal_raise(status);
}
@@ -588,9 +787,11 @@ STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
vstr_t vstr;
mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr);
- // if IRQs are enabled then we can use DMA
+ // if option is set and IRQs are enabled then we can use DMA
+ bool use_dma = *self->use_dma && query_irq() == IRQ_STATE_ENABLED;
+
DMA_HandleTypeDef rx_dma;
- if (query_irq() == IRQ_STATE_ENABLED) {
+ if (use_dma) {
dma_init(&rx_dma, self->rx_dma_descr, self->i2c);
self->i2c->hdmatx = NULL;
self->i2c->hdmarx = &rx_dma;
@@ -603,13 +804,13 @@ STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "addr argument required"));
}
mp_uint_t i2c_addr = args[1].u_int << 1;
- if (query_irq() == IRQ_STATE_DISABLED) {
+ if (!use_dma) {
status = HAL_I2C_Master_Receive(self->i2c, i2c_addr, (uint8_t*)vstr.buf, vstr.len, args[2].u_int);
} else {
status = HAL_I2C_Master_Receive_DMA(self->i2c, i2c_addr, (uint8_t*)vstr.buf, vstr.len);
}
} else {
- if (query_irq() == IRQ_STATE_DISABLED) {
+ if (!use_dma) {
status = HAL_I2C_Slave_Receive(self->i2c, (uint8_t*)vstr.buf, vstr.len, args[2].u_int);
} else {
status = HAL_I2C_Slave_Receive_DMA(self->i2c, (uint8_t*)vstr.buf, vstr.len);
@@ -617,7 +818,7 @@ STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
}
// if we used DMA, wait for it to finish
- if (query_irq() == IRQ_STATE_ENABLED) {
+ if (use_dma) {
if (status == HAL_OK) {
status = i2c_wait_dma_finished(self->i2c, args[2].u_int);
}
@@ -625,6 +826,7 @@ STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
}
if (status != HAL_OK) {
+ i2c_reset_after_error(self->i2c);
mp_hal_raise(status);
}
@@ -680,8 +882,11 @@ STATIC mp_obj_t pyb_i2c_mem_read(mp_uint_t n_args, const mp_obj_t *pos_args, mp_
mem_addr_size = I2C_MEMADD_SIZE_16BIT;
}
+ // if option is set and IRQs are enabled then we can use DMA
+ bool use_dma = *self->use_dma && query_irq() == IRQ_STATE_ENABLED;
+
HAL_StatusTypeDef status;
- if (query_irq() == IRQ_STATE_DISABLED) {
+ if (!use_dma) {
status = HAL_I2C_Mem_Read(self->i2c, i2c_addr, mem_addr, mem_addr_size, (uint8_t*)vstr.buf, vstr.len, args[3].u_int);
} else {
DMA_HandleTypeDef rx_dma;
@@ -696,6 +901,7 @@ STATIC mp_obj_t pyb_i2c_mem_read(mp_uint_t n_args, const mp_obj_t *pos_args, mp_
}
if (status != HAL_OK) {
+ i2c_reset_after_error(self->i2c);
mp_hal_raise(status);
}
@@ -744,8 +950,11 @@ STATIC mp_obj_t pyb_i2c_mem_write(mp_uint_t n_args, const mp_obj_t *pos_args, mp
mem_addr_size = I2C_MEMADD_SIZE_16BIT;
}
+ // if option is set and IRQs are enabled then we can use DMA
+ bool use_dma = *self->use_dma && query_irq() == IRQ_STATE_ENABLED;
+
HAL_StatusTypeDef status;
- if (query_irq() == IRQ_STATE_DISABLED) {
+ if (!use_dma) {
status = HAL_I2C_Mem_Write(self->i2c, i2c_addr, mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len, args[3].u_int);
} else {
DMA_HandleTypeDef tx_dma;
@@ -760,6 +969,7 @@ STATIC mp_obj_t pyb_i2c_mem_write(mp_uint_t n_args, const mp_obj_t *pos_args, mp
}
if (status != HAL_OK) {
+ i2c_reset_after_error(self->i2c);
mp_hal_raise(status);
}