diff options
-rw-r--r-- | stmhal/i2c.c | 89 | ||||
-rw-r--r-- | stmhal/i2c.h | 2 | ||||
-rw-r--r-- | stmhal/stm32_it.c | 12 |
3 files changed, 97 insertions, 6 deletions
diff --git a/stmhal/i2c.c b/stmhal/i2c.c index 53c9667b6a..17557a46e5 100644 --- a/stmhal/i2c.c +++ b/stmhal/i2c.c @@ -317,6 +317,95 @@ STATIC void i2c_reset_after_error(I2C_HandleTypeDef *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 + default: + return; + } + + 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; + } + } +} + +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 + default: + return; + } + + 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); + } +} + 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 diff --git a/stmhal/i2c.h b/stmhal/i2c.h index a159935e6a..c7e64e1142 100644 --- a/stmhal/i2c.h +++ b/stmhal/i2c.h @@ -34,3 +34,5 @@ extern const mp_obj_type_t pyb_i2c_type; void i2c_init0(void); void i2c_init(I2C_HandleTypeDef *i2c); +void i2c_ev_irq_handler(mp_uint_t i2c_id); +void i2c_er_irq_handler(mp_uint_t i2c_id); diff --git a/stmhal/stm32_it.c b/stmhal/stm32_it.c index f596559150..48e10e824b 100644 --- a/stmhal/stm32_it.c +++ b/stmhal/stm32_it.c @@ -706,13 +706,13 @@ void CAN2_RX1_IRQHandler(void) { #if defined(MICROPY_HW_I2C1_SCL) void I2C1_EV_IRQHandler(void) { IRQ_ENTER(I2C1_EV_IRQn); - HAL_I2C_EV_IRQHandler(&I2CHandle1); + i2c_ev_irq_handler(1); IRQ_EXIT(I2C1_EV_IRQn); } void I2C1_ER_IRQHandler(void) { IRQ_ENTER(I2C1_ER_IRQn); - HAL_I2C_ER_IRQHandler(&I2CHandle1); + i2c_er_irq_handler(1); IRQ_EXIT(I2C1_ER_IRQn); } #endif // defined(MICROPY_HW_I2C1_SCL) @@ -720,13 +720,13 @@ void I2C1_ER_IRQHandler(void) { #if defined(MICROPY_HW_I2C2_SCL) void I2C2_EV_IRQHandler(void) { IRQ_ENTER(I2C2_EV_IRQn); - HAL_I2C_EV_IRQHandler(&I2CHandle2); + i2c_ev_irq_handler(2); IRQ_EXIT(I2C2_EV_IRQn); } void I2C2_ER_IRQHandler(void) { IRQ_ENTER(I2C2_ER_IRQn); - HAL_I2C_ER_IRQHandler(&I2CHandle2); + i2c_er_irq_handler(2); IRQ_EXIT(I2C2_ER_IRQn); } #endif // defined(MICROPY_HW_I2C2_SCL) @@ -734,13 +734,13 @@ void I2C2_ER_IRQHandler(void) { #if defined(MICROPY_HW_I2C3_SCL) void I2C3_EV_IRQHandler(void) { IRQ_ENTER(I2C3_EV_IRQn); - HAL_I2C_EV_IRQHandler(&I2CHandle3); + i2c_ev_irq_handler(3); IRQ_EXIT(I2C3_EV_IRQn); } void I2C3_ER_IRQHandler(void) { IRQ_ENTER(I2C3_ER_IRQn); - HAL_I2C_ER_IRQHandler(&I2CHandle3); + i2c_er_irq_handler(3); IRQ_EXIT(I2C3_ER_IRQn); } #endif // defined(MICROPY_HW_I2C3_SCL) |