From 793ca6d7a48120722e848f408e363345ee63fd09 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Mon, 28 Aug 2023 17:57:26 +0800 Subject: [PATCH] fix(i2c): fix issues related to timeout and alive interval tick Fixes https://github.com/espressif/esp-idf/issues/4999 Former usage of I2C_CMD_ALIVE_INTERVAL_TICK macro overrode the ticks_to_wait parameter when the latter was too big --- components/driver/i2c/i2c.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/components/driver/i2c/i2c.c b/components/driver/i2c/i2c.c index fc46628fa45..4f76cd31d5a 100644 --- a/components/driver/i2c/i2c.c +++ b/components/driver/i2c/i2c.c @@ -1526,7 +1526,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, // Sometimes when the FSM get stuck, the ACK_ERR interrupt will occur endlessly until we reset the FSM and clear bus. esp_err_t ret = ESP_FAIL; i2c_obj_t *p_i2c = p_i2c_obj[i2c_num]; - TickType_t ticks_start = xTaskGetTickCount(); + const TickType_t ticks_start = xTaskGetTickCount(); BaseType_t res = xSemaphoreTake(p_i2c->cmd_mux, ticks_to_wait); if (res == pdFALSE) { return ESP_ERR_TIMEOUT; @@ -1566,13 +1566,15 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, i2c_cmd_evt_t evt; while (1) { TickType_t wait_time = xTaskGetTickCount(); - if (wait_time - ticks_start > ticks_to_wait) { // out of time - wait_time = I2C_CMD_ALIVE_INTERVAL_TICK; + const TickType_t elapsed = wait_time - ticks_start; + if (elapsed >= ticks_to_wait) { // out of time + /* Before triggering a timeout, empty the queue by giving a wait_time of 0: + * - if the queue is empty, `pdFALSE` will be returned and the loop will be exited + * - if the queue is not empty, we will pop an element and come back here again + */ + wait_time = 0; } else { - wait_time = ticks_to_wait - (wait_time - ticks_start); - if (wait_time < I2C_CMD_ALIVE_INTERVAL_TICK) { - wait_time = I2C_CMD_ALIVE_INTERVAL_TICK; - } + wait_time = MIN(ticks_to_wait - elapsed, I2C_CMD_ALIVE_INTERVAL_TICK); } // In master mode, since we don't have an interrupt to detective bus error or FSM state, what we do here is to make // sure the interrupt mechanism for master mode is still working.