Skip to content

Commit

Permalink
fix(i2c): Ensure that semaphore is properly given if init fails (#10313)
Browse files Browse the repository at this point in the history
Currently code can return before semaphore is given, which can cause the bus to lock. Change makes sure that it's properly given in case of failure.
  • Loading branch information
me-no-dev authored Sep 10, 2024
1 parent ef23d52 commit 2c4ce95
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions cores/esp32/esp32-hal-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ bool i2cIsInit(uint8_t i2c_num) {
}

esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
esp_err_t ret = ESP_OK;
if (i2c_num >= SOC_I2C_NUM) {
return ESP_ERR_INVALID_ARG;
}
Expand All @@ -90,7 +91,8 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
#endif
if (bus[i2c_num].initialized) {
log_e("bus is already initialized");
return ESP_FAIL;
ret = ESP_FAIL;
goto init_fail;
}

if (!frequency) {
Expand All @@ -103,7 +105,8 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SCL, i2cDetachBus);

if (!perimanClearPinBus(sda) || !perimanClearPinBus(scl)) {
return false;
ret = ESP_FAIL;
goto init_fail;
}

log_i("Initializing I2C Master: sda=%d scl=%d freq=%d", sda, scl, frequency);
Expand All @@ -117,7 +120,7 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
conf.master.clk_speed = frequency;
conf.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL; //Any one clock source that is available for the specified frequency may be chosen

esp_err_t ret = i2c_param_config((i2c_port_t)i2c_num, &conf);
ret = i2c_param_config((i2c_port_t)i2c_num, &conf);
if (ret != ESP_OK) {
log_e("i2c_param_config failed");
} else {
Expand All @@ -133,11 +136,16 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT);
if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER_SDA, (void *)(i2c_num + 1), i2c_num, -1)
|| !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER_SCL, (void *)(i2c_num + 1), i2c_num, -1)) {
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock so that i2cDetachBus can execute i2cDeinit
xSemaphoreGive(bus[i2c_num].lock);
#endif
i2cDetachBus((void *)(i2c_num + 1));
return false;
return ESP_FAIL;
}
}
}
init_fail:
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(bus[i2c_num].lock);
Expand Down

0 comments on commit 2c4ce95

Please sign in to comment.