mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-03 22:08:28 +00:00 
			
		
		
		
	fix(i2c): Enhance lp clock source and avoid deadlock,
Closes https://github.com/espressif/esp-idf/issues/14908, Closes https://github.com/espressif/esp-idf/issues/14906
This commit is contained in:
		@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -962,6 +962,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);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user