From 8e53a4a5dff0938b9538e76f1540a41e03916df0 Mon Sep 17 00:00:00 2001 From: Abanoub Salah Date: Fri, 29 May 2026 09:06:54 +0300 Subject: [PATCH] fix(ulp_riscv): Prioritize error bits over data flags in I2C interrupt wait --- .../ulp/ulp_riscv/ulp_core/ulp_riscv_i2c.c | 21 ++++++++------- components/ulp/ulp_riscv/ulp_riscv_i2c.c | 26 ++++++++++--------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/components/ulp/ulp_riscv/ulp_core/ulp_riscv_i2c.c b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_i2c.c index f65ed09e566..330ab2eeaac 100644 --- a/components/ulp/ulp_riscv/ulp_core/ulp_riscv_i2c.c +++ b/components/ulp/ulp_riscv/ulp_core/ulp_riscv_i2c.c @@ -75,21 +75,24 @@ static inline int32_t ulp_riscv_i2c_wait_for_interrupt(int32_t cycles_to_wait) while (1) { status = READ_PERI_REG(RTC_I2C_INT_ST_REG); - /* Return 0 if Tx or Rx data interrupt bits are set. */ - if ((status & RTC_I2C_TX_DATA_INT_ST) || - (status & RTC_I2C_RX_DATA_INT_ST)) { - return 0; - /* In case of error status, break and return -1 */ + /* If a NAK, Timeout, or Arbitration Loss occurs, abort immediately. */ #if CONFIG_IDF_TARGET_ESP32S2 - } else if ((status & RTC_I2C_TIMEOUT_INT_ST) || + if ((status & RTC_I2C_TIMEOUT_INT_ST) || #elif CONFIG_IDF_TARGET_ESP32S3 - } else if ((status & RTC_I2C_TIME_OUT_INT_ST) || + if ((status & RTC_I2C_TIME_OUT_INT_ST) || #endif // CONFIG_IDF_TARGET_ESP32S2 - (status & RTC_I2C_ACK_ERR_INT_ST) || - (status & RTC_I2C_ARBITRATION_LOST_INT_ST)) { + (status & RTC_I2C_ACK_ERR_INT_ST) || + (status & RTC_I2C_ARBITRATION_LOST_INT_ST)) { return -1; } + /* Return 0 ONLY if hardware channels are error-free and data bits are latched. */ + if ((status & RTC_I2C_TX_DATA_INT_ST) || + (status & RTC_I2C_RX_DATA_INT_ST)) { + return 0; + } + + /* Handle CPU clock-cycle tracking */ if (ulp_riscv_is_timeout_elapsed(timeout_start, cycles_to_wait)) { return -1; } diff --git a/components/ulp/ulp_riscv/ulp_riscv_i2c.c b/components/ulp/ulp_riscv/ulp_riscv_i2c.c index 62a4075b680..ba148f51045 100644 --- a/components/ulp/ulp_riscv/ulp_riscv_i2c.c +++ b/components/ulp/ulp_riscv/ulp_riscv_i2c.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -254,21 +254,23 @@ static inline esp_err_t ulp_riscv_i2c_wait_for_interrupt(int32_t ticks_to_wait) while (1) { status = READ_PERI_REG(RTC_I2C_INT_ST_REG); - /* Return ESP_OK if Tx or Rx data interrupt bits are set. */ + /* If a NAK, Timeout, or Arbitration Loss occurs, abort immediately. */ +#if CONFIG_IDF_TARGET_ESP32S2 + if ((status & RTC_I2C_TIMEOUT_INT_ST) || +#elif CONFIG_IDF_TARGET_ESP32S3 + if ((status & RTC_I2C_TIME_OUT_INT_ST) || +#endif // CONFIG_IDF_TARGET_ESP32S2 + (status & RTC_I2C_ACK_ERR_INT_ST) || + (status & RTC_I2C_ARBITRATION_LOST_INT_ST)) { + ret = ESP_FAIL; + break; + } + + /* Return ESP_OK only if hardware channels are error-free and data bits are latched. */ if ((status & RTC_I2C_TX_DATA_INT_ST) || (status & RTC_I2C_RX_DATA_INT_ST)) { ret = ESP_OK; break; - /* In case of error status, break and return ESP_FAIL */ -#if CONFIG_IDF_TARGET_ESP32S2 - } else if ((status & RTC_I2C_TIMEOUT_INT_ST) || -#elif CONFIG_IDF_TARGET_ESP32S3 - } else if ((status & RTC_I2C_TIME_OUT_INT_ST) || -#endif // CONFIG_IDF_TARGET_ESP32S2 - (status & RTC_I2C_ACK_ERR_INT_ST) || - (status & RTC_I2C_ARBITRATION_LOST_INT_ST)) { - ret = ESP_FAIL; - break; } if ((uint32_t)ticks_to_wait != (uint32_t) -1) {