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 f65ed09e5668..cc5fccbeee0d 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)) { 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; }