From 1ea5682617c5d3a85da930c5fc99ec8b7e0e69f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eckhard=20V=C3=B6llm?= <34288016+iltis42@users.noreply.github.com> Date: Sun, 13 Jun 2021 22:19:37 +0200 Subject: [PATCH 1/2] Update i2c.c Fix issue with single bus clear counter but two I2C buses (I2C0, I2C1). The previously implemented single (static) counter would impact the second bus either if one bus has counter expiry. Merges https://github.com/espressif/esp-idf/pull/7144 --- components/driver/i2c.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/components/driver/i2c.c b/components/driver/i2c.c index c67b3521ee..f9410e5b21 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -1472,6 +1472,8 @@ static bool is_cmd_link_buffer_internal(const i2c_cmd_link_t *link) } #endif +static uint8_t clear_bus_cnt[2] = { 0, 0 }; + esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait) { ESP_RETURN_ON_FALSE(( i2c_num < I2C_NUM_MAX ), ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR); @@ -1489,7 +1491,6 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, } #endif // Sometimes when the FSM get stuck, the ACK_ERR interrupt will occur endlessly until we reset the FSM and clear bus. - static uint8_t clear_bus_cnt = 0; esp_err_t ret = ESP_FAIL; i2c_obj_t *p_i2c = p_i2c_obj[i2c_num]; TickType_t ticks_start = xTaskGetTickCount(); @@ -1504,7 +1505,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, if (p_i2c->status == I2C_STATUS_TIMEOUT || i2c_hal_is_bus_busy(&(i2c_context[i2c_num].hal))) { i2c_hw_fsm_reset(i2c_num); - clear_bus_cnt = 0; + clear_bus_cnt[i2c_num] = 0; } i2c_reset_tx_fifo(i2c_num); i2c_reset_rx_fifo(i2c_num); @@ -1550,12 +1551,12 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example, // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case. i2c_hw_fsm_reset(i2c_num); - clear_bus_cnt = 0; + clear_bus_cnt[i2c_num] = 0; ret = ESP_ERR_TIMEOUT; } else if (p_i2c->status == I2C_STATUS_ACK_ERROR) { - clear_bus_cnt++; - if (clear_bus_cnt >= I2C_ACKERR_CNT_MAX) { - clear_bus_cnt = 0; + clear_bus_cnt[i2c_num]++; + if (clear_bus_cnt[i2c_num] >= I2C_ACKERR_CNT_MAX) { + clear_bus_cnt[i2c_num] = 0; } ret = ESP_FAIL; } else { @@ -1570,7 +1571,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, // If the I2C slave are powered off or the SDA/SCL are connected to ground, for example, // I2C hw FSM would get stuck in wrong state, we have to reset the I2C module in this case. i2c_hw_fsm_reset(i2c_num); - clear_bus_cnt = 0; + clear_bus_cnt[i2c_num] = 0; break; } } From 4ef2ba26f98f423805bbb63a3ca6a8eb6ab5deb4 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Mon, 18 Jul 2022 19:24:37 +0800 Subject: [PATCH 2/2] I2C: Fix the reset counter --- components/driver/i2c.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/driver/i2c.c b/components/driver/i2c.c index f9410e5b21..78b779858a 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -1472,7 +1472,7 @@ static bool is_cmd_link_buffer_internal(const i2c_cmd_link_t *link) } #endif -static uint8_t clear_bus_cnt[2] = { 0, 0 }; +static uint8_t clear_bus_cnt[I2C_NUM_MAX] = { 0 }; esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait) { @@ -1557,6 +1557,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, clear_bus_cnt[i2c_num]++; if (clear_bus_cnt[i2c_num] >= I2C_ACKERR_CNT_MAX) { clear_bus_cnt[i2c_num] = 0; + i2c_hw_fsm_reset(i2c_num); } ret = ESP_FAIL; } else {