Skip to content

Commit 9a91765

Browse files
committed
Merge branch 'fix/i2c_race_condition' into 'master'
fix(i2c_master): Fix i2c master race condition issue Closes IDFGH-14704 See merge request espressif/esp-idf!37355
2 parents b504d61 + 90d477c commit 9a91765

File tree

1 file changed

+7
-7
lines changed

1 file changed

+7
-7
lines changed

components/esp_driver_i2c/i2c_master.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ static bool s_i2c_read_command(i2c_master_bus_handle_t i2c_master, i2c_operation
331331
i2c_ll_master_write_cmd_reg(hal->dev, hw_cmd, i2c_master->cmd_idx);
332332
i2c_ll_master_write_cmd_reg(hal->dev, hw_end_cmd, i2c_master->cmd_idx + 1);
333333
portEXIT_CRITICAL_SAFE(&handle->spinlock);
334-
i2c_master->status = I2C_STATUS_READ;
334+
atomic_store(&i2c_master->status, I2C_STATUS_READ);
335335
portENTER_CRITICAL_SAFE(&handle->spinlock);
336336
if (i2c_master->async_trans == false) {
337337
i2c_hal_master_trans_start(hal);
@@ -472,15 +472,15 @@ static void s_i2c_send_commands(i2c_master_bus_handle_t i2c_master, TickType_t t
472472
while (i2c_master->i2c_trans.cmd_count) {
473473
if (xSemaphoreTake(i2c_master->cmd_semphr, ticks_to_wait) != pdTRUE) {
474474
// Software timeout, clear the command link and finish this transaction.
475+
atomic_store(&i2c_master->status, I2C_STATUS_TIMEOUT);
475476
i2c_master->cmd_idx = 0;
476477
i2c_master->trans_idx = 0;
477-
atomic_store(&i2c_master->status, I2C_STATUS_TIMEOUT);
478478
ESP_LOGE(TAG, "I2C software timeout");
479479
xSemaphoreGive(i2c_master->cmd_semphr);
480480
return;
481481
}
482482

483-
if (i2c_master->status == I2C_STATUS_TIMEOUT) {
483+
if (atomic_load(&i2c_master->status) == I2C_STATUS_TIMEOUT) {
484484
s_i2c_hw_fsm_reset(i2c_master);
485485
i2c_master->cmd_idx = 0;
486486
i2c_master->trans_idx = 0;
@@ -489,7 +489,7 @@ static void s_i2c_send_commands(i2c_master_bus_handle_t i2c_master, TickType_t t
489489
return;
490490
}
491491

492-
if (i2c_master->status == I2C_STATUS_ACK_ERROR) {
492+
if (atomic_load(&i2c_master->status) == I2C_STATUS_ACK_ERROR) {
493493
ESP_LOGE(TAG, "I2C hardware NACK detected");
494494
const i2c_ll_hw_cmd_t hw_stop_cmd = {
495495
.op_code = I2C_LL_CMD_STOP,
@@ -596,7 +596,7 @@ static esp_err_t s_i2c_transaction_start(i2c_master_dev_handle_t i2c_dev, int xf
596596
TickType_t ticks_to_wait = (xfer_timeout_ms == -1) ? portMAX_DELAY : pdMS_TO_TICKS(xfer_timeout_ms);
597597
// Sometimes when the FSM get stuck, the ACK_ERR interrupt will occur endlessly until we reset the FSM and clear bus.
598598
esp_err_t ret = ESP_OK;
599-
if (i2c_master->status == I2C_STATUS_TIMEOUT || i2c_ll_is_bus_busy(hal->dev)) {
599+
if (atomic_load(&i2c_master->status) == I2C_STATUS_TIMEOUT || i2c_ll_is_bus_busy(hal->dev)) {
600600
ESP_RETURN_ON_ERROR(s_i2c_hw_fsm_reset(i2c_master), TAG, "reset hardware failed");
601601
}
602602

@@ -630,7 +630,7 @@ static esp_err_t s_i2c_transaction_start(i2c_master_dev_handle_t i2c_dev, int xf
630630
} else {
631631
s_i2c_send_commands(i2c_master, ticks_to_wait);
632632
// Wait event bits
633-
if (i2c_master->status != I2C_STATUS_DONE) {
633+
if (atomic_load(&i2c_master->status) != I2C_STATUS_DONE) {
634634
ret = ESP_ERR_INVALID_STATE;
635635
}
636636
// Interrupt can be disabled when on transaction finishes.
@@ -650,7 +650,7 @@ I2C_MASTER_ISR_ATTR static void i2c_isr_receive_handler(i2c_master_bus_t *i2c_ma
650650
{
651651
i2c_hal_context_t *hal = &i2c_master->base->hal;
652652

653-
if (i2c_master->status == I2C_STATUS_READ) {
653+
if (atomic_load(&i2c_master->status) == I2C_STATUS_READ) {
654654
i2c_operation_t *i2c_operation = &i2c_master->i2c_trans.ops[i2c_master->trans_idx];
655655
portENTER_CRITICAL_ISR(&i2c_master->base->spinlock);
656656
i2c_ll_read_rxfifo(hal->dev, i2c_operation->data + i2c_operation->bytes_used, i2c_master->rx_cnt);

0 commit comments

Comments
 (0)