diff --git a/components/driver/i2c.c b/components/driver/i2c.c index 164b9e9e6a..21360658a4 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1439,7 +1439,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]; - portTickType ticks_start = xTaskGetTickCount(); + const portTickType ticks_start = xTaskGetTickCount(); portBASE_TYPE res = xSemaphoreTake(p_i2c->cmd_mux, ticks_to_wait); if (res == pdFALSE) { return ESP_ERR_TIMEOUT; @@ -1479,13 +1479,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.