diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index d5a9d3ee6..30439e6bf 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -243,8 +243,6 @@ pub mod dma { DmaRxBuffer, DmaTxBuffer, PeripheralDmaChannel, - Rx, - Tx, }, peripherals::AES, Blocking, diff --git a/esp-hal/src/dma/m2m.rs b/esp-hal/src/dma/m2m.rs index 07139b120..ad265716c 100644 --- a/esp-hal/src/dma/m2m.rs +++ b/esp-hal/src/dma/m2m.rs @@ -23,8 +23,6 @@ use crate::{ DmaTxBuf, DmaTxBuffer, DmaTxInterrupt, - Rx, - Tx, }, Async, Blocking, diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 43c49c68a..1f6411818 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1324,9 +1324,10 @@ impl TxCircularState { } } - pub(crate) fn update(&mut self, channel: &T) -> Result<(), DmaError> + pub(crate) fn update(&mut self, channel: &ChannelTx) -> Result<(), DmaError> where - T: Tx, + Dm: DriverMode, + CH: DmaTxChannel, { if channel .pending_out_interrupts() @@ -1735,60 +1736,6 @@ where { } -/// The functions here are not meant to be used outside the HAL -#[doc(hidden)] -pub trait Rx: crate::private::Sealed { - unsafe fn prepare_transfer_without_start( - &mut self, - peri: DmaPeripheral, - chain: &DescriptorChain, - ) -> Result<(), DmaError>; - - unsafe fn prepare_transfer( - &mut self, - peri: DmaPeripheral, - buffer: &mut BUF, - ) -> Result<(), DmaError>; - - fn start_transfer(&mut self) -> Result<(), DmaError>; - - fn stop_transfer(&mut self); - - #[cfg(gdma)] - fn set_mem2mem_mode(&mut self, value: bool); - - fn listen_in(&self, interrupts: impl Into>); - - fn unlisten_in(&self, interrupts: impl Into>); - - fn is_listening_in(&self) -> EnumSet; - - fn clear_in(&self, interrupts: impl Into>); - - fn pending_in_interrupts(&self) -> EnumSet; - - fn is_done(&self) -> bool; - - fn has_error(&self) -> bool { - self.pending_in_interrupts() - .contains(DmaRxInterrupt::DescriptorError) - } - - fn has_dscr_empty_error(&self) -> bool { - self.pending_in_interrupts() - .contains(DmaRxInterrupt::DescriptorEmpty) - } - - fn has_eof_error(&self) -> bool { - self.pending_in_interrupts() - .contains(DmaRxInterrupt::ErrorEof) - } - - fn clear_interrupts(&self); - - fn waker(&self) -> &'static crate::asynch::AtomicWaker; -} - // NOTE(p4): because the P4 has two different GDMAs, we won't be able to use // `GenericPeripheralGuard`. cfg_if::cfg_if! { @@ -1940,14 +1887,15 @@ where { } -impl Rx for ChannelRx +#[allow(unused)] +impl ChannelRx where Dm: DriverMode, CH: DmaRxChannel, { // TODO: used by I2S, which should be rewritten to use the Preparation-based // API. - unsafe fn prepare_transfer_without_start( + pub(crate) unsafe fn prepare_transfer_without_start( &mut self, peri: DmaPeripheral, chain: &DescriptorChain, @@ -1992,7 +1940,7 @@ where self.do_prepare(preparation, peri) } - unsafe fn prepare_transfer( + pub(crate) unsafe fn prepare_transfer( &mut self, peri: DmaPeripheral, buffer: &mut BUF, @@ -2002,7 +1950,7 @@ where self.do_prepare(preparation, peri) } - fn start_transfer(&mut self) -> Result<(), DmaError> { + pub(crate) fn start_transfer(&mut self) -> Result<(), DmaError> { self.rx_impl.start(); if self @@ -2015,93 +1963,62 @@ where } } - fn stop_transfer(&mut self) { + pub(crate) fn stop_transfer(&mut self) { self.rx_impl.stop() } #[cfg(gdma)] - fn set_mem2mem_mode(&mut self, value: bool) { + pub(crate) fn set_mem2mem_mode(&mut self, value: bool) { self.rx_impl.set_mem2mem_mode(value); } - fn listen_in(&self, interrupts: impl Into>) { + pub(crate) fn listen_in(&self, interrupts: impl Into>) { self.rx_impl.listen(interrupts); } - fn unlisten_in(&self, interrupts: impl Into>) { + pub(crate) fn unlisten_in(&self, interrupts: impl Into>) { self.rx_impl.unlisten(interrupts); } - fn is_listening_in(&self) -> EnumSet { + pub(crate) fn is_listening_in(&self) -> EnumSet { self.rx_impl.is_listening() } - fn clear_in(&self, interrupts: impl Into>) { + pub(crate) fn clear_in(&self, interrupts: impl Into>) { self.rx_impl.clear(interrupts); } - fn pending_in_interrupts(&self) -> EnumSet { + pub(crate) fn pending_in_interrupts(&self) -> EnumSet { self.rx_impl.pending_interrupts() } - fn is_done(&self) -> bool { + pub(crate) fn is_done(&self) -> bool { self.pending_in_interrupts() .contains(DmaRxInterrupt::SuccessfulEof) } - fn clear_interrupts(&self) { + pub(crate) fn clear_interrupts(&self) { self.rx_impl.clear_all(); } - fn waker(&self) -> &'static crate::asynch::AtomicWaker { + pub(crate) fn waker(&self) -> &'static crate::asynch::AtomicWaker { self.rx_impl.waker() } -} -/// The functions here are not meant to be used outside the HAL -#[doc(hidden)] -pub trait Tx: crate::private::Sealed { - unsafe fn prepare_transfer_without_start( - &mut self, - peri: DmaPeripheral, - chain: &DescriptorChain, - ) -> Result<(), DmaError>; - - unsafe fn prepare_transfer( - &mut self, - peri: DmaPeripheral, - buffer: &mut BUF, - ) -> Result<(), DmaError>; - - fn listen_out(&self, interrupts: impl Into>); - - fn unlisten_out(&self, interrupts: impl Into>); - - fn is_listening_out(&self) -> EnumSet; - - fn clear_out(&self, interrupts: impl Into>); - - fn pending_out_interrupts(&self) -> EnumSet; - - fn start_transfer(&mut self) -> Result<(), DmaError>; - - fn stop_transfer(&mut self); - - fn is_done(&self) -> bool { - self.pending_out_interrupts() - .contains(DmaTxInterrupt::TotalEof) + pub(crate) fn has_error(&self) -> bool { + self.pending_in_interrupts() + .contains(DmaRxInterrupt::DescriptorError) } - fn has_error(&self) -> bool { - self.pending_out_interrupts() - .contains(DmaTxInterrupt::DescriptorError) + pub(crate) fn has_dscr_empty_error(&self) -> bool { + self.pending_in_interrupts() + .contains(DmaRxInterrupt::DescriptorEmpty) } - fn clear_interrupts(&self); - - fn waker(&self) -> &'static crate::asynch::AtomicWaker; - - fn last_out_dscr_address(&self) -> usize; + pub(crate) fn has_eof_error(&self) -> bool { + self.pending_in_interrupts() + .contains(DmaRxInterrupt::ErrorEof) + } } /// DMA transmit channel @@ -2235,14 +2152,15 @@ where { } -impl Tx for ChannelTx +#[allow(unused)] +impl ChannelTx where Dm: DriverMode, CH: DmaTxChannel, { // TODO: used by I2S, which should be rewritten to use the Preparation-based // API. - unsafe fn prepare_transfer_without_start( + pub(crate) unsafe fn prepare_transfer_without_start( &mut self, peri: DmaPeripheral, chain: &DescriptorChain, @@ -2291,7 +2209,7 @@ where Ok(()) } - unsafe fn prepare_transfer( + pub(crate) unsafe fn prepare_transfer( &mut self, peri: DmaPeripheral, buffer: &mut BUF, @@ -2301,7 +2219,7 @@ where self.do_prepare(preparation, peri) } - fn start_transfer(&mut self) -> Result<(), DmaError> { + pub(crate) fn start_transfer(&mut self) -> Result<(), DmaError> { self.tx_impl.start(); while self.tx_impl.is_fifo_empty() && self.pending_out_interrupts().is_empty() {} @@ -2315,41 +2233,51 @@ where } } - fn stop_transfer(&mut self) { + pub(crate) fn stop_transfer(&mut self) { self.tx_impl.stop() } - fn listen_out(&self, interrupts: impl Into>) { + pub(crate) fn listen_out(&self, interrupts: impl Into>) { self.tx_impl.listen(interrupts); } - fn unlisten_out(&self, interrupts: impl Into>) { + pub(crate) fn unlisten_out(&self, interrupts: impl Into>) { self.tx_impl.unlisten(interrupts); } - fn is_listening_out(&self) -> EnumSet { + pub(crate) fn is_listening_out(&self) -> EnumSet { self.tx_impl.is_listening() } - fn clear_out(&self, interrupts: impl Into>) { + pub(crate) fn clear_out(&self, interrupts: impl Into>) { self.tx_impl.clear(interrupts); } - fn pending_out_interrupts(&self) -> EnumSet { + pub(crate) fn pending_out_interrupts(&self) -> EnumSet { self.tx_impl.pending_interrupts() } - fn waker(&self) -> &'static crate::asynch::AtomicWaker { + pub(crate) fn waker(&self) -> &'static crate::asynch::AtomicWaker { self.tx_impl.waker() } - fn clear_interrupts(&self) { + pub(crate) fn clear_interrupts(&self) { self.tx_impl.clear_all(); } - fn last_out_dscr_address(&self) -> usize { + pub(crate) fn last_out_dscr_address(&self) -> usize { self.tx_impl.last_dscr_address() } + + pub(crate) fn is_done(&self) -> bool { + self.pending_out_interrupts() + .contains(DmaTxInterrupt::TotalEof) + } + + pub(crate) fn has_error(&self) -> bool { + self.pending_out_interrupts() + .contains(DmaTxInterrupt::DescriptorError) + } } #[doc(hidden)] @@ -2569,6 +2497,8 @@ pub(crate) mod dma_private { use super::*; pub trait DmaSupport { + type DriverMode: DriverMode; + /// Wait until the transfer is done. /// /// Depending on the peripheral this might include checking the DMA @@ -2587,17 +2517,17 @@ pub(crate) mod dma_private { } pub trait DmaSupportTx: DmaSupport { - type TX: Tx; + type Channel: DmaTxChannel; - fn tx(&mut self) -> &mut Self::TX; + fn tx(&mut self) -> &mut ChannelTx; fn chain(&mut self) -> &mut DescriptorChain; } pub trait DmaSupportRx: DmaSupport { - type RX: Rx; + type Channel: DmaRxChannel; - fn rx(&mut self) -> &mut Self::RX; + fn rx(&mut self) -> &mut ChannelRx; fn chain(&mut self) -> &mut DescriptorChain; } @@ -2906,26 +2836,26 @@ pub(crate) mod asynch { use super::*; #[must_use = "futures do nothing unless you `.await` or poll them"] - pub struct DmaTxFuture<'a, TX> + pub struct DmaTxFuture<'a, CH> where - TX: Tx, + CH: DmaTxChannel, { - pub(crate) tx: &'a mut TX, + pub(crate) tx: &'a mut ChannelTx, } - impl<'a, TX> DmaTxFuture<'a, TX> + impl<'a, CH> DmaTxFuture<'a, CH> where - TX: Tx, + CH: DmaTxChannel, { #[cfg_attr(esp32c2, allow(dead_code))] - pub fn new(tx: &'a mut TX) -> Self { + pub fn new(tx: &'a mut ChannelTx) -> Self { Self { tx } } } - impl core::future::Future for DmaTxFuture<'_, TX> + impl core::future::Future for DmaTxFuture<'_, CH> where - TX: Tx, + CH: DmaTxChannel, { type Output = Result<(), DmaError>; @@ -2952,9 +2882,9 @@ pub(crate) mod asynch { } } - impl Drop for DmaTxFuture<'_, TX> + impl Drop for DmaTxFuture<'_, CH> where - TX: Tx, + CH: DmaTxChannel, { fn drop(&mut self) { self.tx @@ -2963,25 +2893,25 @@ pub(crate) mod asynch { } #[must_use = "futures do nothing unless you `.await` or poll them"] - pub struct DmaRxFuture<'a, RX> + pub struct DmaRxFuture<'a, CH> where - RX: Rx, + CH: DmaRxChannel, { - pub(crate) rx: &'a mut RX, + pub(crate) rx: &'a mut ChannelRx, } - impl<'a, RX> DmaRxFuture<'a, RX> + impl<'a, CH> DmaRxFuture<'a, CH> where - RX: Rx, + CH: DmaRxChannel, { - pub fn new(rx: &'a mut RX) -> Self { + pub fn new(rx: &'a mut ChannelRx) -> Self { Self { rx } } } - impl core::future::Future for DmaRxFuture<'_, RX> + impl core::future::Future for DmaRxFuture<'_, CH> where - RX: Rx, + CH: DmaRxChannel, { type Output = Result<(), DmaError>; @@ -3012,9 +2942,9 @@ pub(crate) mod asynch { } } - impl Drop for DmaRxFuture<'_, RX> + impl Drop for DmaRxFuture<'_, CH> where - RX: Rx, + CH: DmaRxChannel, { fn drop(&mut self) { self.rx.unlisten_in( @@ -3026,28 +2956,28 @@ pub(crate) mod asynch { } #[cfg(any(i2s0, i2s1))] - pub struct DmaTxDoneChFuture<'a, TX> + pub struct DmaTxDoneChFuture<'a, CH> where - TX: Tx, + CH: DmaTxChannel, { - pub(crate) tx: &'a mut TX, + pub(crate) tx: &'a mut ChannelTx, _a: (), } #[cfg(any(i2s0, i2s1))] - impl<'a, TX> DmaTxDoneChFuture<'a, TX> + impl<'a, CH> DmaTxDoneChFuture<'a, CH> where - TX: Tx, + CH: DmaTxChannel, { - pub fn new(tx: &'a mut TX) -> Self { + pub fn new(tx: &'a mut ChannelTx) -> Self { Self { tx, _a: () } } } #[cfg(any(i2s0, i2s1))] - impl core::future::Future for DmaTxDoneChFuture<'_, TX> + impl core::future::Future for DmaTxDoneChFuture<'_, CH> where - TX: Tx, + CH: DmaTxChannel, { type Output = Result<(), DmaError>; @@ -3079,9 +3009,9 @@ pub(crate) mod asynch { } #[cfg(any(i2s0, i2s1))] - impl Drop for DmaTxDoneChFuture<'_, TX> + impl Drop for DmaTxDoneChFuture<'_, CH> where - TX: Tx, + CH: DmaTxChannel, { fn drop(&mut self) { self.tx @@ -3090,28 +3020,28 @@ pub(crate) mod asynch { } #[cfg(any(i2s0, i2s1))] - pub struct DmaRxDoneChFuture<'a, RX> + pub struct DmaRxDoneChFuture<'a, CH> where - RX: Rx, + CH: DmaRxChannel, { - pub(crate) rx: &'a mut RX, + pub(crate) rx: &'a mut ChannelRx, _a: (), } #[cfg(any(i2s0, i2s1))] - impl<'a, RX> DmaRxDoneChFuture<'a, RX> + impl<'a, CH> DmaRxDoneChFuture<'a, CH> where - RX: Rx, + CH: DmaRxChannel, { - pub fn new(rx: &'a mut RX) -> Self { + pub fn new(rx: &'a mut ChannelRx) -> Self { Self { rx, _a: () } } } #[cfg(any(i2s0, i2s1))] - impl core::future::Future for DmaRxDoneChFuture<'_, RX> + impl core::future::Future for DmaRxDoneChFuture<'_, CH> where - RX: Rx, + CH: DmaRxChannel, { type Output = Result<(), DmaError>; @@ -3147,9 +3077,9 @@ pub(crate) mod asynch { } #[cfg(any(i2s0, i2s1))] - impl Drop for DmaRxDoneChFuture<'_, RX> + impl Drop for DmaRxDoneChFuture<'_, CH> where - RX: Rx, + CH: DmaRxChannel, { fn drop(&mut self) { self.rx.unlisten_in( diff --git a/esp-hal/src/i2s/master.rs b/esp-hal/src/i2s/master.rs index 6ba510c32..62d4b0665 100644 --- a/esp-hal/src/i2s/master.rs +++ b/esp-hal/src/i2s/master.rs @@ -89,8 +89,6 @@ use crate::{ PeripheralRxChannel, PeripheralTxChannel, ReadBuffer, - Rx, - Tx, WriteBuffer, }, gpio::interconnect::PeripheralOutput, @@ -420,6 +418,8 @@ impl DmaSupport for I2sTx<'_, Dm> where Dm: DriverMode, { + type DriverMode = Dm; + fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { self.i2s.wait_for_tx_done(); } @@ -433,9 +433,9 @@ impl<'d, Dm> DmaSupportTx for I2sTx<'d, Dm> where Dm: DriverMode, { - type TX = ChannelTx>>; + type Channel = PeripheralTxChannel>; - fn tx(&mut self) -> &mut Self::TX { + fn tx(&mut self) -> &mut ChannelTx>> { &mut self.tx_channel } @@ -548,6 +548,8 @@ impl DmaSupport for I2sRx<'_, Dm> where Dm: DriverMode, { + type DriverMode = Dm; + fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { self.i2s.wait_for_rx_done(); } @@ -561,9 +563,9 @@ impl<'d, Dm> DmaSupportRx for I2sRx<'d, Dm> where Dm: DriverMode, { - type RX = ChannelRx>>; + type Channel = PeripheralRxChannel>; - fn rx(&mut self) -> &mut Self::RX { + fn rx(&mut self) -> &mut ChannelRx>> { &mut self.rx_channel } @@ -1784,9 +1786,7 @@ pub mod asynch { asynch::{DmaRxDoneChFuture, DmaRxFuture, DmaTxDoneChFuture, DmaTxFuture}, DmaEligible, ReadBuffer, - Rx, RxCircularState, - Tx, TxCircularState, WriteBuffer, }, diff --git a/esp-hal/src/i2s/parallel.rs b/esp-hal/src/i2s/parallel.rs index 5c9109a42..b530fe4b5 100644 --- a/esp-hal/src/i2s/parallel.rs +++ b/esp-hal/src/i2s/parallel.rs @@ -112,7 +112,6 @@ use crate::{ DmaError, DmaTxBuffer, PeripheralTxChannel, - Tx, }, gpio::{ interconnect::{OutputConnection, PeripheralOutput}, diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index 95f2aa951..3fc04bd21 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -62,7 +62,7 @@ use core::{ use crate::{ clock::Clocks, - dma::{ChannelRx, DmaError, DmaPeripheral, DmaRxBuffer, PeripheralRxChannel, Rx, RxChannelFor}, + dma::{ChannelRx, DmaError, DmaPeripheral, DmaRxBuffer, PeripheralRxChannel, RxChannelFor}, gpio::{ interconnect::{PeripheralInput, PeripheralOutput}, InputSignal, diff --git a/esp-hal/src/lcd_cam/lcd/dpi.rs b/esp-hal/src/lcd_cam/lcd/dpi.rs index 4e34accbb..48b3b9240 100644 --- a/esp-hal/src/lcd_cam/lcd/dpi.rs +++ b/esp-hal/src/lcd_cam/lcd/dpi.rs @@ -103,7 +103,7 @@ use core::{ use crate::{ clock::Clocks, - dma::{ChannelTx, DmaError, DmaPeripheral, DmaTxBuffer, PeripheralTxChannel, Tx, TxChannelFor}, + dma::{ChannelTx, DmaError, DmaPeripheral, DmaTxBuffer, PeripheralTxChannel, TxChannelFor}, gpio::{interconnect::PeripheralOutput, Level, OutputSignal}, lcd_cam::{ calculate_clkm, diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index bf60f46e4..3be1bb779 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -59,7 +59,7 @@ use core::{ use crate::{ clock::Clocks, - dma::{ChannelTx, DmaError, DmaPeripheral, DmaTxBuffer, PeripheralTxChannel, Tx, TxChannelFor}, + dma::{ChannelTx, DmaError, DmaPeripheral, DmaTxBuffer, PeripheralTxChannel, TxChannelFor}, gpio::{ interconnect::{OutputConnection, PeripheralOutput}, OutputSignal, diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 7e56f2d08..d9818b3cd 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -139,9 +139,7 @@ use crate::{ DmaTxBuffer, PeripheralRxChannel, PeripheralTxChannel, - Rx, RxChannelFor, - Tx, TxChannelFor, }, gpio::{ diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index b53cc167f..74b2ad5d8 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -48,7 +48,7 @@ use super::{BitOrder, DataMode, DmaError, Error, Mode}; use crate::{ asynch::AtomicWaker, clock::Clocks, - dma::{DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer, Rx, Tx}, + dma::{DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer}, gpio::{ interconnect::{PeripheralInput, PeripheralOutput}, InputSignal, @@ -1394,6 +1394,55 @@ mod dma { pins: self.pins, } } + + async fn wait_for_idle_async(&mut self) { + if self.rx_transfer_in_progress { + _ = DmaRxFuture::new(&mut self.channel.rx).await; + self.rx_transfer_in_progress = false; + } + + struct Fut(Driver); + impl Future for Fut { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + if self.0.interrupts().contains(SpiInterrupt::TransferDone) { + #[cfg(esp32)] + // Need to poll for done-ness even after interrupt fires. + if self.0.busy() { + cx.waker().wake_by_ref(); + return Poll::Pending; + } + + self.0.clear_interrupts(SpiInterrupt::TransferDone.into()); + return Poll::Ready(()); + } + + self.0.state.waker.register(cx.waker()); + self.0 + .enable_listen(SpiInterrupt::TransferDone.into(), true); + Poll::Pending + } + } + impl Drop for Fut { + fn drop(&mut self) { + self.0 + .enable_listen(SpiInterrupt::TransferDone.into(), false); + } + } + + if !self.is_done() { + Fut(self.driver()).await; + } + + if self.tx_transfer_in_progress { + // In case DMA TX buffer is bigger than what the SPI consumes, stop the DMA. + if !self.channel.tx.is_done() { + self.channel.tx.stop_transfer(); + } + self.tx_transfer_in_progress = false; + } + } } impl core::fmt::Debug for SpiDma<'_, Dm> @@ -1470,55 +1519,6 @@ mod dma { fence(Ordering::Acquire); } - async fn wait_for_idle_async(&mut self) { - if self.rx_transfer_in_progress { - _ = DmaRxFuture::new(&mut self.channel.rx).await; - self.rx_transfer_in_progress = false; - } - - struct Fut(Driver); - impl Future for Fut { - type Output = (); - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - if self.0.interrupts().contains(SpiInterrupt::TransferDone) { - #[cfg(esp32)] - // Need to poll for done-ness even after interrupt fires. - if self.0.busy() { - cx.waker().wake_by_ref(); - return Poll::Pending; - } - - self.0.clear_interrupts(SpiInterrupt::TransferDone.into()); - return Poll::Ready(()); - } - - self.0.state.waker.register(cx.waker()); - self.0 - .enable_listen(SpiInterrupt::TransferDone.into(), true); - Poll::Pending - } - } - impl Drop for Fut { - fn drop(&mut self) { - self.0 - .enable_listen(SpiInterrupt::TransferDone.into(), false); - } - } - - if !self.is_done() { - Fut(self.driver()).await; - } - - if self.tx_transfer_in_progress { - // In case DMA TX buffer is bigger than what the SPI consumes, stop the DMA. - if !self.channel.tx.is_done() { - self.channel.tx.stop_transfer(); - } - self.tx_transfer_in_progress = false; - } - } - /// # Safety: /// /// The caller must ensure to not access the buffer contents while the @@ -1545,8 +1545,7 @@ mod dma { bytes_to_write, rx_buffer, tx_buffer, - &mut self.channel.rx, - &mut self.channel.tx, + &mut self.channel, ) } } @@ -1591,8 +1590,7 @@ mod dma { bytes_to_write, &mut EmptyBuf, &mut self.address_buffer, - &mut self.channel.rx, - &mut self.channel.tx, + &mut self.channel, ) } } @@ -2748,15 +2746,14 @@ impl DmaDriver { #[allow(clippy::too_many_arguments)] #[cfg_attr(place_spi_driver_in_ram, ram)] - unsafe fn start_transfer_dma( + unsafe fn start_transfer_dma( &self, _full_duplex: bool, rx_len: usize, tx_len: usize, rx_buffer: &mut impl DmaRxBuffer, tx_buffer: &mut impl DmaTxBuffer, - rx: &mut RX, - tx: &mut TX, + channel: &mut Channel>>, ) -> Result<(), Error> { #[cfg(esp32s2)] { @@ -2775,8 +2772,10 @@ impl DmaDriver { self.enable_dma(); if rx_len > 0 { - rx.prepare_transfer(self.dma_peripheral, rx_buffer) - .and_then(|_| rx.start_transfer())?; + channel + .rx + .prepare_transfer(self.dma_peripheral, rx_buffer) + .and_then(|_| channel.rx.start_transfer())?; } else { #[cfg(esp32)] { @@ -2793,8 +2792,10 @@ impl DmaDriver { } } if tx_len > 0 { - tx.prepare_transfer(self.dma_peripheral, tx_buffer) - .and_then(|_| tx.start_transfer())?; + channel + .tx + .prepare_transfer(self.dma_peripheral, tx_buffer) + .and_then(|_| channel.tx.start_transfer())?; } #[cfg(gdma)] @@ -3849,6 +3850,8 @@ use core::{ task::{Context, Poll}, }; +use crate::dma::{Channel, PeripheralDmaChannel}; + impl Future for SpiFuture<'_> { type Output = (); diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index e59b246ff..f8eb95663 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -172,8 +172,6 @@ pub mod dma { DmaTxBuffer, EmptyBuf, PeripheralDmaChannel, - Rx, - Tx, }, DriverMode, }; @@ -259,8 +257,7 @@ pub mod dma { bytes_to_write, &mut EmptyBuf, &mut buffer, - &mut self.channel.rx, - &mut self.channel.tx, + &mut self.channel, ) }; if let Err(err) = result { @@ -295,8 +292,7 @@ pub mod dma { 0, &mut buffer, &mut EmptyBuf, - &mut self.channel.rx, - &mut self.channel.tx, + &mut self.channel, ) }; if let Err(err) = result { @@ -341,8 +337,7 @@ pub mod dma { bytes_to_write, &mut rx_buffer, &mut tx_buffer, - &mut self.channel.rx, - &mut self.channel.tx, + &mut self.channel, ) }; if let Err(err) = result { @@ -462,29 +457,28 @@ pub mod dma { } #[allow(clippy::too_many_arguments)] - unsafe fn start_transfer_dma( + unsafe fn start_transfer_dma( &self, read_buffer_len: usize, write_buffer_len: usize, rx_buffer: &mut impl DmaRxBuffer, tx_buffer: &mut impl DmaTxBuffer, - rx: &mut RX, - tx: &mut TX, - ) -> Result<(), Error> - where - RX: Rx, - TX: Tx, - { + channel: &mut Channel>>, + ) -> Result<(), Error> { self.enable_dma(); self.info.reset_spi(); if read_buffer_len > 0 { - rx.prepare_transfer(self.dma_peripheral, rx_buffer)?; + channel + .rx + .prepare_transfer(self.dma_peripheral, rx_buffer)?; } if write_buffer_len > 0 { - tx.prepare_transfer(self.dma_peripheral, tx_buffer)?; + channel + .tx + .prepare_transfer(self.dma_peripheral, tx_buffer)?; } #[cfg(esp32)] @@ -503,11 +497,11 @@ pub mod dma { self.regs().cmd().modify(|_, w| w.usr().set_bit()); if read_buffer_len > 0 { - rx.start_transfer()?; + channel.rx.start_transfer()?; } if write_buffer_len > 0 { - tx.start_transfer()?; + channel.tx.start_transfer()?; } Ok(())