From e0c8def28a89294c8d10ffb88e6b33e94b53b73a Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Thu, 27 Oct 2016 17:30:40 +0200 Subject: [PATCH] STM32: I2C: Reset I2C in case of errors to recover This is to avoid an IP / bus deadlock. This requires to store scl and sda in order to call the init function. --- targets/TARGET_STM/TARGET_STM32F4/common_objects.h | 2 ++ targets/TARGET_STM/TARGET_STM32F4/i2c_api.c | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32F4/common_objects.h b/targets/TARGET_STM/TARGET_STM32F4/common_objects.h index 7a0cbb0613..8259ec97c7 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/common_objects.h +++ b/targets/TARGET_STM/TARGET_STM32F4/common_objects.h @@ -91,6 +91,8 @@ struct i2c_s { I2CName i2c; I2C_HandleTypeDef handle; uint8_t index; + PinName sda; + PinName scl; IRQn_Type event_i2cIRQ; IRQn_Type error_i2cIRQ; volatile uint8_t event; diff --git a/targets/TARGET_STM/TARGET_STM32F4/i2c_api.c b/targets/TARGET_STM/TARGET_STM32F4/i2c_api.c index 857847c627..185a10ecf1 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/i2c_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/i2c_api.c @@ -174,6 +174,8 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { // Determine the I2C to use I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); + obj_s->sda = sda; + obj_s->scl = scl; obj_s->i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl); MBED_ASSERT(obj_s->i2c != (I2CName)NC); @@ -710,12 +712,11 @@ void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c){ /* Get object ptr based on handler ptr */ i2c_t *obj = get_i2c_obj(hi2c); struct i2c_s *obj_s = I2C_S(obj); - I2C_HandleTypeDef *handle = &(obj_s->handle); - /* Disable IT. Not always done before calling macro */ - __HAL_I2C_DISABLE_IT(handle, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + /* re-init IP to try and get back in a working state */ + i2c_init(obj, obj_s->sda, obj_s->scl); - /* Set event flag */ + /* Keep Set event flag */ obj_s->event = I2C_EVENT_ERROR; }