diff --git a/CHANGELOG.md b/CHANGELOG.md index deb4aa5c0..a08d01f00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed the multicore critical section on Xtensa (#1175) - Fix timer `now` for esp32c3 and esp32c6 (#1178) - Wait for registers to get synced before reading the timer count for all chips (#1183) +- Fix I2C error handling (#1184) ### Changed diff --git a/esp-hal/src/i2c.rs b/esp-hal/src/i2c.rs index eaf2300c9..f0526656f 100644 --- a/esp-hal/src/i2c.rs +++ b/esp-hal/src/i2c.rs @@ -697,11 +697,14 @@ pub trait Instance { /// Resets the I2C controller (FIFO + FSM + command list) fn reset(&self) { - // Reset interrupts - // Disable all I2C interrupts + // Reset the FSM + // (the option to reset the FSM is not available + // for the ESP32) + #[cfg(not(esp32))] self.register_block() - .int_ena() - .write(|w| unsafe { w.bits(0) }); + .ctr() + .modify(|_, w| w.fsm_rst().set_bit()); + // Clear all I2C interrupts self.register_block() .int_clr() @@ -712,14 +715,6 @@ pub trait Instance { // Reset the command list self.reset_command_list(); - - // Reset the FSM - // (the option to reset the FSM is not available - // for the ESP32) - #[cfg(not(esp32))] - self.register_block() - .ctr() - .modify(|_, w| w.fsm_rst().set_bit()); } /// Resets the I2C peripheral's command registers @@ -1317,6 +1312,9 @@ pub trait Instance { } else if interrupts.arbitration_lost_int_raw().bit_is_set() { self.reset(); return Err(Error::ArbitrationLost); + } else if interrupts.trans_complete_int_raw().bit_is_set() && self.register_block().sr().read().resp_rec().bit_is_clear() { + self.reset(); + return Err(Error::AckCheckFailed); } } }