mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
fix(lp-i2c): Fixed the generation of spurious I2C start with lp-i2c
This commit fixes an issue with LP I2C and RTC I2C where in the peripherals generated a spurious I2C start condition when initialized. This caused some sensors to not respond properly to the following read or write request. Closes https://github.com/espressif/esp-idf/issues/14043 Closes https://github.com/espressif/esp-idf/issues/11608
This commit is contained in:
parent
17a18e8849
commit
2d331c0413
@ -45,9 +45,10 @@ static esp_err_t lp_i2c_gpio_is_cfg_valid(gpio_num_t sda_io_num, gpio_num_t scl_
|
||||
|
||||
static esp_err_t lp_i2c_configure_io(gpio_num_t io_num, bool pullup_en)
|
||||
{
|
||||
/* 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. */
|
||||
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);
|
||||
/* Initialize IO Pin */
|
||||
ESP_RETURN_ON_ERROR(rtc_gpio_init(io_num), LPI2C_TAG, "LP GPIO Init failed for GPIO %d", io_num);
|
||||
|
||||
/* Set direction to input+output open-drain mode */
|
||||
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);
|
||||
/* 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)
|
||||
/* Verify that the LP I2C GPIOs are valid */
|
||||
ESP_RETURN_ON_ERROR(lp_i2c_gpio_is_cfg_valid(sda_io_num, scl_io_num), LPI2C_TAG, "LP I2C GPIO config invalid");
|
||||
|
||||
/* Initialize SDA Pin */
|
||||
ESP_RETURN_ON_ERROR(lp_i2c_configure_io(sda_io_num, sda_pullup_en), LPI2C_TAG, "LP I2C SDA pin config failed");
|
||||
// NOTE: We always initialize the SCL pin first, then the SDA pin.
|
||||
// This order of initialization is important to avoid any spurious
|
||||
// I2C start conditions on the bus.
|
||||
|
||||
/* Initialize SCL Pin */
|
||||
ESP_RETURN_ON_ERROR(lp_i2c_configure_io(scl_io_num, scl_pullup_en), LPI2C_TAG, "LP I2C SCL pin config failed");
|
||||
|
||||
/* Initialize SDA Pin */
|
||||
ESP_RETURN_ON_ERROR(lp_i2c_configure_io(sda_io_num, sda_pullup_en), LPI2C_TAG, "LP I2C SDA pin config failed");
|
||||
|
||||
/* Select LP I2C function for the SDA Pin */
|
||||
lp_io_dev->gpio[sda_io_num].mcu_sel = 1;
|
||||
|
||||
@ -103,7 +108,7 @@ static esp_err_t lp_i2c_config_clk(const lp_core_i2c_cfg_t *cfg)
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch the clock source fequency */
|
||||
/* Fetch the clock source frequency */
|
||||
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");
|
||||
|
||||
/* 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
|
||||
/* Initialize LP I2C HAL */
|
||||
i2c_hal_init(&i2c_hal, lp_i2c_num);
|
||||
|
||||
/* Clear any pending interrupts */
|
||||
i2c_ll_clear_intr_mask(i2c_hal.dev, UINT32_MAX);
|
||||
|
||||
/* Initialize LP I2C Master mode */
|
||||
i2c_hal_master_init(&i2c_hal);
|
||||
|
||||
|
@ -72,6 +72,8 @@ static esp_err_t i2c_gpio_is_cfg_valid(gpio_num_t sda_io_num, gpio_num_t scl_io_
|
||||
|
||||
static esp_err_t i2c_configure_io(gpio_num_t io_num, bool pullup_en)
|
||||
{
|
||||
/* 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. */
|
||||
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);
|
||||
/* Initialize IO Pin */
|
||||
ESP_RETURN_ON_ERROR(rtc_gpio_init(io_num), RTCI2C_TAG, "RTC GPIO Init failed for GPIO %d", io_num);
|
||||
/* Set direction to input+output */
|
||||
@ -98,12 +100,16 @@ static esp_err_t i2c_set_pin(const ulp_riscv_i2c_cfg_t *cfg)
|
||||
/* Verify that the I2C GPIOs are valid */
|
||||
ESP_RETURN_ON_ERROR(i2c_gpio_is_cfg_valid(sda_io_num, scl_io_num), RTCI2C_TAG, "RTC I2C GPIO config invalid");
|
||||
|
||||
/* Initialize SDA Pin */
|
||||
ESP_RETURN_ON_ERROR(i2c_configure_io(sda_io_num, sda_pullup_en), RTCI2C_TAG, "RTC I2C SDA pin config failed");
|
||||
// NOTE: We always initialize the SCL pin first, then the SDA pin.
|
||||
// This order of initialization is important to avoid any spurious
|
||||
// I2C start conditions on the bus.
|
||||
|
||||
/* Initialize SCL Pin */
|
||||
ESP_RETURN_ON_ERROR(i2c_configure_io(scl_io_num, scl_pullup_en), RTCI2C_TAG, "RTC I2C SCL pin config failed");
|
||||
|
||||
/* Initialize SDA Pin */
|
||||
ESP_RETURN_ON_ERROR(i2c_configure_io(sda_io_num, sda_pullup_en), RTCI2C_TAG, "RTC I2C SDA pin config failed");
|
||||
|
||||
/* Route SDA IO signal to the RTC subsystem */
|
||||
rtc_io_dev->touch_pad[sda_io_num].mux_sel = 1;
|
||||
|
||||
@ -471,6 +477,12 @@ esp_err_t ulp_riscv_i2c_master_init(const ulp_riscv_i2c_cfg_t *cfg)
|
||||
WRITE_PERI_REG(RTC_I2C_CTRL_REG, 0);
|
||||
WRITE_PERI_REG(SENS_SAR_I2C_CTRL_REG, 0);
|
||||
|
||||
/* Verify that the input cfg param is valid */
|
||||
ESP_RETURN_ON_FALSE(cfg, ESP_ERR_INVALID_ARG, RTCI2C_TAG, "RTC I2C configuration is NULL");
|
||||
|
||||
/* Configure RTC I2C GPIOs */
|
||||
ESP_RETURN_ON_ERROR(i2c_set_pin(cfg), RTCI2C_TAG, "Failed to configure RTC I2C GPIOs");
|
||||
|
||||
/* Reset RTC I2C */
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
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)
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_PERI_RESET_CONF_REG, SENS_RTC_I2C_RESET);
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2
|
||||
|
||||
/* Verify that the input cfg param is valid */
|
||||
ESP_RETURN_ON_FALSE(cfg, ESP_ERR_INVALID_ARG, RTCI2C_TAG, "RTC I2C configuration is NULL");
|
||||
|
||||
/* Configure RTC I2C GPIOs */
|
||||
ESP_RETURN_ON_ERROR(i2c_set_pin(cfg), RTCI2C_TAG, "Failed to configure RTC I2C GPIOs");
|
||||
|
||||
/* Enable internal open-drain mode for SDA and SCL lines */
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
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)
|
||||
/* Configure RTC I2C timing parameters */
|
||||
ESP_RETURN_ON_ERROR(i2c_set_timing(cfg), RTCI2C_TAG, "Failed to configure RTC I2C timing");
|
||||
|
||||
/* Clear any pending interrupts */
|
||||
WRITE_PERI_REG(RTC_I2C_INT_CLR_REG, UINT32_MAX);
|
||||
|
||||
/* Enable RTC I2C interrupts */
|
||||
SET_PERI_REG_MASK(RTC_I2C_INT_ENA_REG, RTC_I2C_RX_DATA_INT_ENA |
|
||||
RTC_I2C_TX_DATA_INT_ENA |
|
||||
|
Loading…
Reference in New Issue
Block a user