Merge branch 'fix/enhance_i2c_slave_test_stability_v5.4' into 'release/v5.4'

fix(i2c): Fix i2c read from fifo issue when enabling bt/wifi/uart, etc... (backport v5.4)

See merge request espressif/esp-idf!35434
This commit is contained in:
Michael (XIAO Xufeng) 2024-12-12 11:16:24 +08:00
commit 944329fff4
9 changed files with 81 additions and 7 deletions

View File

@ -169,7 +169,11 @@ esp_err_t i2c_acquire_bus_handle(i2c_port_num_t port_num, i2c_bus_handle_t *i2c_
break;
}
}
ESP_RETURN_ON_FALSE((bus_found == true), ESP_ERR_NOT_FOUND, TAG, "acquire bus failed, no free bus");
if (bus_found == false) {
ESP_LOGE(TAG, "acquire bus failed, no free bus");
_lock_release(&s_i2c_platform.mutex);
return ESP_ERR_NOT_FOUND;
}
} else {
ret = s_i2c_bus_handle_acquire(port_num, i2c_new_bus, mode);
if (ret != ESP_OK) {

View File

@ -785,8 +785,12 @@ static esp_err_t i2c_master_bus_destroy(i2c_master_bus_handle_t bus_handle)
{
ESP_RETURN_ON_FALSE(bus_handle, ESP_ERR_INVALID_ARG, TAG, "no memory for i2c master bus");
i2c_master_bus_handle_t i2c_master = bus_handle;
i2c_common_deinit_pins(i2c_master->base);
if (i2c_release_bus_handle(i2c_master->base) == ESP_OK) {
esp_err_t err = ESP_OK;
if (i2c_master->base) {
i2c_common_deinit_pins(i2c_master->base);
err = i2c_release_bus_handle(i2c_master->base);
}
if (err == ESP_OK) {
if (i2c_master) {
if (i2c_master->bus_lock_mux) {
vSemaphoreDeleteWithCaps(i2c_master->bus_lock_mux);
@ -962,6 +966,19 @@ esp_err_t i2c_new_master_bus(const i2c_master_bus_config_t *bus_config, i2c_mast
}
#if SOC_LP_I2C_SUPPORTED
else {
soc_periph_lp_i2c_clk_src_t clk_srcs[] = SOC_LP_I2C_CLKS;
bool lp_clock_match = false;
for (int i = 0; i < sizeof(clk_srcs) / sizeof(clk_srcs[0]); i++) {
if ((int)clk_srcs[i] == (int)i2c_master->base->clk_src) {
/* Clock source matches. Override the source clock type with the user configured value */
lp_clock_match = true;
break;
}
}
ESP_GOTO_ON_FALSE(lp_clock_match, ESP_ERR_NOT_SUPPORTED, err, TAG, "the clock source does not support lp i2c, please check");
LP_I2C_SRC_CLK_ATOMIC() {
lp_i2c_ll_set_source_clk(hal->dev, i2c_master->base->clk_src);
}

View File

@ -104,7 +104,7 @@ IRAM_ATTR static bool i2c_slave_handle_rx_fifo(i2c_slave_dev_t *i2c_slave, uint3
i2c_slave->rx_data_count += len;
}
}
xSemaphoreTakeFromISR(i2c_slave->operation_mux, &xTaskWoken);
xSemaphoreGiveFromISR(i2c_slave->operation_mux, &xTaskWoken);
return xTaskWoken;
}

View File

@ -146,6 +146,41 @@ TEST_CASE("I2C device add & remove check", "[i2c]")
TEST_ESP_OK(i2c_del_master_bus(bus_handle));
}
TEST_CASE("I2C peripheral allocate all", "[i2c]")
{
i2c_master_bus_handle_t bus_handle[SOC_HP_I2C_NUM];
for (int i = 0; i < SOC_HP_I2C_NUM; i++) {
i2c_master_bus_config_t i2c_mst_config_1 = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = -1,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
};
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config_1, &bus_handle[i]));
}
i2c_master_bus_config_t i2c_mst_config_1 = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = -1,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle_2;
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2c_new_master_bus(&i2c_mst_config_1, &bus_handle_2));
for (int i = 0; i < SOC_HP_I2C_NUM; i++) {
TEST_ESP_OK(i2c_del_master_bus(bus_handle[i]));
}
// Get another one
TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config_1, &bus_handle_2));
TEST_ESP_OK(i2c_del_master_bus(bus_handle_2));
}
TEST_CASE("I2C master probe device test", "[i2c]")
{
// 0x22,33,44,55 does not exist on the I2C bus, so it's expected to return `not found` error

View File

@ -74,6 +74,7 @@ static void i2c_slave_read_test_v2(void)
.slave_addr = ESP_SLAVE_ADDR,
.send_buf_depth = DATA_LENGTH,
.receive_buf_depth = DATA_LENGTH,
.flags.enable_internal_pullup = true,
};
TEST_ESP_OK(i2c_new_slave_device(&i2c_slv_config, &handle));
@ -200,6 +201,7 @@ static void slave_write_buffer_test_v2(void)
.slave_addr = ESP_SLAVE_ADDR,
.send_buf_depth = DATA_LENGTH,
.receive_buf_depth = DATA_LENGTH,
.flags.enable_internal_pullup = true,
};
TEST_ESP_OK(i2c_new_slave_device(&i2c_slv_config, &handle));

View File

@ -64,6 +64,20 @@ TEST_CASE("LP I2C initialize with wrong IO", "[i2c]")
#endif
TEST_CASE("LP I2C initialize with wrong clock source", "[i2c]")
{
i2c_master_bus_config_t i2c_mst_config = {
.lp_source_clk = I2C_CLK_SRC_DEFAULT,
.i2c_port = LP_I2C_NUM_0,
.scl_io_num = LP_I2C_SCL_IO,
.sda_io_num = LP_I2C_SDA_IO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, i2c_new_master_bus(&i2c_mst_config, &bus_handle));
}
static IRAM_ATTR bool test_i2c_rx_done_callback(i2c_slave_dev_handle_t channel, const i2c_slave_rx_done_event_data_t *edata, void *user_data)
{
BaseType_t high_task_wakeup = pdFALSE;

View File

@ -575,7 +575,9 @@ __attribute__((always_inline))
static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
{
for(int i = 0; i < len; i++) {
ptr[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->fifo_data, data);
// Known issue that hardware read fifo will cause data lose, (fifo pointer jump over a random address)
// use `DPORT_REG_READ` can avoid this issue.
ptr[i] = DPORT_REG_READ((uint32_t)&hw->fifo_data);
}
}

View File

@ -400,7 +400,7 @@ Please note that no STOP condition bit is inserted between the write and read op
};
i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(I2C_PORT_NUM_0, &dev_cfg, &dev_handle));
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
uint8_t buf[20] = {0x20};
uint8_t buffer[2];
ESP_ERROR_CHECK(i2c_master_transmit_receive(dev_handle, buf, sizeof(buf), buffer, 2, -1));

View File

@ -401,7 +401,7 @@ I2C 主机写入后读取
};
i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(I2C_PORT_NUM_0, &dev_cfg, &dev_handle));
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
uint8_t buf[20] = {0x20};
uint8_t buffer[2];
ESP_ERROR_CHECK(i2c_master_transmit_receive(dev_handle, buf, sizeof(buf), buffer, 2, -1));