fix(i2c_master): Add i2c master timeout range check

Closes https://github.com/espressif/esp-idf/issues/17930
This commit is contained in:
Chen Chen
2025-12-01 11:53:42 +08:00
parent b389ca9ada
commit 8ad7d769aa
11 changed files with 37 additions and 0 deletions

View File

@@ -5,6 +5,7 @@
*/
#include <string.h>
#include <inttypes.h>
#include <sys/param.h>
#include <sys/lock.h>
#include "sdkconfig.h"
@@ -606,6 +607,16 @@ static void s_i2c_send_command_async(i2c_master_bus_handle_t i2c_master, BaseTyp
i2c_hal_master_trans_start(hal);
}
static inline bool s_i2c_timeout_range_check(uint32_t *timeout_us, uint32_t sclk_clock_hz)
{
uint32_t max_timeout_us = (I2C_LL_MAX_TIMEOUT_PERIOD * 1000000ULL) / sclk_clock_hz;
if (*timeout_us > max_timeout_us) {
*timeout_us = max_timeout_us;
return true;
}
return false;
}
static esp_err_t s_i2c_transaction_start(i2c_master_dev_handle_t i2c_dev, int xfer_timeout_ms)
{
i2c_master_bus_handle_t i2c_master = i2c_dev->master_bus;
@@ -634,6 +645,7 @@ static esp_err_t s_i2c_transaction_start(i2c_master_dev_handle_t i2c_dev, int xf
}
// Set the timeout value
bool timeout_range_exceeded = s_i2c_timeout_range_check(&i2c_dev->scl_wait_us, i2c_master->base->clk_src_freq_hz);
i2c_hal_master_set_scl_timeout_val(hal, i2c_dev->scl_wait_us, i2c_master->base->clk_src_freq_hz);
i2c_ll_master_set_fractional_divider(hal->dev, 0, 0);
@@ -643,6 +655,11 @@ static esp_err_t s_i2c_transaction_start(i2c_master_dev_handle_t i2c_dev, int xf
i2c_ll_rxfifo_rst(hal->dev);
i2c_ll_enable_intr_mask(hal->dev, I2C_LL_MASTER_EVENT_INTR);
portEXIT_CRITICAL(&i2c_master->base->spinlock);
if (timeout_range_exceeded) {
ESP_LOGW(TAG, "Timeout value exceeds the maximum supported value, rounded down to maximum supported value: %" PRIu32 " us", i2c_dev->scl_wait_us);
}
if (i2c_master->async_trans == true) {
s_i2c_send_command_async(i2c_master, NULL);
} else {

View File

@@ -890,6 +890,8 @@ static inline i2c_slave_read_write_status_t i2c_ll_slave_get_read_write_status(i
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
// I2C max timeout period in clock cycles
#define I2C_LL_MAX_TIMEOUT_PERIOD (I2C_LL_MAX_TIMEOUT)
#define I2C_LL_INTR_MASK (0xffff) /*!< I2C all interrupt bitmap */

View File

@@ -815,6 +815,8 @@ static inline uint32_t i2c_ll_calculate_timeout_us_to_reg_val(uint32_t src_clk_h
#define I2C_LL_MASTER_RX_INT (I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE
// I2C max timeout period in clock cycles
#define I2C_LL_MAX_TIMEOUT_PERIOD (1UL << I2C_LL_MAX_TIMEOUT)
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */

View File

@@ -1000,6 +1000,8 @@ static inline i2c_slave_read_write_status_t i2c_ll_slave_get_read_write_status(i
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
// I2C max timeout period in clock cycles
#define I2C_LL_MAX_TIMEOUT_PERIOD (1UL << I2C_LL_MAX_TIMEOUT)
#define I2C_LL_INTR_MASK (0xffff) /*!< I2C all interrupt bitmap */

View File

@@ -1038,6 +1038,8 @@ static inline i2c_slave_read_write_status_t i2c_ll_slave_get_read_write_status(i
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE
// I2C max timeout period in clock cycles
#define I2C_LL_MAX_TIMEOUT_PERIOD (1UL << I2C_LL_MAX_TIMEOUT)
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */

View File

@@ -1040,6 +1040,8 @@ static inline i2c_slave_read_write_status_t i2c_ll_slave_get_read_write_status(i
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE
// I2C max timeout period in clock cycles
#define I2C_LL_MAX_TIMEOUT_PERIOD (1UL << I2C_LL_MAX_TIMEOUT)
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */

View File

@@ -951,6 +951,8 @@ static inline i2c_slave_read_write_status_t i2c_ll_slave_get_read_write_status(i
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE
// I2C max timeout period in clock cycles
#define I2C_LL_MAX_TIMEOUT_PERIOD (1UL << I2C_LL_MAX_TIMEOUT)
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */

View File

@@ -948,6 +948,8 @@ static inline i2c_slave_read_write_status_t i2c_ll_slave_get_read_write_status(i
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE
// I2C max timeout period in clock cycles
#define I2C_LL_MAX_TIMEOUT_PERIOD (1UL << I2C_LL_MAX_TIMEOUT)
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */

View File

@@ -1071,6 +1071,8 @@ static inline i2c_slave_read_write_status_t i2c_ll_slave_get_read_write_status(i
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE
// I2C max timeout period in clock cycles
#define I2C_LL_MAX_TIMEOUT_PERIOD (1UL << I2C_LL_MAX_TIMEOUT)
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */

View File

@@ -956,6 +956,8 @@ static inline i2c_slave_read_write_status_t i2c_ll_slave_get_read_write_status(i
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
// I2C max timeout period in clock cycles
#define I2C_LL_MAX_TIMEOUT_PERIOD (I2C_LL_MAX_TIMEOUT)
#define I2C_LL_INTR_MASK (0x1ffff) /*!< I2C all interrupt bitmap */

View File

@@ -1004,6 +1004,8 @@ static inline i2c_slave_read_write_status_t i2c_ll_slave_get_read_write_status(i
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
// I2C max timeout value
#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_VALUE_V
// I2C max timeout period in clock cycles
#define I2C_LL_MAX_TIMEOUT_PERIOD (1UL << I2C_LL_MAX_TIMEOUT)
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */