Skip to content

Commit 96293d2

Browse files
committed
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.
1 parent 532d5f2 commit 96293d2

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)