diff --git a/esp-hal/src/i2s/master.rs b/esp-hal/src/i2s/master.rs index 2e8ac6d1402..72033c60d98 100644 --- a/esp-hal/src/i2s/master.rs +++ b/esp-hal/src/i2s/master.rs @@ -115,11 +115,12 @@ use enumset::{EnumSet, EnumSetType}; use private::*; +#[allow(unused_imports)] +use crate::RegisterToggle; use crate::{ Async, Blocking, DriverMode, - RegisterToggle, dma::{ Channel, ChannelRx, @@ -1672,12 +1673,20 @@ mod private { } fn reset_tx(&self) { - self.regs().conf().toggle(|w, bit| { - w.tx_reset().bit(bit); - w.tx_fifo_reset().bit(bit) - }); + // Assert resets, read back as a bus barrier, then deassert. + // A bare toggle() (back-to-back set+clear) is too fast for the + // ESP32 I2S hardware — the peripheral does not register the + // reset pulse, causing tx_start() to hang on the next transfer. + self.regs() + .conf() + .modify(|_, w| w.tx_reset().set_bit().tx_fifo_reset().set_bit()); + self.regs().lc_conf().modify(|_, w| w.out_rst().set_bit()); + let _ = self.regs().conf().read(); - self.regs().lc_conf().toggle(|w, bit| w.out_rst().bit(bit)); + self.regs() + .conf() + .modify(|_, w| w.tx_reset().clear_bit().tx_fifo_reset().clear_bit()); + self.regs().lc_conf().modify(|_, w| w.out_rst().clear_bit()); self.regs().int_clr().write(|w| { w.out_done().clear_bit_by_one(); @@ -1706,12 +1715,16 @@ mod private { } fn reset_rx(&self) { - self.regs().conf().toggle(|w, bit| { - w.rx_reset().bit(bit); - w.rx_fifo_reset().bit(bit) - }); + self.regs() + .conf() + .modify(|_, w| w.rx_reset().set_bit().rx_fifo_reset().set_bit()); + self.regs().lc_conf().modify(|_, w| w.in_rst().set_bit()); + let _ = self.regs().conf().read(); - self.regs().lc_conf().toggle(|w, bit| w.in_rst().bit(bit)); + self.regs() + .conf() + .modify(|_, w| w.rx_reset().clear_bit().rx_fifo_reset().clear_bit()); + self.regs().lc_conf().modify(|_, w| w.in_rst().clear_bit()); self.regs().int_clr().write(|w| { w.in_done().clear_bit_by_one();