From c373763022789729003ee814acb01cb682a039e1 Mon Sep 17 00:00:00 2001 From: Chen Chen Date: Mon, 1 Dec 2025 11:53:42 +0800 Subject: [PATCH] fix(i2c_master): Add i2c master timeout range check Closes https://github.com/espressif/esp-idf/issues/17930 --- components/esp_driver_i2c/i2c_master.c | 17 +++++++++++++++++ .../esp_hal_i2c/esp32/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32c2/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32c3/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32c5/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32c6/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32c61/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32h2/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32h21/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32h4/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32p4/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32s2/include/hal/i2c_ll.h | 2 ++ .../esp_hal_i2c/esp32s3/include/hal/i2c_ll.h | 2 ++ 13 files changed, 41 insertions(+) diff --git a/components/esp_driver_i2c/i2c_master.c b/components/esp_driver_i2c/i2c_master.c index 5151384b07f..c4787a91b7c 100644 --- a/components/esp_driver_i2c/i2c_master.c +++ b/components/esp_driver_i2c/i2c_master.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include "esp_rom_sys.h" @@ -665,6 +666,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; @@ -695,6 +706,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); @@ -704,6 +716,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 { diff --git a/components/esp_hal_i2c/esp32/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32/include/hal/i2c_ll.h index 564bd1f7997..1a6f6022d6a 100644 --- a/components/esp_hal_i2c/esp32/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32/include/hal/i2c_ll.h @@ -889,6 +889,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 */ diff --git a/components/esp_hal_i2c/esp32c2/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32c2/include/hal/i2c_ll.h index b2a20de0bc8..6389d327ef4 100644 --- a/components/esp_hal_i2c/esp32c2/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32c2/include/hal/i2c_ll.h @@ -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 */ diff --git a/components/esp_hal_i2c/esp32c3/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32c3/include/hal/i2c_ll.h index 6bb29f24b2e..288937f247a 100644 --- a/components/esp_hal_i2c/esp32c3/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32c3/include/hal/i2c_ll.h @@ -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 */ diff --git a/components/esp_hal_i2c/esp32c5/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32c5/include/hal/i2c_ll.h index 9e583ad05c5..801b244ea8b 100644 --- a/components/esp_hal_i2c/esp32c5/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32c5/include/hal/i2c_ll.h @@ -1048,6 +1048,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 */ diff --git a/components/esp_hal_i2c/esp32c6/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32c6/include/hal/i2c_ll.h index 70feb45eea6..b66a7c520c3 100644 --- a/components/esp_hal_i2c/esp32c6/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32c6/include/hal/i2c_ll.h @@ -1049,6 +1049,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 */ diff --git a/components/esp_hal_i2c/esp32c61/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32c61/include/hal/i2c_ll.h index 0f23e2f418d..b9770a08665 100644 --- a/components/esp_hal_i2c/esp32c61/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32c61/include/hal/i2c_ll.h @@ -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 */ diff --git a/components/esp_hal_i2c/esp32h2/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32h2/include/hal/i2c_ll.h index 51689ac1c98..2df0618d753 100644 --- a/components/esp_hal_i2c/esp32h2/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32h2/include/hal/i2c_ll.h @@ -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 */ diff --git a/components/esp_hal_i2c/esp32h21/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32h21/include/hal/i2c_ll.h index 9d98296b303..fc84118a9d8 100644 --- a/components/esp_hal_i2c/esp32h21/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32h21/include/hal/i2c_ll.h @@ -946,6 +946,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 */ diff --git a/components/esp_hal_i2c/esp32h4/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32h4/include/hal/i2c_ll.h index 47bea5c9700..f3270a54b2e 100644 --- a/components/esp_hal_i2c/esp32h4/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32h4/include/hal/i2c_ll.h @@ -1019,6 +1019,8 @@ static inline void i2c_ll_get_scl_clk_timing(i2c_dev_t *hw, int *high_period, in #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 */ diff --git a/components/esp_hal_i2c/esp32p4/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32p4/include/hal/i2c_ll.h index 403ef151197..31d0f346a90 100644 --- a/components/esp_hal_i2c/esp32p4/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32p4/include/hal/i2c_ll.h @@ -1080,6 +1080,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 */ diff --git a/components/esp_hal_i2c/esp32s2/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32s2/include/hal/i2c_ll.h index 28831bc8a82..0c04f2a5aa4 100644 --- a/components/esp_hal_i2c/esp32s2/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32s2/include/hal/i2c_ll.h @@ -954,6 +954,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 */ diff --git a/components/esp_hal_i2c/esp32s3/include/hal/i2c_ll.h b/components/esp_hal_i2c/esp32s3/include/hal/i2c_ll.h index 20ccff5a198..f866133fb47 100644 --- a/components/esp_hal_i2c/esp32s3/include/hal/i2c_ll.h +++ b/components/esp_hal_i2c/esp32s3/include/hal/i2c_ll.h @@ -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 */