diff options
author | Damien George <damien.p.george@gmail.com> | 2016-11-11 17:38:52 +1100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2016-11-11 17:38:52 +1100 |
commit | 74fb5d6932c835f92c6985799e30ea28b6449705 (patch) | |
tree | 0e723304367f3fb3b6fd34d1968b3f3356b5124c | |
parent | c4e58eaa9820f5e63d9d94cec5ffb403c1dffbe7 (diff) | |
download | micropython-74fb5d6932c835f92c6985799e30ea28b6449705.tar.gz micropython-74fb5d6932c835f92c6985799e30ea28b6449705.zip |
stmhal/i2c: Reset the I2C peripheral if there was an error on the bus.
If an I2C send/recv fails then the peripheral is now checked to see if
it's in a "stuck" state waiting for the stop bit, and if so then it is
reset so that the next I2C transaction can proceed.
This patch also de-inits the I2C peripheral in the init() method, before
init'ing it again.
-rw-r--r-- | stmhal/i2c.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/stmhal/i2c.c b/stmhal/i2c.c index 9f74a2139e..0af2232143 100644 --- a/stmhal/i2c.c +++ b/stmhal/i2c.c @@ -283,6 +283,20 @@ void i2c_deinit(I2C_HandleTypeDef *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); +} + 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 @@ -369,6 +383,7 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, mp_uint_t n_args, *self->use_dma = args[4].u_bool; // init the I2C bus + i2c_deinit(self->i2c); i2c_init(self->i2c); return mp_const_none; @@ -562,6 +577,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); } @@ -635,6 +651,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); } @@ -709,6 +726,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); } @@ -776,6 +794,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); } |