Skip to content

Commit 2c4ce95

Browse files
authored
fix(i2c): Ensure that semaphore is properly given if init fails (#10313)
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.
1 parent ef23d52 commit 2c4ce95

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

cores/esp32/esp32-hal-i2c.c

+12-4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ bool i2cIsInit(uint8_t i2c_num) {
7171
}
7272

7373
esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
74+
esp_err_t ret = ESP_OK;
7475
if (i2c_num >= SOC_I2C_NUM) {
7576
return ESP_ERR_INVALID_ARG;
7677
}
@@ -90,7 +91,8 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
9091
#endif
9192
if (bus[i2c_num].initialized) {
9293
log_e("bus is already initialized");
93-
return ESP_FAIL;
94+
ret = ESP_FAIL;
95+
goto init_fail;
9496
}
9597

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

105107
if (!perimanClearPinBus(sda) || !perimanClearPinBus(scl)) {
106-
return false;
108+
ret = ESP_FAIL;
109+
goto init_fail;
107110
}
108111

109112
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) {
117120
conf.master.clk_speed = frequency;
118121
conf.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL; //Any one clock source that is available for the specified frequency may be chosen
119122

120-
esp_err_t ret = i2c_param_config((i2c_port_t)i2c_num, &conf);
123+
ret = i2c_param_config((i2c_port_t)i2c_num, &conf);
121124
if (ret != ESP_OK) {
122125
log_e("i2c_param_config failed");
123126
} else {
@@ -133,11 +136,16 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
133136
i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT);
134137
if (!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER_SDA, (void *)(i2c_num + 1), i2c_num, -1)
135138
|| !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER_SCL, (void *)(i2c_num + 1), i2c_num, -1)) {
139+
#if !CONFIG_DISABLE_HAL_LOCKS
140+
//release lock so that i2cDetachBus can execute i2cDeinit
141+
xSemaphoreGive(bus[i2c_num].lock);
142+
#endif
136143
i2cDetachBus((void *)(i2c_num + 1));
137-
return false;
144+
return ESP_FAIL;
138145
}
139146
}
140147
}
148+
init_fail:
141149
#if !CONFIG_DISABLE_HAL_LOCKS
142150
//release lock
143151
xSemaphoreGive(bus[i2c_num].lock);

0 commit comments

Comments
 (0)