From 96293d2ec4a093771e26ca42b78c97f1f6b7eaa5 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 9 Sep 2024 13:31:45 +0300 Subject: [PATCH] fix(i2c): Ensure that semaphore is properly given if init fails 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. --- cores/esp32/esp32-hal-i2c.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/cores/esp32/esp32-hal-i2c.c b/cores/esp32/esp32-hal-i2c.c index 1ecef5bfb0d..419ce66bb9b 100644 --- a/cores/esp32/esp32-hal-i2c.c +++ b/cores/esp32/esp32-hal-i2c.c @@ -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; } @@ -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) { @@ -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); @@ -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 { @@ -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);