diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 970e12599ca..289f74ce755 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -2141,7 +2141,10 @@ pub(crate) mod asynch { use super::*; - pub struct DmaTxFuture<'a, TX> { + pub struct DmaTxFuture<'a, TX> + where + TX: Tx, + { pub(crate) tx: &'a mut TX, _a: (), } @@ -2151,8 +2154,6 @@ pub(crate) mod asynch { TX: Tx, { pub fn new(tx: &'a mut TX) -> Self { - tx.listen_eof(); - tx.listen_out_descriptor_error(); Self { tx, _a: () } } @@ -2172,18 +2173,34 @@ pub(crate) mod asynch { cx: &mut core::task::Context<'_>, ) -> Poll { TX::waker().register(cx.waker()); - if self.tx.is_listening_eof() { - Poll::Pending + if self.tx.is_done() { + self.tx.clear_interrupts(); + Poll::Ready(Ok(())) } else if self.tx.has_error() { self.tx.clear_interrupts(); Poll::Ready(Err(DmaError::DescriptorError)) } else { - Poll::Ready(Ok(())) + self.tx.listen_eof(); + self.tx.listen_out_descriptor_error(); + Poll::Pending } } } - pub struct DmaRxFuture<'a, RX> { + impl<'a, TX> Drop for DmaTxFuture<'a, TX> + where + TX: Tx, + { + fn drop(&mut self) { + self.tx.unlisten_eof(); + self.tx.unlisten_out_descriptor_error(); + } + } + + pub struct DmaRxFuture<'a, RX> + where + RX: Rx, + { pub(crate) rx: &'a mut RX, _a: (), } @@ -2193,10 +2210,6 @@ pub(crate) mod asynch { RX: Rx, { pub fn new(rx: &'a mut RX) -> Self { - rx.listen_eof(); - rx.listen_in_descriptor_error(); - rx.listen_in_descriptor_error_dscr_empty(); - rx.listen_in_descriptor_error_err_eof(); Self { rx, _a: () } } @@ -2216,8 +2229,9 @@ pub(crate) mod asynch { cx: &mut core::task::Context<'_>, ) -> Poll { RX::waker().register(cx.waker()); - if self.rx.is_listening_eof() { - Poll::Pending + if self.rx.is_done() { + self.rx.clear_interrupts(); + Poll::Ready(Ok(())) } else if self.rx.has_error() || self.rx.has_dscr_empty_error() || self.rx.has_eof_error() @@ -2225,13 +2239,32 @@ pub(crate) mod asynch { self.rx.clear_interrupts(); Poll::Ready(Err(DmaError::DescriptorError)) } else { - Poll::Ready(Ok(())) + self.rx.listen_eof(); + self.rx.listen_in_descriptor_error(); + self.rx.listen_in_descriptor_error_dscr_empty(); + self.rx.listen_in_descriptor_error_err_eof(); + Poll::Pending } } } + impl<'a, RX> Drop for DmaRxFuture<'a, RX> + where + RX: Rx, + { + fn drop(&mut self) { + self.rx.unlisten_eof(); + self.rx.unlisten_in_descriptor_error(); + self.rx.unlisten_in_descriptor_error_dscr_empty(); + self.rx.unlisten_in_descriptor_error_err_eof(); + } + } + #[cfg(any(i2s0, i2s1))] - pub struct DmaTxDoneChFuture<'a, TX> { + pub struct DmaTxDoneChFuture<'a, TX> + where + TX: Tx, + { pub(crate) tx: &'a mut TX, _a: (), } @@ -2242,8 +2275,6 @@ pub(crate) mod asynch { TX: Tx, { pub fn new(tx: &'a mut TX) -> Self { - tx.listen_ch_out_done(); - tx.listen_out_descriptor_error(); Self { tx, _a: () } } } @@ -2260,19 +2291,36 @@ pub(crate) mod asynch { cx: &mut core::task::Context<'_>, ) -> Poll { TX::waker().register(cx.waker()); - if self.tx.is_listening_ch_out_done() { - Poll::Pending + if self.tx.is_ch_out_done_set() { + self.tx.clear_ch_out_done(); + Poll::Ready(Ok(())) } else if self.tx.has_error() { self.tx.clear_interrupts(); Poll::Ready(Err(DmaError::DescriptorError)) } else { - Poll::Ready(Ok(())) + self.tx.listen_ch_out_done(); + self.tx.listen_out_descriptor_error(); + Poll::Pending } } } #[cfg(any(i2s0, i2s1))] - pub struct DmaRxDoneChFuture<'a, RX> { + impl<'a, TX> Drop for DmaTxDoneChFuture<'a, TX> + where + TX: Tx, + { + fn drop(&mut self) { + self.tx.unlisten_ch_out_done(); + self.tx.unlisten_out_descriptor_error(); + } + } + + #[cfg(any(i2s0, i2s1))] + pub struct DmaRxDoneChFuture<'a, RX> + where + RX: Rx, + { pub(crate) rx: &'a mut RX, _a: (), } @@ -2283,10 +2331,6 @@ pub(crate) mod asynch { RX: Rx, { pub fn new(rx: &'a mut RX) -> Self { - rx.listen_ch_in_done(); - rx.listen_in_descriptor_error(); - rx.listen_in_descriptor_error_dscr_empty(); - rx.listen_in_descriptor_error_err_eof(); Self { rx, _a: () } } } @@ -2303,8 +2347,9 @@ pub(crate) mod asynch { cx: &mut core::task::Context<'_>, ) -> Poll { RX::waker().register(cx.waker()); - if self.rx.is_listening_ch_in_done() { - Poll::Pending + if self.rx.is_ch_in_done_set() { + self.rx.clear_ch_in_done(); + Poll::Ready(Ok(())) } else if self.rx.has_error() || self.rx.has_dscr_empty_error() || self.rx.has_eof_error() @@ -2312,11 +2357,28 @@ pub(crate) mod asynch { self.rx.clear_interrupts(); Poll::Ready(Err(DmaError::DescriptorError)) } else { - Poll::Ready(Ok(())) + self.rx.listen_ch_in_done(); + self.rx.listen_in_descriptor_error(); + self.rx.listen_in_descriptor_error_dscr_empty(); + self.rx.listen_in_descriptor_error_err_eof(); + Poll::Pending } } } + #[cfg(any(i2s0, i2s1))] + impl<'a, RX> Drop for DmaRxDoneChFuture<'a, RX> + where + RX: Rx, + { + fn drop(&mut self) { + self.rx.unlisten_ch_in_done(); + self.rx.unlisten_in_descriptor_error(); + self.rx.unlisten_in_descriptor_error_dscr_empty(); + self.rx.unlisten_in_descriptor_error_err_eof(); + } + } + fn handle_interrupt, Tx: TxChannel>() { if Channel::has_in_descriptor_error() || Channel::has_in_descriptor_error_dscr_empty() @@ -2338,25 +2400,21 @@ pub(crate) mod asynch { } if Channel::is_in_done() && Channel::is_listening_in_eof() { - Channel::clear_in_interrupts(); Channel::unlisten_in_eof(); Rx::waker().wake() } if Channel::is_ch_in_done_set() { - Channel::clear_ch_in_done(); Channel::unlisten_ch_in_done(); Rx::waker().wake() } if Channel::is_out_done() && Channel::is_listening_out_eof() { - Channel::clear_out_interrupts(); Channel::unlisten_out_eof(); Tx::waker().wake() } if Channel::is_ch_out_done_set() { - Channel::clear_ch_out_done(); Channel::unlisten_ch_out_done(); Tx::waker().wake() }