diff --git a/ports/stm32/i2c.c b/ports/stm32/i2c.c index 65271b3525..42aba2eccb 100644 --- a/ports/stm32/i2c.c +++ b/ports/stm32/i2c.c @@ -285,8 +285,17 @@ int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len) { STATIC uint16_t i2c_timeout_ms[MICROPY_HW_MAX_I2C]; +static uint32_t i2c_get_id(i2c_t *i2c) { + #if defined(STM32H7) + if (i2c == I2C4) { + return 3; + } + #endif + return ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); +} + int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq, uint16_t timeout_ms) { - uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); + uint32_t i2c_id = i2c_get_id(i2c); // Init pins if (!mp_hal_pin_config_alt(scl, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, AF_FN_I2C, i2c_id + 1)) { @@ -300,9 +309,22 @@ int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t fr i2c_timeout_ms[i2c_id] = timeout_ms; // Enable I2C peripheral clock - RCC->APB1ENR |= RCC_APB1ENR_I2C1EN << i2c_id; - volatile uint32_t tmp = RCC->APB1ENR; // delay after RCC clock enable + volatile uint32_t tmp; (void)tmp; + switch (i2c_id) { + case 0: + case 1: + case 2: + RCC->APB1ENR |= RCC_APB1ENR_I2C1EN << i2c_id; + tmp = RCC->APB1ENR; // delay after RCC clock enable + break; + #if defined(STM32H7) + case 3: + RCC->APB4ENR |= RCC_APB4ENR_I2C4EN; + tmp = RCC->APB4ENR; // delay after RCC clock enable + break; + #endif + } // Initialise I2C peripheral i2c->CR1 = 0; @@ -340,7 +362,8 @@ int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t fr } STATIC int i2c_wait_cr2_clear(i2c_t *i2c, uint32_t mask) { - uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); + uint32_t i2c_id = i2c_get_id(i2c); + uint32_t t0 = HAL_GetTick(); while (i2c->CR2 & mask) { if (HAL_GetTick() - t0 >= i2c_timeout_ms[i2c_id]) { @@ -352,7 +375,8 @@ STATIC int i2c_wait_cr2_clear(i2c_t *i2c, uint32_t mask) { } STATIC int i2c_wait_isr_set(i2c_t *i2c, uint32_t mask) { - uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); + uint32_t i2c_id = i2c_get_id(i2c); + uint32_t t0 = HAL_GetTick(); while (!(i2c->ISR & mask)) { if (HAL_GetTick() - t0 >= i2c_timeout_ms[i2c_id]) {