Skip to content

Commit 021c03c

Browse files
committed
Merge branch 'fix/lp_i2c_generates_spurious_start_cond_v5.2' into 'release/v5.2'
fix(lp-i2c): Fixed the generation of spurious I2C start with lp-i2c (v5.2) See merge request espressif/esp-idf!32108
2 parents aea64d1 + 2d331c0 commit 021c03c

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

components/ulp/lp_core/lp_core_i2c.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@ static esp_err_t lp_i2c_gpio_is_cfg_valid(gpio_num_t sda_io_num, gpio_num_t scl_
4545

4646
static esp_err_t lp_i2c_configure_io(gpio_num_t io_num, bool pullup_en)
4747
{
48+
/* Set the IO pin to high to avoid them from toggling from Low to High state during initialization. This can register a spurious I2C start condition. */
49+
ESP_RETURN_ON_ERROR(rtc_gpio_set_level(io_num, 1), LPI2C_TAG, "LP GPIO failed to set level to high for %d", io_num);
4850
/* Initialize IO Pin */
4951
ESP_RETURN_ON_ERROR(rtc_gpio_init(io_num), LPI2C_TAG, "LP GPIO Init failed for GPIO %d", io_num);
50-
5152
/* Set direction to input+output open-drain mode */
5253
ESP_RETURN_ON_ERROR(rtc_gpio_set_direction(io_num, RTC_GPIO_MODE_INPUT_OUTPUT_OD), LPI2C_TAG, "LP GPIO Set direction failed for %d", io_num);
5354
/* Disable pulldown on the io pin */
@@ -72,12 +73,16 @@ static esp_err_t lp_i2c_set_pin(const lp_core_i2c_cfg_t *cfg)
7273
/* Verify that the LP I2C GPIOs are valid */
7374
ESP_RETURN_ON_ERROR(lp_i2c_gpio_is_cfg_valid(sda_io_num, scl_io_num), LPI2C_TAG, "LP I2C GPIO config invalid");
7475

75-
/* Initialize SDA Pin */
76-
ESP_RETURN_ON_ERROR(lp_i2c_configure_io(sda_io_num, sda_pullup_en), LPI2C_TAG, "LP I2C SDA pin config failed");
76+
// NOTE: We always initialize the SCL pin first, then the SDA pin.
77+
// This order of initialization is important to avoid any spurious
78+
// I2C start conditions on the bus.
7779

7880
/* Initialize SCL Pin */
7981
ESP_RETURN_ON_ERROR(lp_i2c_configure_io(scl_io_num, scl_pullup_en), LPI2C_TAG, "LP I2C SCL pin config failed");
8082

83+
/* Initialize SDA Pin */
84+
ESP_RETURN_ON_ERROR(lp_i2c_configure_io(sda_io_num, sda_pullup_en), LPI2C_TAG, "LP I2C SDA pin config failed");
85+
8186
/* Select LP I2C function for the SDA Pin */
8287
lp_io_dev->gpio[sda_io_num].mcu_sel = 1;
8388

@@ -103,7 +108,7 @@ static esp_err_t lp_i2c_config_clk(const lp_core_i2c_cfg_t *cfg)
103108
}
104109
}
105110

106-
/* Fetch the clock source fequency */
111+
/* Fetch the clock source frequency */
107112
ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(source_clk, ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, &source_freq), LPI2C_TAG, "Invalid LP I2C source clock selected");
108113

109114
/* Verify that the I2C_SCLK operates at a frequency 20 times larger than the requested SCL bus frequency */
@@ -141,6 +146,9 @@ esp_err_t lp_core_i2c_master_init(i2c_port_t lp_i2c_num, const lp_core_i2c_cfg_t
141146
/* Initialize LP I2C HAL */
142147
i2c_hal_init(&i2c_hal, lp_i2c_num);
143148

149+
/* Clear any pending interrupts */
150+
i2c_ll_clear_intr_mask(i2c_hal.dev, UINT32_MAX);
151+
144152
/* Initialize LP I2C Master mode */
145153
i2c_hal_master_init(&i2c_hal);
146154

components/ulp/ulp_riscv/ulp_riscv_i2c.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ static esp_err_t i2c_gpio_is_cfg_valid(gpio_num_t sda_io_num, gpio_num_t scl_io_
7272

7373
static esp_err_t i2c_configure_io(gpio_num_t io_num, bool pullup_en)
7474
{
75+
/* Set the IO pin to high to avoid them from toggling from Low to High state during initialization. This can register a spurious I2C start condition. */
76+
ESP_RETURN_ON_ERROR(rtc_gpio_set_level(io_num, 1), RTCI2C_TAG, "RTC GPIO failed to set level to high for %d", io_num);
7577
/* Initialize IO Pin */
7678
ESP_RETURN_ON_ERROR(rtc_gpio_init(io_num), RTCI2C_TAG, "RTC GPIO Init failed for GPIO %d", io_num);
7779
/* Set direction to input+output */
@@ -98,12 +100,16 @@ static esp_err_t i2c_set_pin(const ulp_riscv_i2c_cfg_t *cfg)
98100
/* Verify that the I2C GPIOs are valid */
99101
ESP_RETURN_ON_ERROR(i2c_gpio_is_cfg_valid(sda_io_num, scl_io_num), RTCI2C_TAG, "RTC I2C GPIO config invalid");
100102

101-
/* Initialize SDA Pin */
102-
ESP_RETURN_ON_ERROR(i2c_configure_io(sda_io_num, sda_pullup_en), RTCI2C_TAG, "RTC I2C SDA pin config failed");
103+
// NOTE: We always initialize the SCL pin first, then the SDA pin.
104+
// This order of initialization is important to avoid any spurious
105+
// I2C start conditions on the bus.
103106

104107
/* Initialize SCL Pin */
105108
ESP_RETURN_ON_ERROR(i2c_configure_io(scl_io_num, scl_pullup_en), RTCI2C_TAG, "RTC I2C SCL pin config failed");
106109

110+
/* Initialize SDA Pin */
111+
ESP_RETURN_ON_ERROR(i2c_configure_io(sda_io_num, sda_pullup_en), RTCI2C_TAG, "RTC I2C SDA pin config failed");
112+
107113
/* Route SDA IO signal to the RTC subsystem */
108114
rtc_io_dev->touch_pad[sda_io_num].mux_sel = 1;
109115

@@ -471,6 +477,12 @@ esp_err_t ulp_riscv_i2c_master_init(const ulp_riscv_i2c_cfg_t *cfg)
471477
WRITE_PERI_REG(RTC_I2C_CTRL_REG, 0);
472478
WRITE_PERI_REG(SENS_SAR_I2C_CTRL_REG, 0);
473479

480+
/* Verify that the input cfg param is valid */
481+
ESP_RETURN_ON_FALSE(cfg, ESP_ERR_INVALID_ARG, RTCI2C_TAG, "RTC I2C configuration is NULL");
482+
483+
/* Configure RTC I2C GPIOs */
484+
ESP_RETURN_ON_ERROR(i2c_set_pin(cfg), RTCI2C_TAG, "Failed to configure RTC I2C GPIOs");
485+
474486
/* Reset RTC I2C */
475487
#if CONFIG_IDF_TARGET_ESP32S2
476488
i2c_dev->ctrl.i2c_reset = 1;
@@ -484,12 +496,6 @@ esp_err_t ulp_riscv_i2c_master_init(const ulp_riscv_i2c_cfg_t *cfg)
484496
CLEAR_PERI_REG_MASK(SENS_SAR_PERI_RESET_CONF_REG, SENS_RTC_I2C_RESET);
485497
#endif // CONFIG_IDF_TARGET_ESP32S2
486498

487-
/* Verify that the input cfg param is valid */
488-
ESP_RETURN_ON_FALSE(cfg, ESP_ERR_INVALID_ARG, RTCI2C_TAG, "RTC I2C configuration is NULL");
489-
490-
/* Configure RTC I2C GPIOs */
491-
ESP_RETURN_ON_ERROR(i2c_set_pin(cfg), RTCI2C_TAG, "Failed to configure RTC I2C GPIOs");
492-
493499
/* Enable internal open-drain mode for SDA and SCL lines */
494500
#if CONFIG_IDF_TARGET_ESP32S2
495501
i2c_dev->ctrl.sda_force_out = 0;
@@ -519,6 +525,9 @@ esp_err_t ulp_riscv_i2c_master_init(const ulp_riscv_i2c_cfg_t *cfg)
519525
/* Configure RTC I2C timing parameters */
520526
ESP_RETURN_ON_ERROR(i2c_set_timing(cfg), RTCI2C_TAG, "Failed to configure RTC I2C timing");
521527

528+
/* Clear any pending interrupts */
529+
WRITE_PERI_REG(RTC_I2C_INT_CLR_REG, UINT32_MAX);
530+
522531
/* Enable RTC I2C interrupts */
523532
SET_PERI_REG_MASK(RTC_I2C_INT_ENA_REG, RTC_I2C_RX_DATA_INT_ENA |
524533
RTC_I2C_TX_DATA_INT_ENA |

0 commit comments

Comments
 (0)