From 394ff0213b5685f527c87abaea657097060fd3e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 1 Oct 2024 13:35:41 +0200 Subject: [PATCH 01/36] Split PdmaChannel into two --- esp-hal/src/dma/pdma.rs | 51 ++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 423ab7f24e6..ef85b711dd4 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -23,10 +23,15 @@ type SpiRegisterBlock = crate::peripherals::spi2::RegisterBlock; type I2sRegisterBlock = crate::peripherals::i2s0::RegisterBlock; #[doc(hidden)] -pub trait PdmaChannel: crate::private::Sealed { - type RegisterBlock; +pub trait SpiPdmaChannel: crate::private::Sealed { + fn register_block() -> &'static SpiRegisterBlock; + fn tx_waker() -> &'static AtomicWaker; + fn rx_waker() -> &'static AtomicWaker; +} - fn register_block() -> &'static Self::RegisterBlock; +#[doc(hidden)] +pub trait I2sPdmaChannel: crate::private::Sealed { + fn register_block() -> &'static I2sRegisterBlock; fn tx_waker() -> &'static AtomicWaker; fn rx_waker() -> &'static AtomicWaker; } @@ -39,7 +44,7 @@ pub struct SpiDmaRxChannelImpl(PhantomData); impl crate::private::Sealed for SpiDmaTxChannelImpl {} impl crate::private::Sealed for SpiDmaRxChannelImpl {} -impl> RegisterAccess for SpiDmaTxChannelImpl { +impl RegisterAccess for SpiDmaTxChannelImpl { fn reset(&self) { let spi = C::register_block(); spi.dma_conf().modify(|_, w| w.out_rst().set_bit()); @@ -82,16 +87,14 @@ impl> RegisterAccess for SpiDma } } -impl> TxRegisterAccess for SpiDmaTxChannelImpl { +impl TxRegisterAccess for SpiDmaTxChannelImpl { fn last_dscr_address(&self) -> usize { let spi = C::register_block(); spi.out_eof_des_addr().read().dma_out_eof_des_addr().bits() as usize } } -impl> InterruptAccess - for SpiDmaTxChannelImpl -{ +impl InterruptAccess for SpiDmaTxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { let spi = C::register_block(); spi.dma_int_ena().modify(|_, w| { @@ -169,7 +172,7 @@ impl> InterruptAccess> RegisterAccess for SpiDmaRxChannelImpl { +impl RegisterAccess for SpiDmaRxChannelImpl { fn reset(&self) { let spi = C::register_block(); spi.dma_conf().modify(|_, w| w.in_rst().set_bit()); @@ -211,11 +214,9 @@ impl> RegisterAccess for SpiDma } } -impl> RxRegisterAccess for SpiDmaRxChannelImpl {} +impl RxRegisterAccess for SpiDmaRxChannelImpl {} -impl> InterruptAccess - for SpiDmaRxChannelImpl -{ +impl InterruptAccess for SpiDmaRxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { let spi = C::register_block(); spi.dma_int_ena().modify(|_, w| { @@ -345,9 +346,7 @@ macro_rules! ImplSpiChannel { } } - impl PdmaChannel for [] { - type RegisterBlock = SpiRegisterBlock; - + impl SpiPdmaChannel for [] { fn register_block() -> &'static SpiRegisterBlock { unsafe { &*crate::peripherals::[]::PTR } } @@ -437,7 +436,7 @@ pub struct I2sDmaRxChannelImpl(PhantomData); impl crate::private::Sealed for I2sDmaTxChannelImpl {} impl crate::private::Sealed for I2sDmaRxChannelImpl {} -impl> RegisterAccess for I2sDmaTxChannelImpl { +impl RegisterAccess for I2sDmaTxChannelImpl { fn set_burst_mode(&self, burst_mode: bool) { let reg_block = C::register_block(); reg_block @@ -486,7 +485,7 @@ impl> RegisterAccess for I2sDma } } -impl> TxRegisterAccess for I2sDmaTxChannelImpl { +impl TxRegisterAccess for I2sDmaTxChannelImpl { fn last_dscr_address(&self) -> usize { let reg_block = C::register_block(); reg_block @@ -497,9 +496,7 @@ impl> TxRegisterAccess for I2sD } } -impl> InterruptAccess - for I2sDmaTxChannelImpl -{ +impl InterruptAccess for I2sDmaTxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { let reg_block = C::register_block(); reg_block.int_ena().modify(|_, w| { @@ -577,7 +574,7 @@ impl> InterruptAccess> RegisterAccess for I2sDmaRxChannelImpl { +impl RegisterAccess for I2sDmaRxChannelImpl { fn set_burst_mode(&self, burst_mode: bool) { let reg_block = C::register_block(); reg_block @@ -624,11 +621,9 @@ impl> RegisterAccess for I2sDma } } -impl> RxRegisterAccess for I2sDmaRxChannelImpl {} +impl RxRegisterAccess for I2sDmaRxChannelImpl {} -impl> InterruptAccess - for I2sDmaRxChannelImpl -{ +impl InterruptAccess for I2sDmaRxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { let reg_block = C::register_block(); reg_block.int_ena().modify(|_, w| { @@ -754,9 +749,7 @@ macro_rules! ImplI2sChannel { } } - impl PdmaChannel for [] { - type RegisterBlock = I2sRegisterBlock; - + impl I2sPdmaChannel for [] { fn register_block() -> &'static I2sRegisterBlock { unsafe { &*crate::peripherals::[< I2S $num >]::PTR } } From 1c9fed01561a74539863ce83e7e38ed6ea2d860e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 1 Oct 2024 14:05:04 +0200 Subject: [PATCH 02/36] Take &self in PDMA traits --- esp-hal/src/dma/gdma.rs | 20 +++--- esp-hal/src/dma/mod.rs | 10 +-- esp-hal/src/dma/pdma.rs | 148 ++++++++++++++++++++-------------------- 3 files changed, 89 insertions(+), 89 deletions(-) diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index c17358dcdf3..ba28fd0a53e 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -56,26 +56,26 @@ impl crate::private::Sealed for ChannelTxImpl {} impl ChannelTxImpl { #[inline(always)] - fn ch(&self) -> &'static crate::peripherals::dma::ch::CH { + fn ch(&self) -> &crate::peripherals::dma::ch::CH { let dma = unsafe { &*crate::peripherals::DMA::PTR }; dma.ch(self.0.number() as usize) } #[cfg(any(esp32c2, esp32c3))] #[inline(always)] - fn int(&self) -> &'static crate::peripherals::dma::int_ch::INT_CH { + fn int(&self) -> &crate::peripherals::dma::int_ch::INT_CH { let dma = unsafe { &*crate::peripherals::DMA::PTR }; dma.int_ch(self.0.number() as usize) } #[inline(always)] #[cfg(any(esp32c6, esp32h2))] - fn int(&self) -> &'static crate::peripherals::dma::out_int_ch::OUT_INT_CH { + fn int(&self) -> &crate::peripherals::dma::out_int_ch::OUT_INT_CH { let dma = unsafe { &*crate::peripherals::DMA::PTR }; dma.out_int_ch(self.0.number() as usize) } #[cfg(esp32s3)] #[inline(always)] - fn int(&self) -> &'static crate::peripherals::dma::ch::out_int::OUT_INT { + fn int(&self) -> &crate::peripherals::dma::ch::out_int::OUT_INT { let dma = unsafe { &*crate::peripherals::DMA::PTR }; dma.ch(self.0.number() as usize).out_int() } @@ -222,7 +222,7 @@ impl InterruptAccess for ChannelTxImpl { result } - fn waker(&self) -> &'static AtomicWaker { + fn waker(&self) -> &AtomicWaker { &TX_WAKERS[self.0.number() as usize] } } @@ -235,28 +235,28 @@ impl crate::private::Sealed for ChannelRxImpl {} impl ChannelRxImpl { #[inline(always)] - fn ch(&self) -> &'static crate::peripherals::dma::ch::CH { + fn ch(&self) -> &crate::peripherals::dma::ch::CH { let dma = unsafe { &*crate::peripherals::DMA::PTR }; dma.ch(self.0.number() as usize) } #[cfg(any(esp32c2, esp32c3))] #[inline(always)] - fn int(&self) -> &'static crate::peripherals::dma::int_ch::INT_CH { + fn int(&self) -> &crate::peripherals::dma::int_ch::INT_CH { let dma = unsafe { &*crate::peripherals::DMA::PTR }; dma.int_ch(self.0.number() as usize) } #[inline(always)] #[cfg(any(esp32c6, esp32h2))] - fn int(&self) -> &'static crate::peripherals::dma::in_int_ch::IN_INT_CH { + fn int(&self) -> &crate::peripherals::dma::in_int_ch::IN_INT_CH { let dma = unsafe { &*crate::peripherals::DMA::PTR }; dma.in_int_ch(self.0.number() as usize) } #[cfg(esp32s3)] #[inline(always)] - fn int(&self) -> &'static crate::peripherals::dma::ch::in_int::IN_INT { + fn int(&self) -> &crate::peripherals::dma::ch::in_int::IN_INT { let dma = unsafe { &*crate::peripherals::DMA::PTR }; dma.ch(self.0.number() as usize).in_int() } @@ -407,7 +407,7 @@ impl InterruptAccess for ChannelRxImpl { result } - fn waker(&self) -> &'static AtomicWaker { + fn waker(&self) -> &AtomicWaker { &RX_WAKERS[self.0.number() as usize] } } diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 5e66769aee6..5b816ea27b3 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1607,7 +1607,7 @@ pub trait Rx: crate::private::Sealed { fn clear_interrupts(&self); - fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker; + fn waker(&self) -> &embassy_sync::waitqueue::AtomicWaker; } // DMA receive channel @@ -1773,7 +1773,7 @@ where self.rx_impl.clear_all(); } - fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker { + fn waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { self.rx_impl.waker() } } @@ -1822,7 +1822,7 @@ pub trait Tx: crate::private::Sealed { fn clear_interrupts(&self); - fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker; + fn waker(&self) -> &embassy_sync::waitqueue::AtomicWaker; fn last_out_dscr_address(&self) -> usize; } @@ -1974,7 +1974,7 @@ where self.tx_impl.pending_interrupts() } - fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker { + fn waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { self.tx_impl.waker() } @@ -2048,7 +2048,7 @@ pub trait InterruptAccess: crate::private::Sealed { fn is_listening(&self) -> EnumSet; fn clear(&self, interrupts: impl Into>); fn pending_interrupts(&self) -> EnumSet; - fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker; + fn waker(&self) -> &embassy_sync::waitqueue::AtomicWaker; } /// DMA Channel diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index ef85b711dd4..45a3311a1f9 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -24,35 +24,35 @@ type I2sRegisterBlock = crate::peripherals::i2s0::RegisterBlock; #[doc(hidden)] pub trait SpiPdmaChannel: crate::private::Sealed { - fn register_block() -> &'static SpiRegisterBlock; - fn tx_waker() -> &'static AtomicWaker; - fn rx_waker() -> &'static AtomicWaker; + fn register_block(&self) -> &SpiRegisterBlock; + fn tx_waker(&self) -> &AtomicWaker; + fn rx_waker(&self) -> &AtomicWaker; } #[doc(hidden)] pub trait I2sPdmaChannel: crate::private::Sealed { - fn register_block() -> &'static I2sRegisterBlock; - fn tx_waker() -> &'static AtomicWaker; - fn rx_waker() -> &'static AtomicWaker; + fn register_block(&self) -> &I2sRegisterBlock; + fn tx_waker(&self) -> &AtomicWaker; + fn rx_waker(&self) -> &AtomicWaker; } #[doc(hidden)] -pub struct SpiDmaTxChannelImpl(PhantomData); +pub struct SpiDmaTxChannelImpl(C); #[doc(hidden)] -pub struct SpiDmaRxChannelImpl(PhantomData); +pub struct SpiDmaRxChannelImpl(C); impl crate::private::Sealed for SpiDmaTxChannelImpl {} impl crate::private::Sealed for SpiDmaRxChannelImpl {} impl RegisterAccess for SpiDmaTxChannelImpl { fn reset(&self) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_conf().modify(|_, w| w.out_rst().set_bit()); spi.dma_conf().modify(|_, w| w.out_rst().clear_bit()); } fn set_burst_mode(&self, burst_mode: bool) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_conf() .modify(|_, w| w.outdscr_burst_en().bit(burst_mode)); } @@ -64,24 +64,24 @@ impl RegisterAccess for SpiDmaTxChannelImpl { } fn set_link_addr(&self, address: u32) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_out_link() .modify(|_, w| unsafe { w.outlink_addr().bits(address) }); } fn start(&self) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_out_link() .modify(|_, w| w.outlink_start().set_bit()); } fn stop(&self) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_out_link().modify(|_, w| w.outlink_stop().set_bit()); } fn restart(&self) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_out_link() .modify(|_, w| w.outlink_restart().set_bit()); } @@ -89,14 +89,14 @@ impl RegisterAccess for SpiDmaTxChannelImpl { impl TxRegisterAccess for SpiDmaTxChannelImpl { fn last_dscr_address(&self) -> usize { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.out_eof_des_addr().read().dma_out_eof_des_addr().bits() as usize } } impl InterruptAccess for SpiDmaTxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_int_ena().modify(|_, w| { for interrupt in interrupts { match interrupt { @@ -113,7 +113,7 @@ impl InterruptAccess for SpiDmaTxChannelImpl< fn is_listening(&self) -> EnumSet { let mut result = EnumSet::new(); - let spi = C::register_block(); + let spi = self.0.register_block(); let int_ena = spi.dma_int_ena().read(); if int_ena.out_total_eof().bit_is_set() { result |= DmaTxInterrupt::TotalEof; @@ -132,7 +132,7 @@ impl InterruptAccess for SpiDmaTxChannelImpl< } fn clear(&self, interrupts: impl Into>) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_int_clr().write(|w| { for interrupt in interrupts.into() { match interrupt { @@ -149,7 +149,7 @@ impl InterruptAccess for SpiDmaTxChannelImpl< fn pending_interrupts(&self) -> EnumSet { let mut result = EnumSet::new(); - let spi = C::register_block(); + let spi = self.0.register_block(); let int_raw = spi.dma_int_raw().read(); if int_raw.out_total_eof().bit_is_set() { result |= DmaTxInterrupt::TotalEof; @@ -167,20 +167,20 @@ impl InterruptAccess for SpiDmaTxChannelImpl< result } - fn waker(&self) -> &'static AtomicWaker { - C::tx_waker() + fn waker(&self) -> &AtomicWaker { + self.0.tx_waker() } } impl RegisterAccess for SpiDmaRxChannelImpl { fn reset(&self) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_conf().modify(|_, w| w.in_rst().set_bit()); spi.dma_conf().modify(|_, w| w.in_rst().clear_bit()); } fn set_burst_mode(&self, burst_mode: bool) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_conf() .modify(|_, w| w.indscr_burst_en().bit(burst_mode)); } @@ -192,23 +192,23 @@ impl RegisterAccess for SpiDmaRxChannelImpl { } fn set_link_addr(&self, address: u32) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_in_link() .modify(|_, w| unsafe { w.inlink_addr().bits(address) }); } fn start(&self) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_in_link().modify(|_, w| w.inlink_start().set_bit()); } fn stop(&self) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_in_link().modify(|_, w| w.inlink_stop().set_bit()); } fn restart(&self) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_in_link() .modify(|_, w| w.inlink_restart().set_bit()); } @@ -218,7 +218,7 @@ impl RxRegisterAccess for SpiDmaRxChannelImpl {} impl InterruptAccess for SpiDmaRxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_int_ena().modify(|_, w| { for interrupt in interrupts { match interrupt { @@ -236,7 +236,7 @@ impl InterruptAccess for SpiDmaRxChannelImpl< fn is_listening(&self) -> EnumSet { let mut result = EnumSet::new(); - let spi = C::register_block(); + let spi = self.0.register_block(); let int_ena = spi.dma_int_ena().read(); if int_ena.inlink_dscr_error().bit_is_set() { result |= DmaRxInterrupt::DescriptorError; @@ -258,7 +258,7 @@ impl InterruptAccess for SpiDmaRxChannelImpl< } fn clear(&self, interrupts: impl Into>) { - let spi = C::register_block(); + let spi = self.0.register_block(); spi.dma_int_clr().modify(|_, w| { for interrupt in interrupts.into() { match interrupt { @@ -276,7 +276,7 @@ impl InterruptAccess for SpiDmaRxChannelImpl< fn pending_interrupts(&self) -> EnumSet { let mut result = EnumSet::new(); - let spi = C::register_block(); + let spi = self.0.register_block(); let int_raw = spi.dma_int_raw().read(); if int_raw.inlink_dscr_error().bit_is_set() { result |= DmaRxInterrupt::DescriptorError; @@ -297,8 +297,8 @@ impl InterruptAccess for SpiDmaRxChannelImpl< result } - fn waker(&self) -> &'static AtomicWaker { - C::rx_waker() + fn waker(&self) -> &AtomicWaker { + self.0.rx_waker() } } @@ -324,10 +324,10 @@ macro_rules! ImplSpiChannel { type Degraded = Self; fn get_rx_interrupts() -> impl InterruptAccess { - SpiDmaRxChannelImpl::(PhantomData) + SpiDmaRxChannelImpl(Self {}) } fn get_tx_interrupts() -> impl InterruptAccess { - SpiDmaTxChannelImpl::(PhantomData) + SpiDmaTxChannelImpl(Self {}) } fn degrade_rx(rx: Self::Rx) -> Self::Rx { @@ -347,14 +347,14 @@ macro_rules! ImplSpiChannel { } impl SpiPdmaChannel for [] { - fn register_block() -> &'static SpiRegisterBlock { + fn register_block(&self) -> &SpiRegisterBlock { unsafe { &*crate::peripherals::[]::PTR } } - fn tx_waker() -> &'static embassy_sync::waitqueue::AtomicWaker { + fn tx_waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } - fn rx_waker() -> &'static embassy_sync::waitqueue::AtomicWaker { + fn rx_waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } @@ -381,11 +381,11 @@ macro_rules! ImplSpiChannel { .modify(|_, w| unsafe { w.[< spi $num _dma_chan_sel>]().bits($num - 1) }); } - let tx_impl = SpiDmaTxChannelImpl(PhantomData); + let tx_impl = SpiDmaTxChannelImpl([] {}); tx_impl.set_burst_mode(burst_mode); tx_impl.set_priority(priority); - let rx_impl = SpiDmaRxChannelImpl(PhantomData); + let rx_impl = SpiDmaRxChannelImpl([] {}); rx_impl.set_burst_mode(burst_mode); rx_impl.set_priority(priority); @@ -429,16 +429,16 @@ macro_rules! ImplSpiChannel { } #[doc(hidden)] -pub struct I2sDmaTxChannelImpl(PhantomData); +pub struct I2sDmaTxChannelImpl(C); #[doc(hidden)] -pub struct I2sDmaRxChannelImpl(PhantomData); +pub struct I2sDmaRxChannelImpl(C); impl crate::private::Sealed for I2sDmaTxChannelImpl {} impl crate::private::Sealed for I2sDmaRxChannelImpl {} impl RegisterAccess for I2sDmaTxChannelImpl { fn set_burst_mode(&self, burst_mode: bool) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block .lc_conf() .modify(|_, w| w.outdscr_burst_en().bit(burst_mode)); @@ -447,13 +447,13 @@ impl RegisterAccess for I2sDmaTxChannelImpl { fn set_priority(&self, _priority: DmaPriority) {} fn reset(&self) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block.lc_conf().modify(|_, w| w.out_rst().set_bit()); reg_block.lc_conf().modify(|_, w| w.out_rst().clear_bit()); } fn set_link_addr(&self, address: u32) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block .out_link() .modify(|_, w| unsafe { w.outlink_addr().bits(address) }); @@ -464,21 +464,21 @@ impl RegisterAccess for I2sDmaTxChannelImpl { } fn start(&self) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block .out_link() .modify(|_, w| w.outlink_start().set_bit()); } fn stop(&self) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block .out_link() .modify(|_, w| w.outlink_stop().set_bit()); } fn restart(&self) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block .out_link() .modify(|_, w| w.outlink_restart().set_bit()); @@ -487,7 +487,7 @@ impl RegisterAccess for I2sDmaTxChannelImpl { impl TxRegisterAccess for I2sDmaTxChannelImpl { fn last_dscr_address(&self) -> usize { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block .out_eof_des_addr() .read() @@ -498,7 +498,7 @@ impl TxRegisterAccess for I2sDmaTxChannelImpl { impl InterruptAccess for I2sDmaTxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block.int_ena().modify(|_, w| { for interrupt in interrupts { match interrupt { @@ -515,7 +515,7 @@ impl InterruptAccess for I2sDmaTxChannelImpl< fn is_listening(&self) -> EnumSet { let mut result = EnumSet::new(); - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); let int_ena = reg_block.int_ena().read(); if int_ena.out_total_eof().bit_is_set() { result |= DmaTxInterrupt::TotalEof; @@ -536,7 +536,7 @@ impl InterruptAccess for I2sDmaTxChannelImpl< fn pending_interrupts(&self) -> EnumSet { let mut result = EnumSet::new(); - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); let int_raw = reg_block.int_raw().read(); if int_raw.out_total_eof().bit_is_set() { result |= DmaTxInterrupt::TotalEof; @@ -555,7 +555,7 @@ impl InterruptAccess for I2sDmaTxChannelImpl< } fn clear(&self, interrupts: impl Into>) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block.int_clr().write(|w| { for interrupt in interrupts.into() { match interrupt { @@ -569,14 +569,14 @@ impl InterruptAccess for I2sDmaTxChannelImpl< }) } - fn waker(&self) -> &'static AtomicWaker { - C::tx_waker() + fn waker(&self) -> &AtomicWaker { + self.0.tx_waker() } } impl RegisterAccess for I2sDmaRxChannelImpl { fn set_burst_mode(&self, burst_mode: bool) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block .lc_conf() .modify(|_, w| w.indscr_burst_en().bit(burst_mode)); @@ -585,13 +585,13 @@ impl RegisterAccess for I2sDmaRxChannelImpl { fn set_priority(&self, _priority: DmaPriority) {} fn reset(&self) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block.lc_conf().modify(|_, w| w.in_rst().set_bit()); reg_block.lc_conf().modify(|_, w| w.in_rst().clear_bit()); } fn set_link_addr(&self, address: u32) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block .in_link() .modify(|_, w| unsafe { w.inlink_addr().bits(address) }); @@ -602,19 +602,19 @@ impl RegisterAccess for I2sDmaRxChannelImpl { } fn start(&self) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block .in_link() .modify(|_, w| w.inlink_start().set_bit()); } fn stop(&self) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block.in_link().modify(|_, w| w.inlink_stop().set_bit()); } fn restart(&self) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block .in_link() .modify(|_, w| w.inlink_restart().set_bit()); @@ -625,7 +625,7 @@ impl RxRegisterAccess for I2sDmaRxChannelImpl {} impl InterruptAccess for I2sDmaRxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { - let reg_block = C::register_block(); + let spi = self.0.register_block(); reg_block.int_ena().modify(|_, w| { for interrupt in interrupts { match interrupt { @@ -643,7 +643,7 @@ impl InterruptAccess for I2sDmaRxChannelImpl< fn is_listening(&self) -> EnumSet { let mut result = EnumSet::new(); - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); let int_ena = reg_block.int_ena().read(); if int_ena.in_dscr_err().bit_is_set() { result |= DmaRxInterrupt::DescriptorError; @@ -667,7 +667,7 @@ impl InterruptAccess for I2sDmaRxChannelImpl< fn pending_interrupts(&self) -> EnumSet { let mut result = EnumSet::new(); - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); let int_raw = reg_block.int_raw().read(); if int_raw.in_dscr_err().bit_is_set() { result |= DmaRxInterrupt::DescriptorError; @@ -689,7 +689,7 @@ impl InterruptAccess for I2sDmaRxChannelImpl< } fn clear(&self, interrupts: impl Into>) { - let reg_block = C::register_block(); + let reg_block = self.0.register_block(); reg_block.int_clr().write(|w| { for interrupt in interrupts.into() { match interrupt { @@ -704,8 +704,8 @@ impl InterruptAccess for I2sDmaRxChannelImpl< }) } - fn waker(&self) -> &'static AtomicWaker { - C::rx_waker() + fn waker(&self) -> &AtomicWaker { + self.0.rx_waker() } } @@ -727,10 +727,10 @@ macro_rules! ImplI2sChannel { type Degraded = Self; fn get_rx_interrupts() -> impl InterruptAccess { - I2sDmaRxChannelImpl::(PhantomData) + I2sDmaRxChannelImpl(Self {}) } fn get_tx_interrupts() -> impl InterruptAccess { - I2sDmaTxChannelImpl::(PhantomData) + I2sDmaTxChannelImpl(Self {}) } fn degrade_rx(rx: Self::Rx) -> Self::Rx { @@ -750,14 +750,14 @@ macro_rules! ImplI2sChannel { } impl I2sPdmaChannel for [] { - fn register_block() -> &'static I2sRegisterBlock { + fn register_block(&self) -> &I2sRegisterBlock { unsafe { &*crate::peripherals::[< I2S $num >]::PTR } } - fn tx_waker() -> &'static embassy_sync::waitqueue::AtomicWaker { + fn tx_waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } - fn rx_waker() -> &'static embassy_sync::waitqueue::AtomicWaker { + fn rx_waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } @@ -772,11 +772,11 @@ macro_rules! ImplI2sChannel { burst_mode: bool, priority: DmaPriority, ) -> Channel<'a, [], M> { - let tx_impl = I2sDmaTxChannelImpl(PhantomData); + let tx_impl = I2sDmaTxChannelImpl([] {}); tx_impl.set_burst_mode(burst_mode); tx_impl.set_priority(priority); - let rx_impl = I2sDmaRxChannelImpl(PhantomData); + let rx_impl = I2sDmaRxChannelImpl([] {}); rx_impl.set_burst_mode(burst_mode); rx_impl.set_priority(priority); From 2e1f3a96a8f4a4d60494dda93fc16c402071f094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 1 Oct 2024 17:08:29 +0200 Subject: [PATCH 03/36] Implement type-erased PDMA channels --- esp-hal/src/aes/mod.rs | 14 +-- esp-hal/src/dma/gdma.rs | 15 ++- esp-hal/src/dma/mod.rs | 19 ++- esp-hal/src/dma/pdma.rs | 240 +++++++++++++++++++++++++++++++++----- esp-hal/src/i2s.rs | 3 +- esp-hal/src/parl_io.rs | 47 ++------ esp-hal/src/spi/master.rs | 36 ++---- esp-hal/src/spi/slave.rs | 11 +- 8 files changed, 257 insertions(+), 128 deletions(-) diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index e230cf6d28c..b292c496a4b 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -244,6 +244,7 @@ pub mod dma { DmaDescriptor, DmaPeripheral, DmaTransferRxTx, + PeripheralDmaChannel, ReadBuffer, Rx, Tx, @@ -251,10 +252,7 @@ pub mod dma { }, }; - #[cfg(gdma)] type DefaultChannel = crate::dma::AnyDmaChannel; - #[cfg(pdma)] - type DefaultChannel = (); // Replace with PDMA channel once support is added. const ALIGN_SIZE: usize = core::mem::size_of::(); @@ -278,7 +276,6 @@ pub mod dma { pub struct AesDma<'d, C = DefaultChannel> where C: DmaChannel, - C::P: AesPeripheral, { /// The underlying [`Aes`](super::Aes) driver pub aes: super::Aes<'d>, @@ -291,7 +288,7 @@ pub mod dma { /// Functionality for using AES with DMA. pub trait WithDmaAes<'d, C> where - C: DmaChannel, + C: PeripheralDmaChannel, C::P: AesPeripheral, { /// Enable DMA for the current instance of the AES driver @@ -305,7 +302,7 @@ pub mod dma { impl<'d, C> WithDmaAes<'d, C> for crate::aes::Aes<'d> where - C: DmaChannel, + C: PeripheralDmaChannel, C::P: AesPeripheral, { fn with_dma( @@ -326,7 +323,6 @@ pub mod dma { impl<'d, C> core::fmt::Debug for AesDma<'d, C> where C: DmaChannel, - C::P: AesPeripheral, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("AesDma").finish() @@ -336,7 +332,6 @@ pub mod dma { impl<'d, C> DmaSupport for AesDma<'d, C> where C: DmaChannel, - C::P: AesPeripheral, { fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { while self.aes.aes.state().read().state().bits() != 2 // DMA status DONE == 2 @@ -356,7 +351,6 @@ pub mod dma { impl<'d, C> DmaSupportTx for AesDma<'d, C> where C: DmaChannel, - C::P: AesPeripheral, { type TX = ChannelTx<'d, C>; @@ -372,7 +366,6 @@ pub mod dma { impl<'d, C> DmaSupportRx for AesDma<'d, C> where C: DmaChannel, - C::P: AesPeripheral, { type RX = ChannelRx<'d, C>; @@ -388,7 +381,6 @@ pub mod dma { impl<'d, C> AesDma<'d, C> where C: DmaChannel, - C::P: AesPeripheral, { /// Writes the encryption key to the AES hardware, checking that its /// length matches expected constraints. diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index ba28fd0a53e..11544d766e3 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -222,7 +222,7 @@ impl InterruptAccess for ChannelTxImpl { result } - fn waker(&self) -> &AtomicWaker { + fn waker(&self) -> &'static AtomicWaker { &TX_WAKERS[self.0.number() as usize] } } @@ -407,7 +407,7 @@ impl InterruptAccess for ChannelRxImpl { result } - fn waker(&self) -> &AtomicWaker { + fn waker(&self) -> &'static AtomicWaker { &RX_WAKERS[self.0.number() as usize] } } @@ -439,15 +439,12 @@ impl AesPeripheral for SuitablePeripheral {} #[cfg(lcd_cam)] impl LcdCamPeripheral for SuitablePeripheral {} -/// A description of any GDMA channel -#[non_exhaustive] -pub struct AnyDmaChannel {} - -impl crate::private::Sealed for AnyDmaChannel {} - impl DmaChannel for AnyDmaChannel { type Rx = ChannelRxImpl; type Tx = ChannelTxImpl; +} + +impl PeripheralDmaChannel for AnyDmaChannel { type P = SuitablePeripheral; } @@ -463,6 +460,8 @@ macro_rules! impl_channel { impl DmaChannel for [] { type Rx = ChannelRxImpl>; type Tx = ChannelTxImpl>; + } + impl PeripheralDmaChannel for [] { type P = SuitablePeripheral; } diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 5b816ea27b3..9fcefd806ce 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1534,11 +1534,20 @@ pub trait DmaChannel: crate::private::Sealed { /// A description of the TX half of a DMA Channel. type Tx: TxRegisterAccess + InterruptAccess; +} +/// A description of a DMA Channel that can be used with a peripheral. +pub trait PeripheralDmaChannel: DmaChannel { /// A suitable peripheral for this DMA channel. type P: PeripheralMarker; } +/// A description of any DMA channel +#[non_exhaustive] +pub struct AnyDmaChannel {} + +impl crate::private::Sealed for AnyDmaChannel {} + #[doc(hidden)] pub trait DmaChannelExt: DmaChannel { type Degraded: DmaChannel; @@ -1607,7 +1616,7 @@ pub trait Rx: crate::private::Sealed { fn clear_interrupts(&self); - fn waker(&self) -> &embassy_sync::waitqueue::AtomicWaker; + fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker; } // DMA receive channel @@ -1773,7 +1782,7 @@ where self.rx_impl.clear_all(); } - fn waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { + fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker { self.rx_impl.waker() } } @@ -1822,7 +1831,7 @@ pub trait Tx: crate::private::Sealed { fn clear_interrupts(&self); - fn waker(&self) -> &embassy_sync::waitqueue::AtomicWaker; + fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker; fn last_out_dscr_address(&self) -> usize; } @@ -1974,7 +1983,7 @@ where self.tx_impl.pending_interrupts() } - fn waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { + fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker { self.tx_impl.waker() } @@ -2048,7 +2057,7 @@ pub trait InterruptAccess: crate::private::Sealed { fn is_listening(&self) -> EnumSet; fn clear(&self, interrupts: impl Into>); fn pending_interrupts(&self) -> EnumSet; - fn waker(&self) -> &embassy_sync::waitqueue::AtomicWaker; + fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker; } /// DMA Channel diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 45a3311a1f9..dcdf3dc8ae0 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -25,25 +25,45 @@ type I2sRegisterBlock = crate::peripherals::i2s0::RegisterBlock; #[doc(hidden)] pub trait SpiPdmaChannel: crate::private::Sealed { fn register_block(&self) -> &SpiRegisterBlock; - fn tx_waker(&self) -> &AtomicWaker; - fn rx_waker(&self) -> &AtomicWaker; + fn tx_waker(&self) -> &'static AtomicWaker; + fn rx_waker(&self) -> &'static AtomicWaker; } #[doc(hidden)] pub trait I2sPdmaChannel: crate::private::Sealed { fn register_block(&self) -> &I2sRegisterBlock; - fn tx_waker(&self) -> &AtomicWaker; - fn rx_waker(&self) -> &AtomicWaker; + fn tx_waker(&self) -> &'static AtomicWaker; + fn rx_waker(&self) -> &'static AtomicWaker; } -#[doc(hidden)] -pub struct SpiDmaTxChannelImpl(C); #[doc(hidden)] pub struct SpiDmaRxChannelImpl(C); -impl crate::private::Sealed for SpiDmaTxChannelImpl {} impl crate::private::Sealed for SpiDmaRxChannelImpl {} +impl SpiDmaRxChannelImpl +where + AnyPdmaChannel: From, +{ + fn degrade(self) -> AnyPdmaRxChannelImpl { + AnyPdmaRxChannelImpl(AnyPdmaChannel::from(self.0)) + } +} + +#[doc(hidden)] +pub struct SpiDmaTxChannelImpl(C); + +impl crate::private::Sealed for SpiDmaTxChannelImpl {} + +impl SpiDmaTxChannelImpl +where + AnyPdmaChannel: From, +{ + fn degrade(self) -> AnyPdmaTxChannelImpl { + AnyPdmaTxChannelImpl(AnyPdmaChannel::from(self.0)) + } +} + impl RegisterAccess for SpiDmaTxChannelImpl { fn reset(&self) { let spi = self.0.register_block(); @@ -167,7 +187,7 @@ impl InterruptAccess for SpiDmaTxChannelImpl< result } - fn waker(&self) -> &AtomicWaker { + fn waker(&self) -> &'static AtomicWaker { self.0.tx_waker() } } @@ -297,7 +317,7 @@ impl InterruptAccess for SpiDmaRxChannelImpl< result } - fn waker(&self) -> &AtomicWaker { + fn waker(&self) -> &'static AtomicWaker { self.0.rx_waker() } } @@ -314,14 +334,28 @@ macro_rules! ImplSpiChannel { #[non_exhaustive] pub struct [] {} + impl [] { + unsafe fn clone_unchecked(&self) -> Self { + Self {} + } + } + + impl From<[]> for AnyPdmaChannel { + fn from(channel: []) -> Self { + AnyPdmaChannel::[](channel) + } + } + impl DmaChannel for [] { type Rx = SpiDmaRxChannelImpl; type Tx = SpiDmaTxChannelImpl; + } + impl PeripheralDmaChannel for [] { type P = []; } impl DmaChannelExt for [] { - type Degraded = Self; + type Degraded = AnyDmaChannel; fn get_rx_interrupts() -> impl InterruptAccess { SpiDmaRxChannelImpl(Self {}) @@ -330,11 +364,11 @@ macro_rules! ImplSpiChannel { SpiDmaTxChannelImpl(Self {}) } - fn degrade_rx(rx: Self::Rx) -> Self::Rx { - rx + fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { + rx.degrade() } - fn degrade_tx(tx: Self::Tx) -> Self::Tx { - tx + fn degrade_tx(tx: Self::Tx) -> AnyPdmaTxChannelImpl { + tx.degrade() } fn set_isr(handler: InterruptHandler) { @@ -350,11 +384,11 @@ macro_rules! ImplSpiChannel { fn register_block(&self) -> &SpiRegisterBlock { unsafe { &*crate::peripherals::[]::PTR } } - fn tx_waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { + fn tx_waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } - fn rx_waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { + fn rx_waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } @@ -428,14 +462,34 @@ macro_rules! ImplSpiChannel { }; } -#[doc(hidden)] -pub struct I2sDmaTxChannelImpl(C); #[doc(hidden)] pub struct I2sDmaRxChannelImpl(C); -impl crate::private::Sealed for I2sDmaTxChannelImpl {} impl crate::private::Sealed for I2sDmaRxChannelImpl {} +impl I2sDmaRxChannelImpl +where + AnyPdmaChannel: From, +{ + fn degrade(self) -> AnyPdmaRxChannelImpl { + AnyPdmaRxChannelImpl(AnyPdmaChannel::from(self.0)) + } +} + +#[doc(hidden)] +pub struct I2sDmaTxChannelImpl(C); + +impl crate::private::Sealed for I2sDmaTxChannelImpl {} + +impl I2sDmaTxChannelImpl +where + AnyPdmaChannel: From, +{ + fn degrade(self) -> AnyPdmaTxChannelImpl { + AnyPdmaTxChannelImpl(AnyPdmaChannel::from(self.0)) + } +} + impl RegisterAccess for I2sDmaTxChannelImpl { fn set_burst_mode(&self, burst_mode: bool) { let reg_block = self.0.register_block(); @@ -569,7 +623,7 @@ impl InterruptAccess for I2sDmaTxChannelImpl< }) } - fn waker(&self) -> &AtomicWaker { + fn waker(&self) -> &'static AtomicWaker { self.0.tx_waker() } } @@ -704,7 +758,7 @@ impl InterruptAccess for I2sDmaRxChannelImpl< }) } - fn waker(&self) -> &AtomicWaker { + fn waker(&self) -> &'static AtomicWaker { self.0.rx_waker() } } @@ -715,16 +769,30 @@ macro_rules! ImplI2sChannel { #[doc = concat!("DMA channel suitable for I2S", $num)] pub struct [] {} + impl [] { + unsafe fn clone_unchecked(&self) -> Self { + Self {} + } + } + + impl From<[]> for AnyPdmaChannel { + fn from(channel: []) -> Self { + AnyPdmaChannel::[](channel) + } + } + impl $crate::private::Sealed for [] {} impl DmaChannel for [] { type Rx = I2sDmaRxChannelImpl; type Tx = I2sDmaTxChannelImpl; + } + impl PeripheralDmaChannel for [] { type P = []; } impl DmaChannelExt for [] { - type Degraded = Self; + type Degraded = AnyDmaChannel; fn get_rx_interrupts() -> impl InterruptAccess { I2sDmaRxChannelImpl(Self {}) @@ -733,11 +801,11 @@ macro_rules! ImplI2sChannel { I2sDmaTxChannelImpl(Self {}) } - fn degrade_rx(rx: Self::Rx) -> Self::Rx { - rx + fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { + rx.degrade() } - fn degrade_tx(tx: Self::Tx) -> Self::Tx { - tx + fn degrade_tx(tx: Self::Tx) -> AnyPdmaTxChannelImpl { + tx.degrade() } fn set_isr(handler: InterruptHandler) { @@ -753,11 +821,11 @@ macro_rules! ImplI2sChannel { fn register_block(&self) -> &I2sRegisterBlock { unsafe { &*crate::peripherals::[< I2S $num >]::PTR } } - fn tx_waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { + fn tx_waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } - fn rx_waker(&self) -> &embassy_sync::waitqueue::AtomicWaker { + fn rx_waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } @@ -888,3 +956,119 @@ impl<'d> Dma<'d> { } } } + +#[doc(hidden)] +pub enum AnyPdmaChannel { + Spi2(Spi2DmaChannel), + Spi3(Spi3DmaChannel), + I2s0(I2s0DmaChannel), + #[cfg(i2s1)] + I2s1(I2s1DmaChannel), +} + +impl DmaChannel for AnyDmaChannel { + type Rx = AnyPdmaRxChannelImpl; + type Tx = AnyPdmaTxChannelImpl; +} + +#[doc(hidden)] +pub struct AnyPdmaRxChannelImpl(AnyPdmaChannel); + +impl crate::private::Sealed for AnyPdmaRxChannelImpl {} +impl InterruptAccess for AnyPdmaRxChannelImpl { + delegate::delegate! { + to match &self.0 { + AnyPdmaChannel::Spi2(channel) => unsafe { SpiDmaRxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaChannel::Spi3(channel) => unsafe { SpiDmaRxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaChannel::I2s0(channel) => unsafe { I2sDmaRxChannelImpl(channel.clone_unchecked()) }, + #[cfg(i2s1)] + AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaRxChannelImpl(channel.clone_unchecked()) }, + } { + fn listen(&self, interrupts: impl Into>); + fn unlisten(&self, interrupts: impl Into>); + fn is_listening(&self) -> EnumSet; + fn clear(&self, interrupts: impl Into>); + fn pending_interrupts(&self) -> EnumSet; + fn waker(&self) -> &'static AtomicWaker; + } + } +} +impl RegisterAccess for AnyPdmaRxChannelImpl { + delegate::delegate! { + to match &self.0 { + AnyPdmaChannel::Spi2(channel) => unsafe { SpiDmaRxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaChannel::Spi3(channel) => unsafe { SpiDmaRxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaChannel::I2s0(channel) => unsafe { I2sDmaRxChannelImpl(channel.clone_unchecked()) }, + #[cfg(i2s1)] + AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaRxChannelImpl(channel.clone_unchecked()) }, + } { + fn set_burst_mode(&self, burst_mode: bool); + fn set_priority(&self, priority: DmaPriority); + fn clear_interrupts(&self); + fn reset(&self); + fn set_link_addr(&self, address: u32); + fn set_peripheral(&self, peripheral: u8); + fn start(&self); + fn stop(&self); + fn restart(&self); + } + } +} +impl RxRegisterAccess for AnyPdmaRxChannelImpl {} + +#[doc(hidden)] +pub struct AnyPdmaTxChannelImpl(AnyPdmaChannel); + +impl crate::private::Sealed for AnyPdmaTxChannelImpl {} +impl InterruptAccess for AnyPdmaTxChannelImpl { + delegate::delegate! { + to match &self.0 { + AnyPdmaChannel::Spi2(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaChannel::Spi3(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaChannel::I2s0(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + #[cfg(i2s1)] + AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + } { + fn listen(&self, interrupts: impl Into>); + fn unlisten(&self, interrupts: impl Into>); + fn is_listening(&self) -> EnumSet; + fn clear(&self, interrupts: impl Into>); + fn pending_interrupts(&self) -> EnumSet; + fn waker(&self) -> &'static AtomicWaker; + } + } +} +impl RegisterAccess for AnyPdmaTxChannelImpl { + delegate::delegate! { + to match &self.0 { + AnyPdmaChannel::Spi2(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaChannel::Spi3(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaChannel::I2s0(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + #[cfg(i2s1)] + AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + } { + fn set_burst_mode(&self, burst_mode: bool); + fn set_priority(&self, priority: DmaPriority); + fn clear_interrupts(&self); + fn reset(&self); + fn set_link_addr(&self, address: u32); + fn set_peripheral(&self, peripheral: u8); + fn start(&self); + fn stop(&self); + fn restart(&self); + } + } +} +impl TxRegisterAccess for AnyPdmaTxChannelImpl { + delegate::delegate! { + to match &self.0 { + AnyPdmaChannel::Spi2(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaChannel::Spi3(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaChannel::I2s0(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + #[cfg(i2s1)] + AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + } { + fn last_dscr_address(&self) -> usize; + } + } +} diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index ce889bade8c..dd151307695 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -102,6 +102,7 @@ use crate::{ DmaTransferTxCircular, I2s0Peripheral, I2sPeripheral, + PeripheralDmaChannel, ReadBuffer, Rx, Tx, @@ -434,7 +435,7 @@ where impl<'d, I, CH, DmaMode> I2s<'d, I, CH, DmaMode> where I: RegisterAccess, - CH: DmaChannel, + CH: PeripheralDmaChannel, DmaMode: Mode, { /// Construct a new I2S peripheral driver instance for the first I2S diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 9f0e326d314..eb48a6fb339 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -44,6 +44,7 @@ use crate::{ DmaTransferRx, DmaTransferTx, ParlIoPeripheral, + PeripheralDmaChannel, ReadBuffer, Rx, Tx, @@ -1086,7 +1087,6 @@ fn internal_clear_interrupts(interrupts: EnumSet) { pub struct ParlIoFullDuplex<'d, CH, DM> where CH: DmaChannel, - CH::P: ParlIoPeripheral, DM: Mode, { /// The transmitter (TX) channel responsible for handling DMA transfers in @@ -1099,7 +1099,7 @@ where impl<'d, CH, DM> ParlIoFullDuplex<'d, CH, DM> where - CH: DmaChannel, + CH: PeripheralDmaChannel, CH::P: ParlIoPeripheral, DM: Mode, { @@ -1131,7 +1131,6 @@ where impl<'d, CH> ParlIoFullDuplex<'d, CH, Blocking> where CH: DmaChannel, - CH::P: ParlIoPeripheral, { /// Sets the interrupt handler, enables it with /// [crate::interrupt::Priority::min()] @@ -1162,17 +1161,11 @@ where } } -impl<'d, CH> crate::private::Sealed for ParlIoFullDuplex<'d, CH, Blocking> -where - CH: DmaChannel, - CH::P: ParlIoPeripheral, -{ -} +impl<'d, CH> crate::private::Sealed for ParlIoFullDuplex<'d, CH, Blocking> where CH: DmaChannel {} impl<'d, CH> InterruptConfigurable for ParlIoFullDuplex<'d, CH, Blocking> where CH: DmaChannel, - CH::P: ParlIoPeripheral, { fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) { ParlIoFullDuplex::set_interrupt_handler(self, handler); @@ -1183,7 +1176,6 @@ where pub struct ParlIoTxOnly<'d, CH, DM> where CH: DmaChannel, - CH::P: ParlIoPeripheral, DM: Mode, { /// The transmitter (TX) channel responsible for handling DMA transfers in @@ -1193,7 +1185,7 @@ where impl<'d, CH, DM> ParlIoTxOnly<'d, CH, DM> where - CH: DmaChannel, + CH: PeripheralDmaChannel, CH::P: ParlIoPeripheral, DM: Mode, { @@ -1219,7 +1211,6 @@ where impl<'d, CH> ParlIoTxOnly<'d, CH, Blocking> where CH: DmaChannel, - CH::P: ParlIoPeripheral, { /// Sets the interrupt handler, enables it with /// [crate::interrupt::Priority::min()] @@ -1250,17 +1241,11 @@ where } } -impl<'d, CH> crate::private::Sealed for ParlIoTxOnly<'d, CH, Blocking> -where - CH: DmaChannel, - CH::P: ParlIoPeripheral, -{ -} +impl<'d, CH> crate::private::Sealed for ParlIoTxOnly<'d, CH, Blocking> where CH: DmaChannel {} impl<'d, CH> InterruptConfigurable for ParlIoTxOnly<'d, CH, Blocking> where CH: DmaChannel, - CH::P: ParlIoPeripheral, { fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) { ParlIoTxOnly::set_interrupt_handler(self, handler); @@ -1271,7 +1256,6 @@ where pub struct ParlIoRxOnly<'d, CH, DM> where CH: DmaChannel, - CH::P: ParlIoPeripheral, DM: Mode, { /// The receiver (RX) channel responsible for handling DMA transfers in the @@ -1281,7 +1265,7 @@ where impl<'d, CH, DM> ParlIoRxOnly<'d, CH, DM> where - CH: DmaChannel, + CH: PeripheralDmaChannel, CH::P: ParlIoPeripheral, DM: Mode, { @@ -1307,7 +1291,6 @@ where impl<'d, CH> ParlIoRxOnly<'d, CH, Blocking> where CH: DmaChannel, - CH::P: ParlIoPeripheral, { /// Sets the interrupt handler, enables it with /// [crate::interrupt::Priority::min()] @@ -1338,17 +1321,11 @@ where } } -impl<'d, CH> crate::private::Sealed for ParlIoRxOnly<'d, CH, Blocking> -where - CH: DmaChannel, - CH::P: ParlIoPeripheral, -{ -} +impl<'d, CH> crate::private::Sealed for ParlIoRxOnly<'d, CH, Blocking> where CH: DmaChannel {} impl<'d, CH> InterruptConfigurable for ParlIoRxOnly<'d, CH, Blocking> where CH: DmaChannel, - CH::P: ParlIoPeripheral, { fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) { ParlIoRxOnly::set_interrupt_handler(self, handler); @@ -1391,7 +1368,6 @@ fn internal_init(frequency: HertzU32) -> Result<(), Error> { impl<'d, CH, DM> ParlIoTx<'d, CH, DM> where CH: DmaChannel, - CH::P: ParlIoPeripheral, DM: Mode, { /// Perform a DMA write. @@ -1452,7 +1428,6 @@ where impl<'d, CH, DM> DmaSupport for ParlIoTx<'d, CH, DM> where CH: DmaChannel, - CH::P: ParlIoPeripheral, DM: Mode, { fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { @@ -1469,7 +1444,6 @@ where impl<'d, CH, DM> DmaSupportTx for ParlIoTx<'d, CH, DM> where CH: DmaChannel, - CH::P: ParlIoPeripheral, DM: Mode, { type TX = ChannelTx<'d, CH>; @@ -1486,7 +1460,6 @@ where impl<'d, CH, DM> ParlIoRx<'d, CH, DM> where CH: DmaChannel, - CH::P: ParlIoPeripheral, DM: Mode, { /// Perform a DMA read. @@ -1547,7 +1520,6 @@ where impl<'d, CH, DM> DmaSupport for ParlIoRx<'d, CH, DM> where CH: DmaChannel, - CH::P: ParlIoPeripheral, DM: Mode, { fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { @@ -1571,7 +1543,6 @@ where impl<'d, CH, DM> DmaSupportRx for ParlIoRx<'d, CH, DM> where CH: DmaChannel, - CH::P: ParlIoPeripheral, DM: Mode, { type RX = ChannelRx<'d, CH>; @@ -1638,7 +1609,7 @@ pub mod asynch { use super::{private::Instance, Error, ParlIoRx, ParlIoTx, MAX_DMA_SIZE}; use crate::{ - dma::{asynch::DmaRxFuture, DmaChannel, ParlIoPeripheral, ReadBuffer, WriteBuffer}, + dma::{asynch::DmaRxFuture, DmaChannel, ReadBuffer, WriteBuffer}, peripherals::Interrupt, }; @@ -1696,7 +1667,6 @@ pub mod asynch { impl<'d, CH> ParlIoTx<'d, CH, crate::Async> where CH: DmaChannel, - CH::P: ParlIoPeripheral, { /// Perform a DMA write. /// @@ -1722,7 +1692,6 @@ pub mod asynch { impl<'d, CH> ParlIoRx<'d, CH, crate::Async> where CH: DmaChannel, - CH::P: ParlIoPeripheral, { /// Perform a DMA write. /// diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 0ebbc086c1d..faa30d03c7f 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -924,6 +924,7 @@ mod dma { DmaRxBuffer, DmaTxBuf, DmaTxBuffer, + PeripheralDmaChannel, Rx, Spi2Peripheral, SpiPeripheral, @@ -947,7 +948,7 @@ mod dma { channel: Channel<'d, C, DmaMode>, ) -> SpiDma<'d, crate::peripherals::SPI2, C, M, DmaMode> where - C: DmaChannel, + C: PeripheralDmaChannel, C::P: SpiPeripheral + Spi2Peripheral, DmaMode: Mode, { @@ -970,7 +971,7 @@ mod dma { channel: Channel<'d, C, DmaMode>, ) -> SpiDma<'d, crate::peripherals::SPI3, C, M, DmaMode> where - C: DmaChannel, + C: PeripheralDmaChannel, C::P: SpiPeripheral + Spi3Peripheral, DmaMode: Mode, { @@ -988,7 +989,6 @@ mod dma { pub struct SpiDma<'d, T, C, D, M> where C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1005,7 +1005,6 @@ mod dma { unsafe impl<'d, T, C, D, M> Send for SpiDma<'d, T, C, D, M> where C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1014,7 +1013,6 @@ mod dma { impl<'d, T, C, D, M> core::fmt::Debug for SpiDma<'d, T, C, D, M> where C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1031,11 +1029,14 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { - fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, C, M>) -> Self { + fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, C, M>) -> Self + where + C: PeripheralDmaChannel, + C::P: SpiPeripheral, + { #[cfg(all(esp32, spi_address_workaround))] let address_buffer = { use crate::dma::DmaDescriptor; @@ -1267,7 +1268,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1277,7 +1277,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1291,7 +1290,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1322,7 +1320,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1334,7 +1331,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1381,7 +1377,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1402,7 +1397,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, { /// Waits for the DMA transfer to complete asynchronously. @@ -1417,7 +1411,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, M: Mode, { /// # Safety: @@ -1530,7 +1523,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, M: Mode, { /// # Safety: @@ -1655,7 +1647,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1668,7 +1659,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1727,7 +1717,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1741,7 +1730,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, D: DuplexMode, M: Mode, { @@ -1751,7 +1739,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, M: Mode, { /// Reads data from the SPI bus using DMA. @@ -1847,7 +1834,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, M: Mode, { type Error = Error; @@ -1921,7 +1907,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, { type Error = Error; @@ -1936,7 +1921,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, { type Error = Error; @@ -1997,7 +1981,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, { /// Fill the given buffer with data from the bus. pub async fn read_async(&mut self, words: &mut [u8]) -> Result<(), Error> { @@ -2115,7 +2098,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, { async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { self.read_async(words).await @@ -2149,7 +2131,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, M: Mode, { type Error = Error; @@ -2159,7 +2140,6 @@ mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, M: Mode, { fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index 98d7bf318de..513e157b420 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -164,6 +164,7 @@ pub mod dma { DmaTransferRx, DmaTransferRxTx, DmaTransferTx, + PeripheralDmaChannel, ReadBuffer, Rx, Spi2Peripheral, @@ -185,7 +186,7 @@ pub mod dma { tx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI2, C, DmaMode> where - C: DmaChannel, + C: PeripheralDmaChannel, C::P: SpiPeripheral + Spi2Peripheral, DmaMode: Mode, { @@ -211,7 +212,7 @@ pub mod dma { tx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI3, C, DmaMode> where - C: DmaChannel, + C: PeripheralDmaChannel, C::P: SpiPeripheral + Spi3Peripheral, DmaMode: Mode, { @@ -229,7 +230,6 @@ pub mod dma { pub struct SpiDma<'d, T, C, DmaMode> where C: DmaChannel, - C::P: SpiPeripheral, DmaMode: Mode, { pub(crate) spi: PeripheralRef<'d, T>, @@ -241,7 +241,6 @@ pub mod dma { impl<'d, T, C, DmaMode> core::fmt::Debug for SpiDma<'d, T, C, DmaMode> where C: DmaChannel, - C::P: SpiPeripheral, DmaMode: Mode, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -253,7 +252,6 @@ pub mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, DmaMode: Mode, { fn peripheral_wait_dma(&mut self, is_rx: bool, is_tx: bool) { @@ -274,7 +272,6 @@ pub mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, DmaMode: Mode, { type TX = ChannelTx<'d, C>; @@ -292,7 +289,6 @@ pub mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, DmaMode: Mode, { type RX = ChannelRx<'d, C>; @@ -310,7 +306,6 @@ pub mod dma { where T: InstanceDma, C: DmaChannel, - C::P: SpiPeripheral, DmaMode: Mode, { /// Register a buffer for a DMA write. From b561a4308dcfb35970130025c4e37caac9478377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 1 Oct 2024 17:23:02 +0200 Subject: [PATCH 04/36] Remove Degraded assoc type --- esp-hal/src/dma/gdma.rs | 2 -- esp-hal/src/dma/mod.rs | 12 +++++------- esp-hal/src/dma/pdma.rs | 4 ---- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index 11544d766e3..08778a5b50e 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -466,8 +466,6 @@ macro_rules! impl_channel { } impl DmaChannelExt for [] { - type Degraded = AnyDmaChannel; - fn get_rx_interrupts() -> impl InterruptAccess { ChannelRxImpl(SpecificGdmaChannel::<$num> {}) } diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 9fcefd806ce..4488a61df9b 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1550,13 +1550,11 @@ impl crate::private::Sealed for AnyDmaChannel {} #[doc(hidden)] pub trait DmaChannelExt: DmaChannel { - type Degraded: DmaChannel; - fn get_rx_interrupts() -> impl InterruptAccess; fn get_tx_interrupts() -> impl InterruptAccess; - fn degrade_rx(rx: Self::Rx) -> ::Rx; - fn degrade_tx(tx: Self::Tx) -> ::Tx; + fn degrade_rx(rx: Self::Rx) -> ::Rx; + fn degrade_tx(tx: Self::Tx) -> ::Tx; #[doc(hidden)] fn set_isr(handler: InterruptHandler); @@ -1644,7 +1642,7 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelRx<'a, CH::Degraded> + pub fn degrade(self) -> ChannelRx<'a, AnyDmaChannel> where CH: DmaChannelExt, { @@ -1861,7 +1859,7 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelTx<'a, CH::Degraded> + pub fn degrade(self) -> ChannelTx<'a, AnyDmaChannel> where CH: DmaChannelExt, { @@ -2137,7 +2135,7 @@ where { /// Return a type-erased (degraded) version of this channel (both rx and /// tx). - pub fn degrade(self) -> Channel<'d, C::Degraded, M> { + pub fn degrade(self) -> Channel<'d, AnyDmaChannel, M> { Channel { rx: self.rx.degrade(), tx: self.tx.degrade(), diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index dcdf3dc8ae0..0b7f97b0601 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -355,8 +355,6 @@ macro_rules! ImplSpiChannel { } impl DmaChannelExt for [] { - type Degraded = AnyDmaChannel; - fn get_rx_interrupts() -> impl InterruptAccess { SpiDmaRxChannelImpl(Self {}) } @@ -792,8 +790,6 @@ macro_rules! ImplI2sChannel { } impl DmaChannelExt for [] { - type Degraded = AnyDmaChannel; - fn get_rx_interrupts() -> impl InterruptAccess { I2sDmaRxChannelImpl(Self {}) } From ebac0abfa14b0d8f5a7cb4e223763967ef5a1218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 1 Oct 2024 17:26:08 +0200 Subject: [PATCH 05/36] Move degrade fns to base trait --- esp-hal/src/dma/gdma.rs | 21 ++++++++++++++------- esp-hal/src/dma/mod.rs | 21 +++++++++------------ esp-hal/src/dma/pdma.rs | 36 ++++++++++++++++++++++-------------- 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index 08778a5b50e..ec5c6ff9ba2 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -442,6 +442,13 @@ impl LcdCamPeripheral for SuitablePeripheral {} impl DmaChannel for AnyDmaChannel { type Rx = ChannelRxImpl; type Tx = ChannelTxImpl; + + fn degrade_rx(rx: Self::Rx) -> ChannelRxImpl { + rx + } + fn degrade_tx(tx: Self::Tx) -> ChannelTxImpl { + tx + } } impl PeripheralDmaChannel for AnyDmaChannel { @@ -460,6 +467,13 @@ macro_rules! impl_channel { impl DmaChannel for [] { type Rx = ChannelRxImpl>; type Tx = ChannelTxImpl>; + + fn degrade_rx(rx: Self::Rx) -> ChannelRxImpl { + rx.degrade() + } + fn degrade_tx(tx: Self::Tx) -> ChannelTxImpl { + tx.degrade() + } } impl PeripheralDmaChannel for [] { type P = SuitablePeripheral; @@ -474,13 +488,6 @@ macro_rules! impl_channel { ChannelTxImpl(SpecificGdmaChannel::<$num> {}) } - fn degrade_rx(rx: Self::Rx) -> ChannelRxImpl { - rx.degrade() - } - fn degrade_tx(tx: Self::Tx) -> ChannelTxImpl { - tx.degrade() - } - fn set_isr(handler: $crate::interrupt::InterruptHandler) { let mut dma = unsafe { crate::peripherals::DMA::steal() }; $( diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 4488a61df9b..2033074740b 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1534,6 +1534,12 @@ pub trait DmaChannel: crate::private::Sealed { /// A description of the TX half of a DMA Channel. type Tx: TxRegisterAccess + InterruptAccess; + + // TODO: maybe document + #[doc(hidden)] + fn degrade_rx(rx: Self::Rx) -> ::Rx; + #[doc(hidden)] + fn degrade_tx(tx: Self::Tx) -> ::Tx; } /// A description of a DMA Channel that can be used with a peripheral. @@ -1553,9 +1559,6 @@ pub trait DmaChannelExt: DmaChannel { fn get_rx_interrupts() -> impl InterruptAccess; fn get_tx_interrupts() -> impl InterruptAccess; - fn degrade_rx(rx: Self::Rx) -> ::Rx; - fn degrade_tx(tx: Self::Tx) -> ::Tx; - #[doc(hidden)] fn set_isr(handler: InterruptHandler); } @@ -1642,10 +1645,7 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelRx<'a, AnyDmaChannel> - where - CH: DmaChannelExt, - { + pub fn degrade(self) -> ChannelRx<'a, AnyDmaChannel> { ChannelRx { burst_mode: self.burst_mode, rx_impl: CH::degrade_rx(self.rx_impl), @@ -1859,10 +1859,7 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelTx<'a, AnyDmaChannel> - where - CH: DmaChannelExt, - { + pub fn degrade(self) -> ChannelTx<'a, AnyDmaChannel> { ChannelTx { burst_mode: self.burst_mode, tx_impl: CH::degrade_tx(self.tx_impl), @@ -2131,7 +2128,7 @@ where impl<'d, C, M: Mode> Channel<'d, C, M> where - C: DmaChannelExt, + C: DmaChannel, { /// Return a type-erased (degraded) version of this channel (both rx and /// tx). diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 0b7f97b0601..21889d374d8 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -349,6 +349,13 @@ macro_rules! ImplSpiChannel { impl DmaChannel for [] { type Rx = SpiDmaRxChannelImpl; type Tx = SpiDmaTxChannelImpl; + + fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { + rx.degrade() + } + fn degrade_tx(tx: Self::Tx) -> AnyPdmaTxChannelImpl { + tx.degrade() + } } impl PeripheralDmaChannel for [] { type P = []; @@ -362,13 +369,6 @@ macro_rules! ImplSpiChannel { SpiDmaTxChannelImpl(Self {}) } - fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { - rx.degrade() - } - fn degrade_tx(tx: Self::Tx) -> AnyPdmaTxChannelImpl { - tx.degrade() - } - fn set_isr(handler: InterruptHandler) { let interrupt = $crate::peripherals::Interrupt::[< SPI $num _DMA >]; unsafe { @@ -784,6 +784,13 @@ macro_rules! ImplI2sChannel { impl DmaChannel for [] { type Rx = I2sDmaRxChannelImpl; type Tx = I2sDmaTxChannelImpl; + + fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { + rx.degrade() + } + fn degrade_tx(tx: Self::Tx) -> AnyPdmaTxChannelImpl { + tx.degrade() + } } impl PeripheralDmaChannel for [] { type P = []; @@ -797,13 +804,6 @@ macro_rules! ImplI2sChannel { I2sDmaTxChannelImpl(Self {}) } - fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { - rx.degrade() - } - fn degrade_tx(tx: Self::Tx) -> AnyPdmaTxChannelImpl { - tx.degrade() - } - fn set_isr(handler: InterruptHandler) { let interrupt = $crate::peripherals::Interrupt::[< I2S $num >]; unsafe { @@ -965,6 +965,14 @@ pub enum AnyPdmaChannel { impl DmaChannel for AnyDmaChannel { type Rx = AnyPdmaRxChannelImpl; type Tx = AnyPdmaTxChannelImpl; + + fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { + rx + } + + fn degrade_tx(tx: Self::Tx) -> AnyPdmaTxChannelImpl { + tx + } } #[doc(hidden)] From c8ab220565c0caf43550e8962c37d328762c6ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 1 Oct 2024 17:52:51 +0200 Subject: [PATCH 06/36] Use PeripheralDmaChannel on constructors only --- esp-hal/src/aes/mod.rs | 38 ++++++++++++++++---------------- esp-hal/src/i2s.rs | 4 +++- esp-hal/src/lcd_cam/cam.rs | 31 +++++++++++++++++++++----- esp-hal/src/lcd_cam/lcd/i8080.rs | 22 +++++++++++++----- esp-hal/src/parl_io.rs | 27 +++++++++++++++-------- 5 files changed, 81 insertions(+), 41 deletions(-) diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index b292c496a4b..8c56bb80353 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -236,6 +236,7 @@ pub mod dma { dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, AesPeripheral, + AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -252,8 +253,6 @@ pub mod dma { }, }; - type DefaultChannel = crate::dma::AnyDmaChannel; - const ALIGN_SIZE: usize = core::mem::size_of::(); /// Specifies the block cipher modes available for AES operations. @@ -273,7 +272,7 @@ pub mod dma { } /// A DMA capable AES instance. - pub struct AesDma<'d, C = DefaultChannel> + pub struct AesDma<'d, C = AnyDmaChannel> where C: DmaChannel, { @@ -285,32 +284,33 @@ pub mod dma { tx_chain: DescriptorChain, } - /// Functionality for using AES with DMA. - pub trait WithDmaAes<'d, C> - where - C: PeripheralDmaChannel, - C::P: AesPeripheral, - { + impl<'d> crate::aes::Aes<'d> { /// Enable DMA for the current instance of the AES driver - fn with_dma( + pub fn with_dma( self, channel: Channel<'d, C, crate::Blocking>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], - ) -> AesDma<'d, C>; - } + ) -> AesDma<'d> + where + Self: Sized, + C: PeripheralDmaChannel, + C::P: AesPeripheral, + { + self.with_dma_typed(channel.degrade(), rx_descriptors, tx_descriptors) + } - impl<'d, C> WithDmaAes<'d, C> for crate::aes::Aes<'d> - where - C: PeripheralDmaChannel, - C::P: AesPeripheral, - { - fn with_dma( + /// Enable DMA for the current instance of the AES driver + pub fn with_dma_typed( self, channel: Channel<'d, C, crate::Blocking>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], - ) -> AesDma<'d, C> { + ) -> AesDma<'d, C> + where + C: PeripheralDmaChannel, + C::P: AesPeripheral, + { AesDma { aes: self, channel, diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index dd151307695..42912f8a774 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -435,7 +435,7 @@ where impl<'d, I, CH, DmaMode> I2s<'d, I, CH, DmaMode> where I: RegisterAccess, - CH: PeripheralDmaChannel, + CH: DmaChannel, DmaMode: Mode, { /// Construct a new I2S peripheral driver instance for the first I2S @@ -452,6 +452,7 @@ where ) -> Self where I: I2s0Instance, + CH: PeripheralDmaChannel, CH::P: I2sPeripheral + I2s0Peripheral, DmaMode: Mode, { @@ -481,6 +482,7 @@ where ) -> Self where I: I2s1Instance, + CH: PeripheralDmaChannel, CH::P: I2sPeripheral + I2s1Peripheral, { Self::new_internal( diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index 282461264d1..ee3d585f448 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -82,6 +82,7 @@ use crate::{ DmaPeripheral, DmaRxBuffer, LcdCamPeripheral, + PeripheralDmaChannel, Rx, }, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull}, @@ -134,17 +135,35 @@ pub struct Camera<'d, CH: DmaChannel = AnyDmaChannel> { rx_channel: ChannelRx<'d, CH>, } -impl<'d, CH: DmaChannel> Camera<'d, CH> -where - CH::P: LcdCamPeripheral, -{ +impl<'d> Camera<'d> { /// Creates a new `Camera` instance with DMA support. - pub fn new( + pub fn new( + cam: Cam<'d>, + channel: ChannelRx<'d, CH>, + descriptors: &'static mut [DmaDescriptor], + pins: P, + frequency: HertzU32, + ) -> Self + where + CH: PeripheralDmaChannel, + CH::P: LcdCamPeripheral, + { + Self::new_typed(cam, channel.degrade(), descriptors, pins, frequency) + } +} + +impl<'d, CH: DmaChannel> Camera<'d, CH> { + /// Creates a new `Camera` instance with DMA support. + pub fn new_typed( cam: Cam<'d>, channel: ChannelRx<'d, CH>, _pins: P, frequency: HertzU32, - ) -> Self { + ) -> Self + where + CH: PeripheralDmaChannel, + CH::P: LcdCamPeripheral, + { let lcd_cam = cam.lcd_cam; let clocks = Clocks::get(); diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index e910c078e17..0db565d077e 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -69,7 +69,16 @@ use fugit::HertzU32; use crate::{ clock::Clocks, - dma::{ChannelTx, DmaChannel, DmaError, DmaPeripheral, DmaTxBuffer, LcdCamPeripheral, Tx}, + dma::{ + ChannelTx, + DmaChannel, + DmaError, + DmaPeripheral, + DmaTxBuffer, + LcdCamPeripheral, + PeripheralDmaChannel, + Tx, + }, gpio::{OutputSignal, PeripheralOutput}, lcd_cam::{ asynch::LCD_DONE_WAKER, @@ -91,10 +100,7 @@ pub struct I8080<'d, CH: DmaChannel, DM: Mode> { _phantom: PhantomData, } -impl<'d, CH: DmaChannel, DM: Mode> I8080<'d, CH, DM> -where - CH::P: LcdCamPeripheral, -{ +impl<'d, CH: DmaChannel, DM: Mode> I8080<'d, CH, DM> { /// Creates a new instance of the I8080 LCD interface. pub fn new( lcd: Lcd<'d, DM>, @@ -102,7 +108,11 @@ where mut pins: P, frequency: HertzU32, config: Config, - ) -> Self { + ) -> Self + where + CH: PeripheralDmaChannel, + CH::P: LcdCamPeripheral, + { let lcd_cam = lcd.lcd_cam; let clocks = Clocks::get(); diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index eb48a6fb339..2e8b15059bb 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -1099,8 +1099,7 @@ where impl<'d, CH, DM> ParlIoFullDuplex<'d, CH, DM> where - CH: PeripheralDmaChannel, - CH::P: ParlIoPeripheral, + CH: DmaChannel, DM: Mode, { /// Create a new instance of [ParlIoFullDuplex] @@ -1110,7 +1109,11 @@ where tx_descriptors: &'static mut [DmaDescriptor], rx_descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, - ) -> Result { + ) -> Result + where + CH: PeripheralDmaChannel, + CH::P: ParlIoPeripheral, + { internal_init(frequency)?; Ok(Self { @@ -1185,8 +1188,7 @@ where impl<'d, CH, DM> ParlIoTxOnly<'d, CH, DM> where - CH: PeripheralDmaChannel, - CH::P: ParlIoPeripheral, + CH: DmaChannel, DM: Mode, { /// Create a new [ParlIoTxOnly] @@ -1195,7 +1197,11 @@ where dma_channel: Channel<'d, CH, DM>, descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, - ) -> Result { + ) -> Result + where + CH: PeripheralDmaChannel, + CH::P: ParlIoPeripheral, + { internal_init(frequency)?; Ok(Self { @@ -1265,8 +1271,7 @@ where impl<'d, CH, DM> ParlIoRxOnly<'d, CH, DM> where - CH: PeripheralDmaChannel, - CH::P: ParlIoPeripheral, + CH: DmaChannel, DM: Mode, { /// Create a new [ParlIoRxOnly] instance @@ -1275,7 +1280,11 @@ where dma_channel: Channel<'d, CH, DM>, descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, - ) -> Result { + ) -> Result + where + CH: PeripheralDmaChannel, + CH::P: ParlIoPeripheral, + { internal_init(frequency)?; Ok(Self { From 68c13cda7ca9c2c32e5bf0c4e26fda1462701f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 1 Oct 2024 18:07:31 +0200 Subject: [PATCH 07/36] Remove WithDmaAes use --- esp-hal/CHANGELOG.md | 1 + hil-test/tests/aes_dma.rs | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index f129e75067b..b6977bb6cf6 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -107,6 +107,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed the `place-spi-driver-in-ram` feature, this is now enabled via [esp-config](https://docs.rs/esp-config) (#2156) - Removed `esp_hal::spi::slave::prelude` (#2260) - Removed `esp_hal::spi::slave::WithDmaSpiN` traits (#2260) +- The `WithDmaAes` trait has been removed (#2261) ## [0.20.1] - 2024-08-30 diff --git a/hil-test/tests/aes_dma.rs b/hil-test/tests/aes_dma.rs index 3d0accd1fd5..3fdb98db1ff 100644 --- a/hil-test/tests/aes_dma.rs +++ b/hil-test/tests/aes_dma.rs @@ -6,11 +6,7 @@ #![no_main] use esp_hal::{ - aes::{ - dma::{CipherMode, WithDmaAes}, - Aes, - Mode, - }, + aes::{dma::CipherMode, Aes, Mode}, dma::{Dma, DmaPriority}, dma_buffers, peripherals::Peripherals, From 8a1bcc7ffe6a29e400f6dd1f621900c9869ec714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Wed, 2 Oct 2024 15:11:27 +0200 Subject: [PATCH 08/36] Erase DMA type params --- esp-hal/src/aes/mod.rs | 53 ++-------- esp-hal/src/dma/gdma.rs | 87 +++++++++------- esp-hal/src/dma/pdma.rs | 2 +- esp-hal/src/i2s.rs | 155 ++++++++++++---------------- esp-hal/src/lcd_cam/cam.rs | 49 +++------ esp-hal/src/lcd_cam/lcd/i8080.rs | 37 +++---- esp-hal/src/parl_io.rs | 172 +++++++++++-------------------- esp-hal/src/spi/master.rs | 117 +++++++++------------ esp-hal/src/spi/slave.rs | 59 +++++------ 9 files changed, 297 insertions(+), 434 deletions(-) diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index 8c56bb80353..d523f974621 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -241,7 +241,6 @@ pub mod dma { ChannelRx, ChannelTx, DescriptorChain, - DmaChannel, DmaDescriptor, DmaPeripheral, DmaTransferRxTx, @@ -272,14 +271,11 @@ pub mod dma { } /// A DMA capable AES instance. - pub struct AesDma<'d, C = AnyDmaChannel> - where - C: DmaChannel, - { + pub struct AesDma<'d> { /// The underlying [`Aes`](super::Aes) driver pub aes: super::Aes<'d>, - pub(crate) channel: Channel<'d, C, crate::Blocking>, + channel: Channel<'d, AnyDmaChannel, crate::Blocking>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, } @@ -296,43 +292,23 @@ pub mod dma { Self: Sized, C: PeripheralDmaChannel, C::P: AesPeripheral, - { - self.with_dma_typed(channel.degrade(), rx_descriptors, tx_descriptors) - } - - /// Enable DMA for the current instance of the AES driver - pub fn with_dma_typed( - self, - channel: Channel<'d, C, crate::Blocking>, - rx_descriptors: &'static mut [DmaDescriptor], - tx_descriptors: &'static mut [DmaDescriptor], - ) -> AesDma<'d, C> - where - C: PeripheralDmaChannel, - C::P: AesPeripheral, { AesDma { aes: self, - channel, + channel: channel.degrade(), rx_chain: DescriptorChain::new(rx_descriptors), tx_chain: DescriptorChain::new(tx_descriptors), } } } - impl<'d, C> core::fmt::Debug for AesDma<'d, C> - where - C: DmaChannel, - { + impl<'d> core::fmt::Debug for AesDma<'d> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("AesDma").finish() } } - impl<'d, C> DmaSupport for AesDma<'d, C> - where - C: DmaChannel, - { + impl<'d> DmaSupport for AesDma<'d> { fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { while self.aes.aes.state().read().state().bits() != 2 // DMA status DONE == 2 && !self.channel.tx.is_done() @@ -348,11 +324,8 @@ pub mod dma { } } - impl<'d, C> DmaSupportTx for AesDma<'d, C> - where - C: DmaChannel, - { - type TX = ChannelTx<'d, C>; + impl<'d> DmaSupportTx for AesDma<'d> { + type TX = ChannelTx<'d, AnyDmaChannel>; fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx @@ -363,11 +336,8 @@ pub mod dma { } } - impl<'d, C> DmaSupportRx for AesDma<'d, C> - where - C: DmaChannel, - { - type RX = ChannelRx<'d, C>; + impl<'d> DmaSupportRx for AesDma<'d> { + type RX = ChannelRx<'d, AnyDmaChannel>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx @@ -378,10 +348,7 @@ pub mod dma { } } - impl<'d, C> AesDma<'d, C> - where - C: DmaChannel, - { + impl<'d> AesDma<'d> { /// Writes the encryption key to the AES hardware, checking that its /// length matches expected constraints. pub fn write_key(&mut self, key: K) diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index ec5c6ff9ba2..3d8bae2622c 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -630,21 +630,25 @@ pub use m2m::*; mod m2m { #[cfg(esp32s3)] use crate::dma::DmaExtMemBKSize; - use crate::dma::{ - dma_private::{DmaSupport, DmaSupportRx}, - Channel, - ChannelRx, - DescriptorChain, - DmaChannel, - DmaDescriptor, - DmaEligible, - DmaError, - DmaPeripheral, - DmaTransferRx, - ReadBuffer, - Rx, - Tx, - WriteBuffer, + use crate::{ + dma::{ + dma_private::{DmaSupport, DmaSupportRx}, + AnyDmaChannel, + Channel, + ChannelRx, + DescriptorChain, + DmaChannel, + DmaDescriptor, + DmaEligible, + DmaError, + DmaPeripheral, + DmaTransferRx, + ReadBuffer, + Rx, + Tx, + WriteBuffer, + }, + Mode, }; /// DMA Memory to Memory pseudo-Peripheral @@ -652,29 +656,30 @@ mod m2m { /// This is a pseudo-peripheral that allows for memory to memory transfers. /// It is not a real peripheral, but a way to use the DMA engine for memory /// to memory transfers. - pub struct Mem2Mem<'d, C, MODE> + pub struct Mem2Mem<'d, M> where - C: DmaChannel, - MODE: crate::Mode, + M: Mode, { - channel: Channel<'d, C, MODE>, + channel: Channel<'d, AnyDmaChannel, M>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, peripheral: DmaPeripheral, } - impl<'d, C, MODE> Mem2Mem<'d, C, MODE> + impl<'d, M> Mem2Mem<'d, M> where - C: DmaChannel, - MODE: crate::Mode, + M: Mode, { /// Create a new Mem2Mem instance. - pub fn new( - channel: Channel<'d, C, MODE>, + pub fn new( + channel: Channel<'d, CH, M>, peripheral: impl DmaEligible, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], - ) -> Result { + ) -> Result + where + CH: DmaChannel, + { unsafe { Self::new_unsafe( channel, @@ -687,13 +692,16 @@ mod m2m { } /// Create a new Mem2Mem instance with specific chunk size. - pub fn new_with_chunk_size( - channel: Channel<'d, C, MODE>, + pub fn new_with_chunk_size( + channel: Channel<'d, CH, M>, peripheral: impl DmaEligible, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], chunk_size: usize, - ) -> Result { + ) -> Result + where + CH: DmaChannel, + { unsafe { Self::new_unsafe( channel, @@ -711,13 +719,16 @@ mod m2m { /// /// You must ensure that your not using DMA for the same peripheral and /// that your the only one using the DmaPeripheral. - pub unsafe fn new_unsafe( - channel: Channel<'d, C, MODE>, + pub unsafe fn new_unsafe( + channel: Channel<'d, CH, M>, peripheral: DmaPeripheral, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], chunk_size: usize, - ) -> Result { + ) -> Result + where + CH: DmaChannel, + { if !(1..=4092).contains(&chunk_size) { return Err(DmaError::InvalidChunkSize); } @@ -725,7 +736,7 @@ mod m2m { return Err(DmaError::OutOfDescriptors); } Ok(Mem2Mem { - channel, + channel: channel.degrade(), peripheral, rx_chain: DescriptorChain::new_with_chunk_size(rx_descriptors, chunk_size), tx_chain: DescriptorChain::new_with_chunk_size(tx_descriptors, chunk_size), @@ -776,10 +787,9 @@ mod m2m { } } - impl<'d, C, MODE> DmaSupport for Mem2Mem<'d, C, MODE> + impl<'d, MODE> DmaSupport for Mem2Mem<'d, MODE> where - C: DmaChannel, - MODE: crate::Mode, + MODE: Mode, { fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { while !self.channel.rx.is_done() {} @@ -790,12 +800,11 @@ mod m2m { } } - impl<'d, C, MODE> DmaSupportRx for Mem2Mem<'d, C, MODE> + impl<'d, MODE> DmaSupportRx for Mem2Mem<'d, MODE> where - C: DmaChannel, - MODE: crate::Mode, + MODE: Mode, { - type RX = ChannelRx<'d, C>; + type RX = ChannelRx<'d, AnyDmaChannel>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 21889d374d8..f4304518e27 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -805,7 +805,7 @@ macro_rules! ImplI2sChannel { } fn set_isr(handler: InterruptHandler) { - let interrupt = $crate::peripherals::Interrupt::[< I2S $num >]; + let interrupt = $crate::peripherals::Interrupt::[< I2S $num >]; unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()); } diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index 42912f8a774..ca772aca7b4 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -89,6 +89,7 @@ use crate::dma::I2s1Peripheral; use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, + AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -263,10 +264,9 @@ pub trait I2sWrite { } /// Initiate a DMA tx transfer -pub trait I2sWriteDma<'d, T, CH, TXBUF, DmaMode> +pub trait I2sWriteDma<'d, T, TXBUF, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, Self: DmaSupportTx + Sized, { @@ -295,10 +295,9 @@ pub trait I2sRead { } /// Initiate a DMA rx transfer -pub trait I2sReadDma<'d, T, CH, RXBUF, DmaMode> +pub trait I2sReadDma<'d, T, RXBUF, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, Self: DmaSupportRx + Sized, { @@ -321,27 +320,25 @@ where } /// Instance of the I2S peripheral driver -pub struct I2s<'d, I, CH, DmaMode> +pub struct I2s<'d, I, DmaMode> where I: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { /// Handles the reception (RX) side of the I2S peripheral. - pub i2s_rx: RxCreator<'d, I, CH, DmaMode>, + pub i2s_rx: RxCreator<'d, I, DmaMode>, /// Handles the transmission (TX) side of the I2S peripheral. - pub i2s_tx: TxCreator<'d, I, CH, DmaMode>, + pub i2s_tx: TxCreator<'d, I, DmaMode>, phantom: PhantomData, } -impl<'d, I, CH, DmaMode> I2s<'d, I, CH, DmaMode> +impl<'d, I, DmaMode> I2s<'d, I, DmaMode> where I: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { #[allow(clippy::too_many_arguments)] - fn new_internal( + fn new_internal( _i2s: impl Peripheral

+ 'd, standard: Standard, data_format: DataFormat, @@ -361,6 +358,7 @@ where I::set_master(); I::update(); + let channel = channel.degrade(); Self { i2s_rx: RxCreator { register_access: PhantomData, @@ -379,10 +377,9 @@ where } } -impl<'d, I, CH, DmaMode> I2s<'d, I, CH, DmaMode> +impl<'d, I, DmaMode> I2s<'d, I, DmaMode> where I: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { /// Sets the interrupt handler @@ -413,18 +410,16 @@ where } } -impl<'d, I, CH, DmaMode> crate::private::Sealed for I2s<'d, I, CH, DmaMode> +impl<'d, I, DmaMode> crate::private::Sealed for I2s<'d, I, DmaMode> where I: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { } -impl<'d, I, CH, DmaMode> InterruptConfigurable for I2s<'d, I, CH, DmaMode> +impl<'d, I, DmaMode> InterruptConfigurable for I2s<'d, I, DmaMode> where I: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) { @@ -432,16 +427,15 @@ where } } -impl<'d, I, CH, DmaMode> I2s<'d, I, CH, DmaMode> +impl<'d, I, DmaMode> I2s<'d, I, DmaMode> where I: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { /// Construct a new I2S peripheral driver instance for the first I2S /// peripheral #[allow(clippy::too_many_arguments)] - pub fn new( + pub fn new( i2s: impl Peripheral

+ 'd, standard: Standard, data_format: DataFormat, @@ -471,7 +465,7 @@ where /// peripheral #[allow(clippy::too_many_arguments)] #[cfg(i2s1)] - pub fn new_i2s1( + pub fn new_i2s1( i2s: impl Peripheral

+ 'd, standard: Standard, data_format: DataFormat, @@ -507,21 +501,19 @@ where } /// I2S TX channel -pub struct I2sTx<'d, T, CH, DmaMode> +pub struct I2sTx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, { register_access: PhantomData, - tx_channel: ChannelTx<'d, CH>, + tx_channel: ChannelTx<'d, AnyDmaChannel>, tx_chain: DescriptorChain, phantom: PhantomData, } -impl<'d, T, CH, DmaMode> core::fmt::Debug for I2sTx<'d, T, CH, DmaMode> +impl<'d, T, DmaMode> core::fmt::Debug for I2sTx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -529,10 +521,9 @@ where } } -impl<'d, T, CH, DmaMode> DmaSupport for I2sTx<'d, T, CH, DmaMode> +impl<'d, T, DmaMode> DmaSupport for I2sTx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { @@ -544,13 +535,12 @@ where } } -impl<'d, T, CH, DmaMode> DmaSupportTx for I2sTx<'d, T, CH, DmaMode> +impl<'d, T, DmaMode> DmaSupportTx for I2sTx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { - type TX = ChannelTx<'d, CH>; + type TX = ChannelTx<'d, AnyDmaChannel>; fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel @@ -561,13 +551,15 @@ where } } -impl<'d, T, CH, DmaMode> I2sTx<'d, T, CH, DmaMode> +impl<'d, T, DmaMode> I2sTx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { - fn new(tx_channel: ChannelTx<'d, CH>, descriptors: &'static mut [DmaDescriptor]) -> Self { + fn new( + tx_channel: ChannelTx<'d, AnyDmaChannel>, + descriptors: &'static mut [DmaDescriptor], + ) -> Self { Self { register_access: PhantomData, tx_channel, @@ -636,10 +628,9 @@ where } } -impl<'d, T, W, CH, DmaMode> I2sWrite for I2sTx<'d, T, CH, DmaMode> +impl<'d, T, W, DmaMode> I2sWrite for I2sTx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, W: AcceptedWord, DmaMode: Mode, { @@ -650,10 +641,9 @@ where } } -impl<'d, T, CH, TXBUF, DmaMode> I2sWriteDma<'d, T, CH, TXBUF, DmaMode> for I2sTx<'d, T, CH, DmaMode> +impl<'d, T, TXBUF, DmaMode> I2sWriteDma<'d, T, TXBUF, DmaMode> for I2sTx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { fn write_dma<'t>(&'t mut self, words: &'t TXBUF) -> Result, Error> @@ -677,22 +667,20 @@ where } /// I2S RX channel -pub struct I2sRx<'d, T, CH, DmaMode> +pub struct I2sRx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { register_access: PhantomData, - rx_channel: ChannelRx<'d, CH>, + rx_channel: ChannelRx<'d, AnyDmaChannel>, rx_chain: DescriptorChain, phantom: PhantomData, } -impl<'d, T, CH, DmaMode> core::fmt::Debug for I2sRx<'d, T, CH, DmaMode> +impl<'d, T, DmaMode> core::fmt::Debug for I2sRx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -700,10 +688,9 @@ where } } -impl<'d, T, CH, DmaMode> DmaSupport for I2sRx<'d, T, CH, DmaMode> +impl<'d, T, DmaMode> DmaSupport for I2sRx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { @@ -715,13 +702,12 @@ where } } -impl<'d, T, CH, DmaMode> DmaSupportRx for I2sRx<'d, T, CH, DmaMode> +impl<'d, T, DmaMode> DmaSupportRx for I2sRx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { - type RX = ChannelRx<'d, CH>; + type RX = ChannelRx<'d, AnyDmaChannel>; fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel @@ -732,13 +718,15 @@ where } } -impl<'d, T, CH, DmaMode> I2sRx<'d, T, CH, DmaMode> +impl<'d, T, DmaMode> I2sRx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { - fn new(rx_channel: ChannelRx<'d, CH>, descriptors: &'static mut [DmaDescriptor]) -> Self { + fn new( + rx_channel: ChannelRx<'d, AnyDmaChannel>, + descriptors: &'static mut [DmaDescriptor], + ) -> Self { Self { register_access: PhantomData, rx_channel, @@ -805,10 +793,9 @@ where } } -impl<'d, W, T, CH, DmaMode> I2sRead for I2sRx<'d, T, CH, DmaMode> +impl<'d, W, T, DmaMode> I2sRead for I2sRx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, W: AcceptedWord, DmaMode: Mode, { @@ -826,10 +813,9 @@ where } } -impl<'d, T, CH, RXBUF, DmaMode> I2sReadDma<'d, T, CH, RXBUF, DmaMode> for I2sRx<'d, T, CH, DmaMode> +impl<'d, T, RXBUF, DmaMode> I2sReadDma<'d, T, RXBUF, DmaMode> for I2sRx<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, Self: DmaSupportRx + Sized, { @@ -878,7 +864,7 @@ mod private { #[cfg(any(esp32, esp32s3))] use crate::peripherals::{i2s1::RegisterBlock, I2S1}; use crate::{ - dma::{ChannelRx, ChannelTx, DmaChannel, DmaDescriptor, DmaPeripheral}, + dma::{AnyDmaChannel, ChannelRx, ChannelTx, DmaDescriptor, DmaPeripheral}, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, into_ref, @@ -888,25 +874,23 @@ mod private { Mode, }; - pub struct TxCreator<'d, T, CH, DmaMode> + pub struct TxCreator<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { pub register_access: PhantomData, - pub tx_channel: ChannelTx<'d, CH>, + pub tx_channel: ChannelTx<'d, AnyDmaChannel>, pub descriptors: &'static mut [DmaDescriptor], pub(crate) phantom: PhantomData, } - impl<'d, T, CH, DmaMode> TxCreator<'d, T, CH, DmaMode> + impl<'d, T, DmaMode> TxCreator<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { - pub fn build(self) -> I2sTx<'d, T, CH, DmaMode> { + pub fn build(self) -> I2sTx<'d, T, DmaMode> { I2sTx::new(self.tx_channel, self.descriptors) } @@ -944,25 +928,23 @@ mod private { } } - pub struct RxCreator<'d, T, CH, DmaMode> + pub struct RxCreator<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { pub register_access: PhantomData, - pub rx_channel: ChannelRx<'d, CH>, + pub rx_channel: ChannelRx<'d, AnyDmaChannel>, pub descriptors: &'static mut [DmaDescriptor], pub(crate) phantom: PhantomData, } - impl<'d, T, CH, DmaMode> RxCreator<'d, T, CH, DmaMode> + impl<'d, T, DmaMode> RxCreator<'d, T, DmaMode> where T: RegisterAccess, - CH: DmaChannel, DmaMode: Mode, { - pub fn build(self) -> I2sRx<'d, T, CH, DmaMode> { + pub fn build(self) -> I2sRx<'d, T, DmaMode> { I2sRx::new(self.rx_channel, self.descriptors) } @@ -2069,7 +2051,6 @@ pub mod asynch { use crate::{ dma::{ asynch::{DmaRxDoneChFuture, DmaRxFuture, DmaTxDoneChFuture, DmaTxFuture}, - DmaChannel, ReadBuffer, Rx, RxCircularState, @@ -2081,10 +2062,9 @@ pub mod asynch { }; /// Initiate an async DMA tx transfer - pub trait I2sWriteDmaAsync<'d, T, CH> + pub trait I2sWriteDmaAsync<'d, T> where T: RegisterAccess, - CH: DmaChannel, { /// One-shot write I2S. async fn write_dma_async(&mut self, words: &mut [u8]) -> Result<(), Error>; @@ -2093,15 +2073,14 @@ pub mod asynch { fn write_dma_circular_async( self, words: TXBUF, - ) -> Result, Error> + ) -> Result, Error> where TXBUF: ReadBuffer; } - impl<'d, T, CH> I2sWriteDmaAsync<'d, T, CH> for super::I2sTx<'d, T, CH, Async> + impl<'d, T> I2sWriteDmaAsync<'d, T> for super::I2sTx<'d, T, Async> where T: RegisterAccess, - CH: DmaChannel, { async fn write_dma_async(&mut self, words: &mut [u8]) -> Result<(), Error> { let (ptr, len) = (words.as_ptr(), words.len()); @@ -2127,7 +2106,7 @@ pub mod asynch { fn write_dma_circular_async( mut self, words: TXBUF, - ) -> Result, Error> + ) -> Result, Error> where TXBUF: ReadBuffer, { @@ -2161,20 +2140,18 @@ pub mod asynch { } /// An in-progress async circular DMA write transfer. - pub struct I2sWriteDmaTransferAsync<'d, T, CH, BUFFER> + pub struct I2sWriteDmaTransferAsync<'d, T, BUFFER> where T: RegisterAccess, - CH: DmaChannel, { - i2s_tx: I2sTx<'d, T, CH, Async>, + i2s_tx: I2sTx<'d, T, Async>, state: TxCircularState, _buffer: BUFFER, } - impl<'d, T, CH, BUFFER> I2sWriteDmaTransferAsync<'d, T, CH, BUFFER> + impl<'d, T, BUFFER> I2sWriteDmaTransferAsync<'d, T, BUFFER> where T: RegisterAccess, - CH: DmaChannel, { /// How many bytes can be pushed into the DMA transaction. /// Will wait for more than 0 bytes available. @@ -2213,10 +2190,9 @@ pub mod asynch { } /// Initiate an async DMA rx transfer - pub trait I2sReadDmaAsync<'d, T, CH> + pub trait I2sReadDmaAsync<'d, T> where T: RegisterAccess, - CH: DmaChannel, { /// One-shot read I2S. async fn read_dma_async(&mut self, words: &mut [u8]) -> Result<(), Error>; @@ -2225,15 +2201,14 @@ pub mod asynch { fn read_dma_circular_async( self, words: RXBUF, - ) -> Result, Error> + ) -> Result, Error> where RXBUF: WriteBuffer; } - impl<'d, T, CH> I2sReadDmaAsync<'d, T, CH> for super::I2sRx<'d, T, CH, Async> + impl<'d, T> I2sReadDmaAsync<'d, T> for super::I2sRx<'d, T, Async> where T: RegisterAccess, - CH: DmaChannel, { async fn read_dma_async(&mut self, words: &mut [u8]) -> Result<(), Error> { let (ptr, len) = (words.as_mut_ptr(), words.len()); @@ -2267,7 +2242,7 @@ pub mod asynch { fn read_dma_circular_async( mut self, mut words: RXBUF, - ) -> Result, Error> + ) -> Result, Error> where RXBUF: WriteBuffer, { @@ -2303,20 +2278,18 @@ pub mod asynch { } /// An in-progress async circular DMA read transfer. - pub struct I2sReadDmaTransferAsync<'d, T, CH, BUFFER> + pub struct I2sReadDmaTransferAsync<'d, T, BUFFER> where T: RegisterAccess, - CH: DmaChannel, { - i2s_rx: I2sRx<'d, T, CH, Async>, + i2s_rx: I2sRx<'d, T, Async>, state: RxCircularState, _buffer: BUFFER, } - impl<'d, T, CH, BUFFER> I2sReadDmaTransferAsync<'d, T, CH, BUFFER> + impl<'d, T, BUFFER> I2sReadDmaTransferAsync<'d, T, BUFFER> where T: RegisterAccess, - CH: DmaChannel, { /// How many bytes can be popped from the DMA transaction. /// Will wait for more than 0 bytes available. diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index ee3d585f448..574fc578f31 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -77,7 +77,6 @@ use crate::{ dma::{ AnyDmaChannel, ChannelRx, - DmaChannel, DmaError, DmaPeripheral, DmaRxBuffer, @@ -130,31 +129,14 @@ pub struct Cam<'d> { } /// Represents the camera interface with DMA support. -pub struct Camera<'d, CH: DmaChannel = AnyDmaChannel> { +pub struct Camera<'d> { lcd_cam: PeripheralRef<'d, LCD_CAM>, - rx_channel: ChannelRx<'d, CH>, + rx_channel: ChannelRx<'d, AnyDmaChannel>, } impl<'d> Camera<'d> { /// Creates a new `Camera` instance with DMA support. - pub fn new( - cam: Cam<'d>, - channel: ChannelRx<'d, CH>, - descriptors: &'static mut [DmaDescriptor], - pins: P, - frequency: HertzU32, - ) -> Self - where - CH: PeripheralDmaChannel, - CH::P: LcdCamPeripheral, - { - Self::new_typed(cam, channel.degrade(), descriptors, pins, frequency) - } -} - -impl<'d, CH: DmaChannel> Camera<'d, CH> { - /// Creates a new `Camera` instance with DMA support. - pub fn new_typed( + pub fn new( cam: Cam<'d>, channel: ChannelRx<'d, CH>, _pins: P, @@ -163,6 +145,7 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> { where CH: PeripheralDmaChannel, CH::P: LcdCamPeripheral, + P: RxPins, { let lcd_cam = cam.lcd_cam; @@ -209,12 +192,12 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> { Self { lcd_cam, - rx_channel: channel, + rx_channel: channel.degrade(), } } } -impl<'d, CH: DmaChannel> Camera<'d, CH> { +impl<'d> Camera<'d> { /// Configures the byte order for the camera data. pub fn set_byte_order(&mut self, byte_order: ByteOrder) -> &mut Self { self.lcd_cam @@ -339,7 +322,7 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> { pub fn receive( mut self, mut buf: BUF, - ) -> Result, (DmaError, Self, BUF)> { + ) -> Result, (DmaError, Self, BUF)> { // Reset Camera control unit and Async Rx FIFO self.lcd_cam .cam_ctrl1() @@ -385,12 +368,12 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> { /// Represents an ongoing (or potentially stopped) transfer from the Camera to a /// DMA buffer. -pub struct CameraTransfer<'d, BUF: DmaRxBuffer, CH: DmaChannel = AnyDmaChannel> { - camera: ManuallyDrop>, +pub struct CameraTransfer<'d, BUF: DmaRxBuffer> { + camera: ManuallyDrop>, buffer_view: ManuallyDrop, } -impl<'d, BUF: DmaRxBuffer, CH: DmaChannel> CameraTransfer<'d, BUF, CH> { +impl<'d, BUF: DmaRxBuffer> CameraTransfer<'d, BUF> { /// Returns true when [Self::wait] will not block. pub fn is_done(&self) -> bool { // This peripheral doesn't really "complete". As long the camera (or anything @@ -418,7 +401,7 @@ impl<'d, BUF: DmaRxBuffer, CH: DmaChannel> CameraTransfer<'d, BUF, CH> { } /// Stops this transfer on the spot and returns the peripheral and buffer. - pub fn stop(mut self) -> (Camera<'d, CH>, BUF) { + pub fn stop(mut self) -> (Camera<'d>, BUF) { self.stop_peripherals(); let (camera, view) = self.release(); (camera, BUF::from_view(view)) @@ -429,7 +412,7 @@ impl<'d, BUF: DmaRxBuffer, CH: DmaChannel> CameraTransfer<'d, BUF, CH> { /// Note: The camera doesn't really "finish" its transfer, so what you're /// really waiting for here is a DMA Error. You typically just want to /// call [Self::stop] once you have the data you need. - pub fn wait(mut self) -> (Result<(), DmaError>, Camera<'d, CH>, BUF) { + pub fn wait(mut self) -> (Result<(), DmaError>, Camera<'d>, BUF) { while !self.is_done() {} // Stop the DMA as it doesn't know that the camera has stopped. @@ -448,7 +431,7 @@ impl<'d, BUF: DmaRxBuffer, CH: DmaChannel> CameraTransfer<'d, BUF, CH> { (result, camera, BUF::from_view(view)) } - fn release(mut self) -> (Camera<'d, CH>, BUF::View) { + fn release(mut self) -> (Camera<'d>, BUF::View) { // SAFETY: Since forget is called on self, we know that self.camera and // self.buffer_view won't be touched again. let result = unsafe { @@ -472,7 +455,7 @@ impl<'d, BUF: DmaRxBuffer, CH: DmaChannel> CameraTransfer<'d, BUF, CH> { } } -impl<'d, BUF: DmaRxBuffer, CH: DmaChannel> Deref for CameraTransfer<'d, BUF, CH> { +impl<'d, BUF: DmaRxBuffer> Deref for CameraTransfer<'d, BUF> { type Target = BUF::View; fn deref(&self) -> &Self::Target { @@ -480,13 +463,13 @@ impl<'d, BUF: DmaRxBuffer, CH: DmaChannel> Deref for CameraTransfer<'d, BUF, CH> } } -impl<'d, BUF: DmaRxBuffer, CH: DmaChannel> DerefMut for CameraTransfer<'d, BUF, CH> { +impl<'d, BUF: DmaRxBuffer> DerefMut for CameraTransfer<'d, BUF> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buffer_view } } -impl<'d, BUF: DmaRxBuffer, CH: DmaChannel> Drop for CameraTransfer<'d, BUF, CH> { +impl<'d, BUF: DmaRxBuffer> Drop for CameraTransfer<'d, BUF> { fn drop(&mut self) { self.stop_peripherals(); diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index 0db565d077e..bc443a5ca4d 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -70,8 +70,8 @@ use fugit::HertzU32; use crate::{ clock::Clocks, dma::{ + AnyDmaChannel, ChannelTx, - DmaChannel, DmaError, DmaPeripheral, DmaTxBuffer, @@ -94,15 +94,15 @@ use crate::{ }; /// Represents the I8080 LCD interface. -pub struct I8080<'d, CH: DmaChannel, DM: Mode> { +pub struct I8080<'d, DM: Mode> { lcd_cam: PeripheralRef<'d, LCD_CAM>, - tx_channel: ChannelTx<'d, CH>, + tx_channel: ChannelTx<'d, AnyDmaChannel>, _phantom: PhantomData, } -impl<'d, CH: DmaChannel, DM: Mode> I8080<'d, CH, DM> { +impl<'d, DM: Mode> I8080<'d, DM> { /// Creates a new instance of the I8080 LCD interface. - pub fn new( + pub fn new( lcd: Lcd<'d, DM>, channel: ChannelTx<'d, CH>, mut pins: P, @@ -112,6 +112,7 @@ impl<'d, CH: DmaChannel, DM: Mode> I8080<'d, CH, DM> { where CH: PeripheralDmaChannel, CH::P: LcdCamPeripheral, + P: TxPins, { let lcd_cam = lcd.lcd_cam; @@ -215,13 +216,13 @@ impl<'d, CH: DmaChannel, DM: Mode> I8080<'d, CH, DM> { Self { lcd_cam, - tx_channel: channel, + tx_channel: channel.degrade(), _phantom: PhantomData, } } } -impl<'d, CH: DmaChannel, DM: Mode> I8080<'d, CH, DM> { +impl<'d, DM: Mode> I8080<'d, DM> { /// Configures the byte order for data transmission. pub fn set_byte_order(&mut self, byte_order: ByteOrder) -> &mut Self { let is_inverted = byte_order != ByteOrder::default(); @@ -280,7 +281,7 @@ impl<'d, CH: DmaChannel, DM: Mode> I8080<'d, CH, DM> { cmd: impl Into>, dummy: u8, mut data: BUF, - ) -> Result, (DmaError, Self, BUF)> { + ) -> Result, (DmaError, Self, BUF)> { let cmd = cmd.into(); // Reset LCD control unit and Async Tx FIFO @@ -376,7 +377,7 @@ impl<'d, CH: DmaChannel, DM: Mode> I8080<'d, CH, DM> { } } -impl<'d, CH: DmaChannel, DM: Mode> core::fmt::Debug for I8080<'d, CH, DM> { +impl<'d, DM: Mode> core::fmt::Debug for I8080<'d, DM> { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { f.debug_struct("I8080").finish() } @@ -384,12 +385,12 @@ impl<'d, CH: DmaChannel, DM: Mode> core::fmt::Debug for I8080<'d, CH, DM> { /// Represents an ongoing (or potentially finished) transfer using the I8080 LCD /// interface -pub struct I8080Transfer<'d, BUF: DmaTxBuffer, CH: DmaChannel, DM: Mode> { - i8080: ManuallyDrop>, +pub struct I8080Transfer<'d, BUF: DmaTxBuffer, DM: Mode> { + i8080: ManuallyDrop>, buf_view: ManuallyDrop, } -impl<'d, BUF: DmaTxBuffer, CH: DmaChannel, DM: Mode> I8080Transfer<'d, BUF, CH, DM> { +impl<'d, BUF: DmaTxBuffer, DM: Mode> I8080Transfer<'d, BUF, DM> { /// Returns true when [Self::wait] will not block. pub fn is_done(&self) -> bool { self.i8080 @@ -401,7 +402,7 @@ impl<'d, BUF: DmaTxBuffer, CH: DmaChannel, DM: Mode> I8080Transfer<'d, BUF, CH, } /// Stops this transfer on the spot and returns the peripheral and buffer. - pub fn cancel(mut self) -> (I8080<'d, CH, DM>, BUF) { + pub fn cancel(mut self) -> (I8080<'d, DM>, BUF) { self.stop_peripherals(); let (_, i8080, buf) = self.wait(); (i8080, buf) @@ -411,7 +412,7 @@ impl<'d, BUF: DmaTxBuffer, CH: DmaChannel, DM: Mode> I8080Transfer<'d, BUF, CH, /// /// Note: This also clears the transfer interrupt so it can be used in /// interrupt handlers to "handle" the interrupt. - pub fn wait(mut self) -> (Result<(), DmaError>, I8080<'d, CH, DM>, BUF) { + pub fn wait(mut self) -> (Result<(), DmaError>, I8080<'d, DM>, BUF) { while !self.is_done() {} // Clear "done" interrupt. @@ -450,7 +451,7 @@ impl<'d, BUF: DmaTxBuffer, CH: DmaChannel, DM: Mode> I8080Transfer<'d, BUF, CH, } } -impl<'d, BUF: DmaTxBuffer, CH: DmaChannel, DM: Mode> Deref for I8080Transfer<'d, BUF, CH, DM> { +impl<'d, BUF: DmaTxBuffer, DM: Mode> Deref for I8080Transfer<'d, BUF, DM> { type Target = BUF::View; fn deref(&self) -> &Self::Target { @@ -458,13 +459,13 @@ impl<'d, BUF: DmaTxBuffer, CH: DmaChannel, DM: Mode> Deref for I8080Transfer<'d, } } -impl<'d, BUF: DmaTxBuffer, CH: DmaChannel, DM: Mode> DerefMut for I8080Transfer<'d, BUF, CH, DM> { +impl<'d, BUF: DmaTxBuffer, DM: Mode> DerefMut for I8080Transfer<'d, BUF, DM> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buf_view } } -impl<'d, BUF: DmaTxBuffer, CH: DmaChannel> I8080Transfer<'d, BUF, CH, crate::Async> { +impl<'d, BUF: DmaTxBuffer> I8080Transfer<'d, BUF, crate::Async> { /// Waits for [Self::is_done] to return true. pub async fn wait_for_done(&mut self) { use core::{ @@ -503,7 +504,7 @@ impl<'d, BUF: DmaTxBuffer, CH: DmaChannel> I8080Transfer<'d, BUF, CH, crate::Asy } } -impl<'d, BUF: DmaTxBuffer, CH: DmaChannel, DM: Mode> Drop for I8080Transfer<'d, BUF, CH, DM> { +impl<'d, BUF: DmaTxBuffer, DM: Mode> Drop for I8080Transfer<'d, BUF, DM> { fn drop(&mut self) { self.stop_peripherals(); diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 2e8b15059bb..e0a55d4aaf9 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -33,11 +33,11 @@ use private::*; use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, + AnyDmaChannel, Channel, ChannelRx, ChannelTx, DescriptorChain, - DmaChannel, DmaDescriptor, DmaError, DmaPeripheral, @@ -836,9 +836,8 @@ impl<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> { } -impl<'d, CH, DM> TxCreatorFullDuplex<'d, CH, DM> +impl<'d, DM> TxCreatorFullDuplex<'d, DM> where - CH: DmaChannel, DM: Mode, { /// Configure TX to use the given pins and settings @@ -849,7 +848,7 @@ where idle_value: u16, sample_edge: SampleEdge, bit_order: BitPackOrder, - ) -> Result, Error> + ) -> Result, Error> where P: FullDuplex + TxPins + ConfigurePins, CP: TxClkPin, @@ -869,9 +868,8 @@ where } } -impl<'d, CH, DM> TxCreator<'d, CH, DM> +impl<'d, DM> TxCreator<'d, DM> where - CH: DmaChannel, DM: Mode, { /// Configure TX to use the given pins and settings @@ -882,7 +880,7 @@ where idle_value: u16, sample_edge: SampleEdge, bit_order: BitPackOrder, - ) -> Result, Error> + ) -> Result, Error> where P: TxPins + ConfigurePins, CP: TxClkPin, @@ -903,19 +901,17 @@ where } /// Parallel IO TX channel -pub struct ParlIoTx<'d, CH, DM> +pub struct ParlIoTx<'d, DM> where - CH: DmaChannel, DM: Mode, { - tx_channel: ChannelTx<'d, CH>, + tx_channel: ChannelTx<'d, AnyDmaChannel>, tx_chain: DescriptorChain, phantom: PhantomData, } -impl<'d, CH, DM> core::fmt::Debug for ParlIoTx<'d, CH, DM> +impl<'d, DM> core::fmt::Debug for ParlIoTx<'d, DM> where - CH: DmaChannel, DM: Mode, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -923,9 +919,8 @@ where } } -impl<'d, CH, DM> RxCreatorFullDuplex<'d, CH, DM> +impl<'d, DM> RxCreatorFullDuplex<'d, DM> where - CH: DmaChannel, DM: Mode, { /// Configure RX to use the given pins and settings @@ -935,7 +930,7 @@ where clk_pin: &'d mut CP, bit_order: BitPackOrder, timeout_ticks: Option, - ) -> Result, Error> + ) -> Result, Error> where P: FullDuplex + RxPins + ConfigurePins, CP: RxClkPin, @@ -954,9 +949,8 @@ where } } -impl<'d, CH, DM> RxCreator<'d, CH, DM> +impl<'d, DM> RxCreator<'d, DM> where - CH: DmaChannel, DM: Mode, { /// Configure RX to use the given pins and settings @@ -966,7 +960,7 @@ where clk_pin: &'d mut CP, bit_order: BitPackOrder, timeout_ticks: Option, - ) -> Result, Error> + ) -> Result, Error> where P: RxPins + ConfigurePins, CP: RxClkPin, @@ -986,19 +980,17 @@ where } /// Parallel IO RX channel -pub struct ParlIoRx<'d, CH, DM> +pub struct ParlIoRx<'d, DM> where - CH: DmaChannel, DM: Mode, { - rx_channel: ChannelRx<'d, CH>, + rx_channel: ChannelRx<'d, AnyDmaChannel>, rx_chain: DescriptorChain, phantom: PhantomData, } -impl<'d, CH, DM> core::fmt::Debug for ParlIoRx<'d, CH, DM> +impl<'d, DM> core::fmt::Debug for ParlIoRx<'d, DM> where - CH: DmaChannel, DM: Mode, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -1084,26 +1076,24 @@ fn internal_clear_interrupts(interrupts: EnumSet) { /// Parallel IO in full duplex mode /// /// Full duplex mode might limit the maximum possible bit width. -pub struct ParlIoFullDuplex<'d, CH, DM> +pub struct ParlIoFullDuplex<'d, DM> where - CH: DmaChannel, DM: Mode, { /// The transmitter (TX) channel responsible for handling DMA transfers in /// the parallel I/O full-duplex operation. - pub tx: TxCreatorFullDuplex<'d, CH, DM>, + pub tx: TxCreatorFullDuplex<'d, DM>, /// The receiver (RX) channel responsible for handling DMA transfers in the /// parallel I/O full-duplex operation. - pub rx: RxCreatorFullDuplex<'d, CH, DM>, + pub rx: RxCreatorFullDuplex<'d, DM>, } -impl<'d, CH, DM> ParlIoFullDuplex<'d, CH, DM> +impl<'d, DM> ParlIoFullDuplex<'d, DM> where - CH: DmaChannel, DM: Mode, { /// Create a new instance of [ParlIoFullDuplex] - pub fn new( + pub fn new( _parl_io: impl Peripheral

+ 'd, dma_channel: Channel<'d, CH, DM>, tx_descriptors: &'static mut [DmaDescriptor], @@ -1118,12 +1108,12 @@ where Ok(Self { tx: TxCreatorFullDuplex { - tx_channel: dma_channel.tx, + tx_channel: dma_channel.tx.degrade(), descriptors: tx_descriptors, phantom: PhantomData, }, rx: RxCreatorFullDuplex { - rx_channel: dma_channel.rx, + rx_channel: dma_channel.rx.degrade(), descriptors: rx_descriptors, phantom: PhantomData, }, @@ -1131,10 +1121,7 @@ where } } -impl<'d, CH> ParlIoFullDuplex<'d, CH, Blocking> -where - CH: DmaChannel, -{ +impl<'d> ParlIoFullDuplex<'d, Blocking> { /// Sets the interrupt handler, enables it with /// [crate::interrupt::Priority::min()] /// @@ -1164,35 +1151,31 @@ where } } -impl<'d, CH> crate::private::Sealed for ParlIoFullDuplex<'d, CH, Blocking> where CH: DmaChannel {} +impl<'d> crate::private::Sealed for ParlIoFullDuplex<'d, Blocking> {} -impl<'d, CH> InterruptConfigurable for ParlIoFullDuplex<'d, CH, Blocking> -where - CH: DmaChannel, -{ +impl<'d> InterruptConfigurable for ParlIoFullDuplex<'d, Blocking> { fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) { ParlIoFullDuplex::set_interrupt_handler(self, handler); } } /// Parallel IO in half duplex / TX only mode -pub struct ParlIoTxOnly<'d, CH, DM> +pub struct ParlIoTxOnly<'d, DM> where - CH: DmaChannel, DM: Mode, { /// The transmitter (TX) channel responsible for handling DMA transfers in /// the parallel I/O operation. - pub tx: TxCreator<'d, CH, DM>, + pub tx: TxCreator<'d, DM>, } -impl<'d, CH, DM> ParlIoTxOnly<'d, CH, DM> +impl<'d, DM> ParlIoTxOnly<'d, DM> where - CH: DmaChannel, DM: Mode, { /// Create a new [ParlIoTxOnly] - pub fn new( + // TODO: only take a TX DMA channel? + pub fn new( _parl_io: impl Peripheral

+ 'd, dma_channel: Channel<'d, CH, DM>, descriptors: &'static mut [DmaDescriptor], @@ -1206,7 +1189,7 @@ where Ok(Self { tx: TxCreator { - tx_channel: dma_channel.tx, + tx_channel: dma_channel.tx.degrade(), descriptors, phantom: PhantomData, }, @@ -1214,10 +1197,7 @@ where } } -impl<'d, CH> ParlIoTxOnly<'d, CH, Blocking> -where - CH: DmaChannel, -{ +impl<'d> ParlIoTxOnly<'d, Blocking> { /// Sets the interrupt handler, enables it with /// [crate::interrupt::Priority::min()] /// @@ -1247,35 +1227,31 @@ where } } -impl<'d, CH> crate::private::Sealed for ParlIoTxOnly<'d, CH, Blocking> where CH: DmaChannel {} +impl<'d> crate::private::Sealed for ParlIoTxOnly<'d, Blocking> {} -impl<'d, CH> InterruptConfigurable for ParlIoTxOnly<'d, CH, Blocking> -where - CH: DmaChannel, -{ +impl<'d> InterruptConfigurable for ParlIoTxOnly<'d, Blocking> { fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) { ParlIoTxOnly::set_interrupt_handler(self, handler); } } /// Parallel IO in half duplex / RX only mode -pub struct ParlIoRxOnly<'d, CH, DM> +pub struct ParlIoRxOnly<'d, DM> where - CH: DmaChannel, DM: Mode, { /// The receiver (RX) channel responsible for handling DMA transfers in the /// parallel I/O operation. - pub rx: RxCreator<'d, CH, DM>, + pub rx: RxCreator<'d, DM>, } -impl<'d, CH, DM> ParlIoRxOnly<'d, CH, DM> +impl<'d, DM> ParlIoRxOnly<'d, DM> where - CH: DmaChannel, DM: Mode, { /// Create a new [ParlIoRxOnly] instance - pub fn new( + // TODO: only take a RX DMA channel? + pub fn new( _parl_io: impl Peripheral

+ 'd, dma_channel: Channel<'d, CH, DM>, descriptors: &'static mut [DmaDescriptor], @@ -1289,7 +1265,7 @@ where Ok(Self { rx: RxCreator { - rx_channel: dma_channel.rx, + rx_channel: dma_channel.rx.degrade(), descriptors, phantom: PhantomData, }, @@ -1297,10 +1273,7 @@ where } } -impl<'d, CH> ParlIoRxOnly<'d, CH, Blocking> -where - CH: DmaChannel, -{ +impl<'d> ParlIoRxOnly<'d, Blocking> { /// Sets the interrupt handler, enables it with /// [crate::interrupt::Priority::min()] /// @@ -1330,12 +1303,9 @@ where } } -impl<'d, CH> crate::private::Sealed for ParlIoRxOnly<'d, CH, Blocking> where CH: DmaChannel {} +impl<'d> crate::private::Sealed for ParlIoRxOnly<'d, Blocking> {} -impl<'d, CH> InterruptConfigurable for ParlIoRxOnly<'d, CH, Blocking> -where - CH: DmaChannel, -{ +impl<'d> InterruptConfigurable for ParlIoRxOnly<'d, Blocking> { fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) { ParlIoRxOnly::set_interrupt_handler(self, handler); } @@ -1374,9 +1344,8 @@ fn internal_init(frequency: HertzU32) -> Result<(), Error> { Ok(()) } -impl<'d, CH, DM> ParlIoTx<'d, CH, DM> +impl<'d, DM> ParlIoTx<'d, DM> where - CH: DmaChannel, DM: Mode, { /// Perform a DMA write. @@ -1434,9 +1403,8 @@ where } } -impl<'d, CH, DM> DmaSupport for ParlIoTx<'d, CH, DM> +impl<'d, DM> DmaSupport for ParlIoTx<'d, DM> where - CH: DmaChannel, DM: Mode, { fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { @@ -1450,12 +1418,11 @@ where } } -impl<'d, CH, DM> DmaSupportTx for ParlIoTx<'d, CH, DM> +impl<'d, DM> DmaSupportTx for ParlIoTx<'d, DM> where - CH: DmaChannel, DM: Mode, { - type TX = ChannelTx<'d, CH>; + type TX = ChannelTx<'d, AnyDmaChannel>; fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel @@ -1466,9 +1433,8 @@ where } } -impl<'d, CH, DM> ParlIoRx<'d, CH, DM> +impl<'d, DM> ParlIoRx<'d, DM> where - CH: DmaChannel, DM: Mode, { /// Perform a DMA read. @@ -1498,7 +1464,7 @@ where } fn start_receive_bytes_dma( - rx_channel: &mut ChannelRx<'d, CH>, + rx_channel: &mut ChannelRx<'d, AnyDmaChannel>, rx_chain: &mut DescriptorChain, ptr: *mut u8, len: usize, @@ -1526,9 +1492,8 @@ where } } -impl<'d, CH, DM> DmaSupport for ParlIoRx<'d, CH, DM> +impl<'d, DM> DmaSupport for ParlIoRx<'d, DM> where - CH: DmaChannel, DM: Mode, { fn peripheral_wait_dma(&mut self, _is_rx: bool, _is_tx: bool) { @@ -1549,12 +1514,11 @@ where } } -impl<'d, CH, DM> DmaSupportRx for ParlIoRx<'d, CH, DM> +impl<'d, DM> DmaSupportRx for ParlIoRx<'d, DM> where - CH: DmaChannel, DM: Mode, { - type RX = ChannelRx<'d, CH>; + type RX = ChannelRx<'d, AnyDmaChannel>; fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel @@ -1566,45 +1530,41 @@ where } /// Creates a TX channel -pub struct TxCreator<'d, CH, DM> +pub struct TxCreator<'d, DM> where - CH: DmaChannel, DM: Mode, { - tx_channel: ChannelTx<'d, CH>, + tx_channel: ChannelTx<'d, AnyDmaChannel>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } /// Creates a RX channel -pub struct RxCreator<'d, CH, DM> +pub struct RxCreator<'d, DM> where - CH: DmaChannel, DM: Mode, { - rx_channel: ChannelRx<'d, CH>, + rx_channel: ChannelRx<'d, AnyDmaChannel>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } /// Creates a TX channel -pub struct TxCreatorFullDuplex<'d, CH, DM> +pub struct TxCreatorFullDuplex<'d, DM> where - CH: DmaChannel, DM: Mode, { - tx_channel: ChannelTx<'d, CH>, + tx_channel: ChannelTx<'d, AnyDmaChannel>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } /// Creates a RX channel -pub struct RxCreatorFullDuplex<'d, CH, DM> +pub struct RxCreatorFullDuplex<'d, DM> where - CH: DmaChannel, DM: Mode, { - rx_channel: ChannelRx<'d, CH>, + rx_channel: ChannelRx<'d, AnyDmaChannel>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1618,7 +1578,7 @@ pub mod asynch { use super::{private::Instance, Error, ParlIoRx, ParlIoTx, MAX_DMA_SIZE}; use crate::{ - dma::{asynch::DmaRxFuture, DmaChannel, ReadBuffer, WriteBuffer}, + dma::{asynch::DmaRxFuture, ReadBuffer, WriteBuffer}, peripherals::Interrupt, }; @@ -1673,10 +1633,7 @@ pub mod asynch { } } - impl<'d, CH> ParlIoTx<'d, CH, crate::Async> - where - CH: DmaChannel, - { + impl<'d> ParlIoTx<'d, crate::Async> { /// Perform a DMA write. /// /// The maximum amount of data to be sent is 32736 bytes. @@ -1698,10 +1655,7 @@ pub mod asynch { } } - impl<'d, CH> ParlIoRx<'d, CH, crate::Async> - where - CH: DmaChannel, - { + impl<'d> ParlIoRx<'d, crate::Async> { /// Perform a DMA write. /// /// The maximum amount of data to be sent is 32736 bytes. diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index faa30d03c7f..518ae45e72b 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -918,8 +918,8 @@ mod dma { use crate::{ dma::{ asynch::{DmaRxFuture, DmaTxFuture}, + AnyDmaChannel, Channel, - DmaChannel, DmaRxBuf, DmaRxBuffer, DmaTxBuf, @@ -946,7 +946,7 @@ mod dma { pub fn with_dma( self, channel: Channel<'d, C, DmaMode>, - ) -> SpiDma<'d, crate::peripherals::SPI2, C, M, DmaMode> + ) -> SpiDma<'d, crate::peripherals::SPI2, M, DmaMode> where C: PeripheralDmaChannel, C::P: SpiPeripheral + Spi2Peripheral, @@ -969,7 +969,7 @@ mod dma { pub fn with_dma( self, channel: Channel<'d, C, DmaMode>, - ) -> SpiDma<'d, crate::peripherals::SPI3, C, M, DmaMode> + ) -> SpiDma<'d, crate::peripherals::SPI3, M, DmaMode> where C: PeripheralDmaChannel, C::P: SpiPeripheral + Spi3Peripheral, @@ -986,14 +986,13 @@ mod dma { /// [`SpiDmaBus`] via `with_buffers` to get access /// to a DMA capable SPI bus that implements the /// embedded-hal traits. - pub struct SpiDma<'d, T, C, D, M> + pub struct SpiDma<'d, T, D, M> where - C: DmaChannel, D: DuplexMode, M: Mode, { pub(crate) spi: PeripheralRef<'d, T>, - pub(crate) channel: Channel<'d, C, M>, + pub(crate) channel: Channel<'d, AnyDmaChannel, M>, tx_transfer_in_progress: bool, rx_transfer_in_progress: bool, #[cfg(all(esp32, spi_address_workaround))] @@ -1002,17 +1001,15 @@ mod dma { } #[cfg(all(esp32, spi_address_workaround))] - unsafe impl<'d, T, C, D, M> Send for SpiDma<'d, T, C, D, M> + unsafe impl<'d, T, D, M> Send for SpiDma<'d, T, D, M> where - C: DmaChannel, D: DuplexMode, M: Mode, { } - impl<'d, T, C, D, M> core::fmt::Debug for SpiDma<'d, T, C, D, M> + impl<'d, T, D, M> core::fmt::Debug for SpiDma<'d, T, D, M> where - C: DmaChannel, D: DuplexMode, M: Mode, { @@ -1025,17 +1022,16 @@ mod dma { } } - impl<'d, T, C, D, M> SpiDma<'d, T, C, D, M> + impl<'d, T, D, M> SpiDma<'d, T, D, M> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { - fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, C, M>) -> Self + fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, CH, M>) -> Self where - C: PeripheralDmaChannel, - C::P: SpiPeripheral, + CH: PeripheralDmaChannel, + CH::P: SpiPeripheral, { #[cfg(all(esp32, spi_address_workaround))] let address_buffer = { @@ -1055,7 +1051,7 @@ mod dma { Self { spi, - channel, + channel: channel.degrade(), #[cfg(all(esp32, spi_address_workaround))] address_buffer, tx_transfer_in_progress: false, @@ -1264,19 +1260,17 @@ mod dma { } } - impl<'d, T, C, D, M> crate::private::Sealed for SpiDma<'d, T, C, D, M> + impl<'d, T, D, M> crate::private::Sealed for SpiDma<'d, T, D, M> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { } - impl<'d, T, C, D, M> InterruptConfigurable for SpiDma<'d, T, C, D, M> + impl<'d, T, D, M> InterruptConfigurable for SpiDma<'d, T, D, M> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { @@ -1286,10 +1280,9 @@ mod dma { } } - impl<'d, T, C, D, M> SpiDma<'d, T, C, D, M> + impl<'d, T, D, M> SpiDma<'d, T, D, M> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { @@ -1307,7 +1300,7 @@ mod dma { self, dma_rx_buf: DmaRxBuf, dma_tx_buf: DmaTxBuf, - ) -> SpiDmaBus<'d, T, C, D, M> { + ) -> SpiDmaBus<'d, T, D, M> { SpiDmaBus::new(self, dma_rx_buf, dma_tx_buf) } } @@ -1316,25 +1309,23 @@ mod dma { /// /// This structure holds references to the SPI instance, DMA buffers, and /// transfer status. - pub struct SpiDmaTransfer<'d, T, C, D, M, Buf> + pub struct SpiDmaTransfer<'d, T, D, M, Buf> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { - spi_dma: ManuallyDrop>, + spi_dma: ManuallyDrop>, dma_buf: ManuallyDrop, } - impl<'d, T, C, D, M, Buf> SpiDmaTransfer<'d, T, C, D, M, Buf> + impl<'d, T, D, M, Buf> SpiDmaTransfer<'d, T, D, M, Buf> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { - fn new(spi_dma: SpiDma<'d, T, C, D, M>, dma_buf: Buf) -> Self { + fn new(spi_dma: SpiDma<'d, T, D, M>, dma_buf: Buf) -> Self { Self { spi_dma: ManuallyDrop::new(spi_dma), dma_buf: ManuallyDrop::new(dma_buf), @@ -1353,7 +1344,7 @@ mod dma { /// /// This method blocks until the transfer is finished and returns the /// `SpiDma` instance and the associated buffer. - pub fn wait(mut self) -> (SpiDma<'d, T, C, D, M>, Buf) { + pub fn wait(mut self) -> (SpiDma<'d, T, D, M>, Buf) { self.spi_dma.wait_for_idle(); let retval = unsafe { ( @@ -1373,10 +1364,9 @@ mod dma { } } - impl<'d, T, C, D, M, Buf> Drop for SpiDmaTransfer<'d, T, C, D, M, Buf> + impl<'d, T, D, M, Buf> Drop for SpiDmaTransfer<'d, T, D, M, Buf> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { @@ -1393,10 +1383,9 @@ mod dma { } } - impl<'d, T, C, D, Buf> SpiDmaTransfer<'d, T, C, D, crate::Async, Buf> + impl<'d, T, D, Buf> SpiDmaTransfer<'d, T, D, crate::Async, Buf> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, { /// Waits for the DMA transfer to complete asynchronously. @@ -1407,10 +1396,9 @@ mod dma { } } - impl<'d, T, C, M> SpiDma<'d, T, C, FullDuplexMode, M> + impl<'d, T, M> SpiDma<'d, T, FullDuplexMode, M> where T: InstanceDma, - C: DmaChannel, M: Mode, { /// # Safety: @@ -1437,7 +1425,7 @@ mod dma { pub fn dma_write( mut self, mut buffer: TX, - ) -> Result, (Error, Self, TX)> { + ) -> Result, (Error, Self, TX)> { self.wait_for_idle(); match unsafe { self.start_dma_write(&mut buffer) } { @@ -1470,7 +1458,7 @@ mod dma { pub fn dma_read( mut self, mut buffer: RX, - ) -> Result, (Error, Self, RX)> { + ) -> Result, (Error, Self, RX)> { self.wait_for_idle(); match unsafe { self.start_dma_read(&mut buffer) } { Ok(_) => Ok(SpiDmaTransfer::new(self, buffer)), @@ -1509,7 +1497,7 @@ mod dma { mut self, mut rx_buffer: RX, mut tx_buffer: TX, - ) -> Result, (Error, Self, RX, TX)> + ) -> Result, (Error, Self, RX, TX)> { self.wait_for_idle(); match unsafe { self.start_dma_transfer(&mut rx_buffer, &mut tx_buffer) } { @@ -1519,10 +1507,9 @@ mod dma { } } - impl<'d, T, C, M> SpiDma<'d, T, C, HalfDuplexMode, M> + impl<'d, T, M> SpiDma<'d, T, HalfDuplexMode, M> where T: InstanceDma, - C: DmaChannel, M: Mode, { /// # Safety: @@ -1566,7 +1553,7 @@ mod dma { address: Address, dummy: u8, mut buffer: RX, - ) -> Result, (Error, Self, RX)> { + ) -> Result, (Error, Self, RX)> { self.wait_for_idle(); match unsafe { @@ -1627,7 +1614,7 @@ mod dma { address: Address, dummy: u8, mut buffer: TX, - ) -> Result, (Error, Self, TX)> { + ) -> Result, (Error, Self, TX)> { self.wait_for_idle(); match unsafe { @@ -1643,28 +1630,26 @@ mod dma { /// /// This structure is responsible for managing SPI transfers using DMA /// buffers. - pub struct SpiDmaBus<'d, T, C, D, M> + pub struct SpiDmaBus<'d, T, D, M> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { - spi_dma: SpiDma<'d, T, C, D, M>, + spi_dma: SpiDma<'d, T, D, M>, rx_buf: DmaRxBuf, tx_buf: DmaTxBuf, } - impl<'d, T, C, D, M> SpiDmaBus<'d, T, C, D, M> + impl<'d, T, D, M> SpiDmaBus<'d, T, D, M> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { /// Creates a new `SpiDmaBus` with the specified SPI instance and DMA /// buffers. - pub fn new(spi_dma: SpiDma<'d, T, C, D, M>, rx_buf: DmaRxBuf, tx_buf: DmaTxBuf) -> Self { + pub fn new(spi_dma: SpiDma<'d, T, D, M>, rx_buf: DmaRxBuf, tx_buf: DmaTxBuf) -> Self { Self { spi_dma, rx_buf, @@ -1713,10 +1698,9 @@ mod dma { } } - impl<'d, T, C, D, M> InterruptConfigurable for SpiDmaBus<'d, T, C, D, M> + impl<'d, T, D, M> InterruptConfigurable for SpiDmaBus<'d, T, D, M> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { @@ -1726,19 +1710,17 @@ mod dma { } } - impl<'d, T, C, D, M> crate::private::Sealed for SpiDmaBus<'d, T, C, D, M> + impl<'d, T, D, M> crate::private::Sealed for SpiDmaBus<'d, T, D, M> where T: InstanceDma, - C: DmaChannel, D: DuplexMode, M: Mode, { } - impl<'d, T, C, M> SpiDmaBus<'d, T, C, FullDuplexMode, M> + impl<'d, T, M> SpiDmaBus<'d, T, FullDuplexMode, M> where T: InstanceDma, - C: DmaChannel, M: Mode, { /// Reads data from the SPI bus using DMA. @@ -1830,10 +1812,9 @@ mod dma { } } - impl<'d, T, C, M> HalfDuplexReadWrite for SpiDmaBus<'d, T, C, HalfDuplexMode, M> + impl<'d, T, M> HalfDuplexReadWrite for SpiDmaBus<'d, T, HalfDuplexMode, M> where T: InstanceDma, - C: DmaChannel, M: Mode, { type Error = Error; @@ -1902,11 +1883,10 @@ mod dma { } } - impl<'d, T, C> embedded_hal_02::blocking::spi::Transfer - for SpiDmaBus<'d, T, C, FullDuplexMode, crate::Blocking> + impl<'d, T> embedded_hal_02::blocking::spi::Transfer + for SpiDmaBus<'d, T, FullDuplexMode, crate::Blocking> where T: InstanceDma, - C: DmaChannel, { type Error = Error; @@ -1916,11 +1896,10 @@ mod dma { } } - impl<'d, T, C> embedded_hal_02::blocking::spi::Write - for SpiDmaBus<'d, T, C, FullDuplexMode, crate::Blocking> + impl<'d, T> embedded_hal_02::blocking::spi::Write + for SpiDmaBus<'d, T, FullDuplexMode, crate::Blocking> where T: InstanceDma, - C: DmaChannel, { type Error = Error; @@ -1977,10 +1956,9 @@ mod dma { } } - impl<'d, T, C> SpiDmaBus<'d, T, C, FullDuplexMode, crate::Async> + impl<'d, T> SpiDmaBus<'d, T, FullDuplexMode, crate::Async> where T: InstanceDma, - C: DmaChannel, { /// Fill the given buffer with data from the bus. pub async fn read_async(&mut self, words: &mut [u8]) -> Result<(), Error> { @@ -2094,10 +2072,9 @@ mod dma { } } - impl<'d, T, C> embedded_hal_async::spi::SpiBus for SpiDmaBus<'d, T, C, FullDuplexMode, crate::Async> + impl<'d, T> embedded_hal_async::spi::SpiBus for SpiDmaBus<'d, T, FullDuplexMode, crate::Async> where T: InstanceDma, - C: DmaChannel, { async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { self.read_async(words).await @@ -2127,19 +2104,17 @@ mod dma { use super::*; - impl<'d, T, C, M> ErrorType for SpiDmaBus<'d, T, C, FullDuplexMode, M> + impl<'d, T, M> ErrorType for SpiDmaBus<'d, T, FullDuplexMode, M> where T: InstanceDma, - C: DmaChannel, M: Mode, { type Error = Error; } - impl<'d, T, C, M> SpiBus for SpiDmaBus<'d, T, C, FullDuplexMode, M> + impl<'d, T, M> SpiBus for SpiDmaBus<'d, T, FullDuplexMode, M> where T: InstanceDma, - C: DmaChannel, M: Mode, { fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index 513e157b420..01491183ed3 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -155,6 +155,7 @@ pub mod dma { use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, + AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -184,19 +185,14 @@ pub mod dma { channel: Channel<'d, C, DmaMode>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], - ) -> SpiDma<'d, crate::peripherals::SPI2, C, DmaMode> + ) -> SpiDma<'d, crate::peripherals::SPI2, DmaMode> where C: PeripheralDmaChannel, C::P: SpiPeripheral + Spi2Peripheral, DmaMode: Mode, { self.spi.set_data_mode(self.data_mode, true); - SpiDma { - spi: self.spi, - channel, - rx_chain: DescriptorChain::new(rx_descriptors), - tx_chain: DescriptorChain::new(tx_descriptors), - } + SpiDma::new(self.spi, channel, rx_descriptors, tx_descriptors) } } @@ -210,37 +206,30 @@ pub mod dma { channel: Channel<'d, C, DmaMode>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], - ) -> SpiDma<'d, crate::peripherals::SPI3, C, DmaMode> + ) -> SpiDma<'d, crate::peripherals::SPI3, DmaMode> where C: PeripheralDmaChannel, C::P: SpiPeripheral + Spi3Peripheral, DmaMode: Mode, { self.spi.set_data_mode(self.data_mode, true); - SpiDma { - spi: self.spi, - channel, - rx_chain: DescriptorChain::new(rx_descriptors), - tx_chain: DescriptorChain::new(tx_descriptors), - } + SpiDma::new(self.spi, channel, rx_descriptors, tx_descriptors) } } /// A DMA capable SPI instance. - pub struct SpiDma<'d, T, C, DmaMode> + pub struct SpiDma<'d, T, DmaMode> where - C: DmaChannel, DmaMode: Mode, { pub(crate) spi: PeripheralRef<'d, T>, - pub(crate) channel: Channel<'d, C, DmaMode>, + pub(crate) channel: Channel<'d, AnyDmaChannel, DmaMode>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, } - impl<'d, T, C, DmaMode> core::fmt::Debug for SpiDma<'d, T, C, DmaMode> + impl<'d, T, DmaMode> core::fmt::Debug for SpiDma<'d, T, DmaMode> where - C: DmaChannel, DmaMode: Mode, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -248,10 +237,9 @@ pub mod dma { } } - impl<'d, T, C, DmaMode> DmaSupport for SpiDma<'d, T, C, DmaMode> + impl<'d, T, DmaMode> DmaSupport for SpiDma<'d, T, DmaMode> where T: InstanceDma, - C: DmaChannel, DmaMode: Mode, { fn peripheral_wait_dma(&mut self, is_rx: bool, is_tx: bool) { @@ -268,13 +256,12 @@ pub mod dma { } } - impl<'d, T, C, DmaMode> DmaSupportTx for SpiDma<'d, T, C, DmaMode> + impl<'d, T, DmaMode> DmaSupportTx for SpiDma<'d, T, DmaMode> where T: InstanceDma, - C: DmaChannel, DmaMode: Mode, { - type TX = ChannelTx<'d, C>; + type TX = ChannelTx<'d, AnyDmaChannel>; fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx @@ -285,13 +272,12 @@ pub mod dma { } } - impl<'d, T, C, DmaMode> DmaSupportRx for SpiDma<'d, T, C, DmaMode> + impl<'d, T, DmaMode> DmaSupportRx for SpiDma<'d, T, DmaMode> where T: InstanceDma, - C: DmaChannel, DmaMode: Mode, { - type RX = ChannelRx<'d, C>; + type RX = ChannelRx<'d, AnyDmaChannel>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx @@ -302,12 +288,27 @@ pub mod dma { } } - impl<'d, T, C, DmaMode> SpiDma<'d, T, C, DmaMode> + impl<'d, T, DmaMode> SpiDma<'d, T, DmaMode> where T: InstanceDma, - C: DmaChannel, DmaMode: Mode, { + fn new( + spi: PeripheralRef<'d, T>, + channel: Channel<'d, CH, DmaMode>, + rx_descriptors: &'static mut [DmaDescriptor], + tx_descriptors: &'static mut [DmaDescriptor], + ) -> Self + where + CH: DmaChannel, + { + Self { + spi, + channel: channel.degrade(), + rx_chain: DescriptorChain::new(rx_descriptors), + tx_chain: DescriptorChain::new(tx_descriptors), + } + } /// Register a buffer for a DMA write. /// /// This will return a [DmaTransferTx]. The maximum amount of data to be From a88bf54ef44293f6e10d7999a4746f7e64f652e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Wed, 2 Oct 2024 17:16:34 +0200 Subject: [PATCH 09/36] Clean up examples/tests --- examples/src/bin/lcd_i8080.rs | 9 +++------ hil-test/tests/dma_mem2mem.rs | 10 +++++----- hil-test/tests/embassy_interrupt_spi_dma.rs | 13 +------------ hil-test/tests/i2s.rs | 4 +--- hil-test/tests/qspi.rs | 19 ++++++------------- hil-test/tests/spi_half_duplex_read.rs | 10 +--------- hil-test/tests/spi_half_duplex_write.rs | 13 +------------ hil-test/tests/spi_half_duplex_write_psram.rs | 13 +------------ 8 files changed, 19 insertions(+), 72 deletions(-) diff --git a/examples/src/bin/lcd_i8080.rs b/examples/src/bin/lcd_i8080.rs index a87c1a2ea72..2937f427cae 100644 --- a/examples/src/bin/lcd_i8080.rs +++ b/examples/src/bin/lcd_i8080.rs @@ -25,7 +25,7 @@ use esp_backtrace as _; use esp_hal::{ delay::Delay, - dma::{Dma, DmaChannel0, DmaPriority, DmaTxBuf}, + dma::{Dma, DmaPriority, DmaTxBuf}, dma_tx_buffer, gpio::{Input, Io, Level, Output, Pull}, lcd_cam::{ @@ -88,15 +88,12 @@ fn main() -> ! { // 8 vs 16 bit, non-native primitives like Rgb565, Rgb888, etc. This Bus is just provided as // an example of how to implement your own. struct Bus<'d> { - resources: Option<(I8080<'d, DmaChannel0, Blocking>, DmaTxBuf)>, + resources: Option<(I8080<'d, Blocking>, DmaTxBuf)>, } impl<'d> Bus<'d> { fn use_resources( &mut self, - func: impl FnOnce( - I8080<'d, DmaChannel0, Blocking>, - DmaTxBuf, - ) -> (T, I8080<'d, DmaChannel0, Blocking>, DmaTxBuf), + func: impl FnOnce(I8080<'d, Blocking>, DmaTxBuf) -> (T, I8080<'d, Blocking>, DmaTxBuf), ) -> T { let (i8080, buf) = self.resources.take().unwrap(); let (result, i8080, buf) = func(i8080, buf); diff --git a/hil-test/tests/dma_mem2mem.rs b/hil-test/tests/dma_mem2mem.rs index 9abd073db65..6499f90d9aa 100644 --- a/hil-test/tests/dma_mem2mem.rs +++ b/hil-test/tests/dma_mem2mem.rs @@ -6,7 +6,7 @@ #![no_main] use esp_hal::{ - dma::{Channel, Dma, DmaError, DmaPriority, Mem2Mem}, + dma::{AnyDmaChannel, Channel, Dma, DmaError, DmaPriority, Mem2Mem}, dma_buffers, dma_buffers_chunk_size, dma_descriptors, @@ -24,10 +24,8 @@ cfg_if::cfg_if! { } } -use esp_hal::dma::DmaChannel0; - struct Context { - channel: Channel<'static, DmaChannel0, Blocking>, + channel: Channel<'static, AnyDmaChannel, Blocking>, dma_peripheral: DmaPeripheralType, } @@ -52,7 +50,9 @@ mod tests { } Context { - channel: dma_channel.configure(false, DmaPriority::Priority0), + channel: dma_channel + .configure(false, DmaPriority::Priority0) + .degrade(), dma_peripheral, } } diff --git a/hil-test/tests/embassy_interrupt_spi_dma.rs b/hil-test/tests/embassy_interrupt_spi_dma.rs index b1fac2b3c0c..86177a23c6a 100644 --- a/hil-test/tests/embassy_interrupt_spi_dma.rs +++ b/hil-test/tests/embassy_interrupt_spi_dma.rs @@ -25,17 +25,6 @@ use esp_hal::{ use esp_hal_embassy::InterruptExecutor; use hil_test as _; -cfg_if::cfg_if! { - if #[cfg(any( - feature = "esp32", - feature = "esp32s2", - ))] { - use esp_hal::dma::Spi3DmaChannel as DmaChannel1; - } else { - use esp_hal::dma::DmaChannel1; - } -} - macro_rules! mk_static { ($t:ty,$val:expr) => {{ static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new(); @@ -46,7 +35,7 @@ macro_rules! mk_static { } #[embassy_executor::task] -async fn interrupt_driven_task(spi: SpiDma<'static, SPI3, DmaChannel1, FullDuplexMode, Async>) { +async fn interrupt_driven_task(spi: SpiDma<'static, SPI3, FullDuplexMode, Async>) { let mut ticker = Ticker::every(Duration::from_millis(1)); let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(128); diff --git a/hil-test/tests/i2s.rs b/hil-test/tests/i2s.rs index 537e6622177..a9351bd5141 100644 --- a/hil-test/tests/i2s.rs +++ b/hil-test/tests/i2s.rs @@ -23,10 +23,8 @@ use hil_test as _; cfg_if::cfg_if! { if #[cfg(any(esp32, esp32s2))] { - use esp_hal::dma::I2s0DmaChannel as DmaChannel0; type DmaChannel0Creator = esp_hal::dma::I2s0DmaChannelCreator; } else { - use esp_hal::dma::DmaChannel0; type DmaChannel0Creator = esp_hal::dma::ChannelCreator<0>; } } @@ -59,7 +57,7 @@ impl Iterator for SampleSource { } #[embassy_executor::task] -async fn writer(tx_buffer: &'static mut [u8], i2s_tx: I2sTx<'static, I2S0, DmaChannel0, Async>) { +async fn writer(tx_buffer: &'static mut [u8], i2s_tx: I2sTx<'static, I2S0, Async>) { let mut samples = SampleSource::new(); for b in tx_buffer.iter_mut() { *b = samples.next().unwrap(); diff --git a/hil-test/tests/qspi.rs b/hil-test/tests/qspi.rs index af9132bede8..f9358d70458 100644 --- a/hil-test/tests/qspi.rs +++ b/hil-test/tests/qspi.rs @@ -8,7 +8,7 @@ #[cfg(pcnt)] use esp_hal::pcnt::{channel::EdgeMode, unit::Unit, Pcnt}; use esp_hal::{ - dma::{Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, + dma::{AnyDmaChannel, Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::{AnyPin, Input, Io, Level, NoPin, Output, Pull}, prelude::*, @@ -22,14 +22,6 @@ use esp_hal::{ }; use hil_test as _; -cfg_if::cfg_if! { - if #[cfg(any(esp32, esp32s2))] { - use esp_hal::dma::Spi2DmaChannel as DmaChannel0; - } else { - use esp_hal::dma::DmaChannel0; - } -} - cfg_if::cfg_if! { if #[cfg(esp32)] { const COMMAND_DATA_MODES: [SpiDataMode; 1] = [SpiDataMode::Single]; @@ -38,14 +30,13 @@ cfg_if::cfg_if! { } } -type SpiUnderTest = - SpiDma<'static, esp_hal::peripherals::SPI2, DmaChannel0, HalfDuplexMode, Blocking>; +type SpiUnderTest = SpiDma<'static, esp_hal::peripherals::SPI2, HalfDuplexMode, Blocking>; struct Context { spi: esp_hal::peripherals::SPI2, #[cfg(pcnt)] pcnt: esp_hal::peripherals::PCNT, - dma_channel: Channel<'static, DmaChannel0, Blocking>, + dma_channel: Channel<'static, AnyDmaChannel, Blocking>, gpios: [AnyPin; 3], } @@ -206,7 +197,9 @@ mod tests { } } - let dma_channel = dma_channel.configure(false, DmaPriority::Priority0); + let dma_channel = dma_channel + .configure(false, DmaPriority::Priority0) + .degrade(); Context { spi: peripherals.SPI2, diff --git a/hil-test/tests/spi_half_duplex_read.rs b/hil-test/tests/spi_half_duplex_read.rs index 48e5dc3d446..5f0c379f4b3 100644 --- a/hil-test/tests/spi_half_duplex_read.rs +++ b/hil-test/tests/spi_half_duplex_read.rs @@ -21,16 +21,8 @@ use esp_hal::{ }; use hil_test as _; -cfg_if::cfg_if! { - if #[cfg(any(esp32, esp32s2))] { - use esp_hal::dma::Spi2DmaChannel as DmaChannel0; - } else { - use esp_hal::dma::DmaChannel0; - } -} - struct Context { - spi: SpiDma<'static, SPI2, DmaChannel0, HalfDuplexMode, Blocking>, + spi: SpiDma<'static, SPI2, HalfDuplexMode, Blocking>, miso_mirror: Output<'static>, } diff --git a/hil-test/tests/spi_half_duplex_write.rs b/hil-test/tests/spi_half_duplex_write.rs index fb6cc0fcfce..eb653963aca 100644 --- a/hil-test/tests/spi_half_duplex_write.rs +++ b/hil-test/tests/spi_half_duplex_write.rs @@ -22,19 +22,8 @@ use esp_hal::{ }; use hil_test as _; -cfg_if::cfg_if! { - if #[cfg(any( - feature = "esp32", - feature = "esp32s2", - ))] { - use esp_hal::dma::Spi2DmaChannel as DmaChannel0; - } else { - use esp_hal::dma::DmaChannel0; - } -} - struct Context { - spi: SpiDma<'static, SPI2, DmaChannel0, HalfDuplexMode, Blocking>, + spi: SpiDma<'static, SPI2, HalfDuplexMode, Blocking>, pcnt_unit: Unit<'static, 0>, pcnt_source: InputSignal, } diff --git a/hil-test/tests/spi_half_duplex_write_psram.rs b/hil-test/tests/spi_half_duplex_write_psram.rs index eb7987e2315..b5a6845b196 100644 --- a/hil-test/tests/spi_half_duplex_write_psram.rs +++ b/hil-test/tests/spi_half_duplex_write_psram.rs @@ -25,17 +25,6 @@ use esp_hal::{ use hil_test as _; extern crate alloc; -cfg_if::cfg_if! { - if #[cfg(any( - feature = "esp32", - feature = "esp32s2", - ))] { - use esp_hal::dma::Spi2DmaChannel as DmaChannel0; - } else { - use esp_hal::dma::DmaChannel0; - } -} - macro_rules! dma_alloc_buffer { ($size:expr, $align:expr) => {{ let layout = core::alloc::Layout::from_size_align($size, $align).unwrap(); @@ -51,7 +40,7 @@ macro_rules! dma_alloc_buffer { } struct Context { - spi: SpiDma<'static, SPI2, DmaChannel0, HalfDuplexMode, Blocking>, + spi: SpiDma<'static, SPI2, HalfDuplexMode, Blocking>, pcnt_unit: Unit<'static, 0>, pcnt_source: InputSignal, } From 2b8253acbf61b2fcd38d9706489136f73358d8a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Thu, 3 Oct 2024 09:46:42 +0200 Subject: [PATCH 10/36] Remove redundant trait bounds --- esp-hal/src/i2s.rs | 5 ++--- esp-hal/src/spi/master.rs | 16 ++++++++-------- esp-hal/src/spi/slave.rs | 17 ++++++++--------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index ca772aca7b4..29a29d5322c 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -102,7 +102,6 @@ use crate::{ DmaTransferTx, DmaTransferTxCircular, I2s0Peripheral, - I2sPeripheral, PeripheralDmaChannel, ReadBuffer, Rx, @@ -447,7 +446,7 @@ where where I: I2s0Instance, CH: PeripheralDmaChannel, - CH::P: I2sPeripheral + I2s0Peripheral, + CH::P: I2s0Peripheral, DmaMode: Mode, { Self::new_internal( @@ -477,7 +476,7 @@ where where I: I2s1Instance, CH: PeripheralDmaChannel, - CH::P: I2sPeripheral + I2s1Peripheral, + CH::P: I2s1Peripheral, { Self::new_internal( i2s, diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 518ae45e72b..cb00f7ee96c 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -943,13 +943,13 @@ mod dma { /// This method prepares the SPI instance for DMA transfers. It /// initializes the DMA channel for transmission and returns an /// instance of `SpiDma` that supports DMA operations. - pub fn with_dma( + pub fn with_dma( self, - channel: Channel<'d, C, DmaMode>, + channel: Channel<'d, CH, DmaMode>, ) -> SpiDma<'d, crate::peripherals::SPI2, M, DmaMode> where - C: PeripheralDmaChannel, - C::P: SpiPeripheral + Spi2Peripheral, + CH: PeripheralDmaChannel, + CH::P: Spi2Peripheral, DmaMode: Mode, { SpiDma::new(self.spi, channel) @@ -966,13 +966,13 @@ mod dma { /// This method prepares the SPI instance for DMA transfers using SPI3 /// and returns an instance of `SpiDma` that supports DMA /// operations. - pub fn with_dma( + pub fn with_dma( self, - channel: Channel<'d, C, DmaMode>, + channel: Channel<'d, CH, DmaMode>, ) -> SpiDma<'d, crate::peripherals::SPI3, M, DmaMode> where - C: PeripheralDmaChannel, - C::P: SpiPeripheral + Spi3Peripheral, + CH: PeripheralDmaChannel, + CH::P: Spi3Peripheral, DmaMode: Mode, { SpiDma::new(self.spi, channel) diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index 01491183ed3..831ee657f0c 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -169,7 +169,6 @@ pub mod dma { ReadBuffer, Rx, Spi2Peripheral, - SpiPeripheral, Tx, WriteBuffer, }, @@ -180,15 +179,15 @@ pub mod dma { /// Configures the SPI3 peripheral with the provided DMA channel and /// descriptors. #[cfg_attr(esp32, doc = "\n\n**Note**: ESP32 only supports Mode 1 and 3.")] - pub fn with_dma( + pub fn with_dma( mut self, - channel: Channel<'d, C, DmaMode>, + channel: Channel<'d, CH, DmaMode>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI2, DmaMode> where - C: PeripheralDmaChannel, - C::P: SpiPeripheral + Spi2Peripheral, + CH: PeripheralDmaChannel, + CH::P: Spi2Peripheral, DmaMode: Mode, { self.spi.set_data_mode(self.data_mode, true); @@ -201,15 +200,15 @@ pub mod dma { /// Configures the SPI3 peripheral with the provided DMA channel and /// descriptors. #[cfg_attr(esp32, doc = "\n\n**Note**: ESP32 only supports Mode 1 and 3.")] - pub fn with_dma( + pub fn with_dma( mut self, - channel: Channel<'d, C, DmaMode>, + channel: Channel<'d, CH, DmaMode>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, crate::peripherals::SPI3, DmaMode> where - C: PeripheralDmaChannel, - C::P: SpiPeripheral + Spi3Peripheral, + CH: PeripheralDmaChannel, + CH::P: Spi3Peripheral, DmaMode: Mode, { self.spi.set_data_mode(self.data_mode, true); From b591eb6aaa18651399f90e4bd19e685d58982113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Thu, 3 Oct 2024 11:31:24 +0200 Subject: [PATCH 11/36] Remove peripheral-specific DMA traits --- esp-hal/src/aes/mod.rs | 6 +- esp-hal/src/dma/gdma.rs | 25 --------- esp-hal/src/dma/mod.rs | 53 ++++++------------ esp-hal/src/dma/pdma.rs | 12 +--- esp-hal/src/i2s.rs | 66 ++++++---------------- esp-hal/src/lcd_cam/cam.rs | 14 +---- esp-hal/src/lcd_cam/lcd/i8080.rs | 14 +---- esp-hal/src/spi/master.rs | 95 ++++++++++++++------------------ esp-hal/src/spi/slave.rs | 48 +++++++--------- 9 files changed, 102 insertions(+), 231 deletions(-) diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index d523f974621..840bb05da9e 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -235,16 +235,15 @@ pub mod dma { aes::{Key, Mode}, dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, - AesPeripheral, AnyDmaChannel, Channel, ChannelRx, ChannelTx, DescriptorChain, + DmaChannel, DmaDescriptor, DmaPeripheral, DmaTransferRxTx, - PeripheralDmaChannel, ReadBuffer, Rx, Tx, @@ -290,8 +289,7 @@ pub mod dma { ) -> AesDma<'d> where Self: Sized, - C: PeripheralDmaChannel, - C::P: AesPeripheral, + C: DmaChannel, { AesDma { aes: self, diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index 3d8bae2622c..ba0ae9fd1bd 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -421,24 +421,6 @@ pub struct ChannelCreator {} pub struct SuitablePeripheral {} impl PeripheralMarker for SuitablePeripheral {} -// with GDMA every channel can be used for any peripheral -impl SpiPeripheral for SuitablePeripheral {} -impl Spi2Peripheral for SuitablePeripheral {} -#[cfg(spi3)] -impl Spi3Peripheral for SuitablePeripheral {} -#[cfg(any(i2s0, i2s1))] -impl I2sPeripheral for SuitablePeripheral {} -#[cfg(i2s0)] -impl I2s0Peripheral for SuitablePeripheral {} -#[cfg(i2s1)] -impl I2s1Peripheral for SuitablePeripheral {} -#[cfg(parl_io)] -impl ParlIoPeripheral for SuitablePeripheral {} -#[cfg(aes)] -impl AesPeripheral for SuitablePeripheral {} -#[cfg(lcd_cam)] -impl LcdCamPeripheral for SuitablePeripheral {} - impl DmaChannel for AnyDmaChannel { type Rx = ChannelRxImpl; type Tx = ChannelTxImpl; @@ -451,10 +433,6 @@ impl DmaChannel for AnyDmaChannel { } } -impl PeripheralDmaChannel for AnyDmaChannel { - type P = SuitablePeripheral; -} - macro_rules! impl_channel { ($num: literal, $async_handler: path, $($interrupt: ident),* ) => { paste::paste! { @@ -475,9 +453,6 @@ macro_rules! impl_channel { tx.degrade() } } - impl PeripheralDmaChannel for [] { - type P = SuitablePeripheral; - } impl DmaChannelExt for [] { fn get_rx_interrupts() -> impl InterruptAccess { diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 2033074740b..129632403fd 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -900,46 +900,28 @@ pub trait DmaEligible { } } -/// Marks channels as useable for SPI -#[doc(hidden)] -pub trait SpiPeripheral: PeripheralMarker {} - -/// Marks channels as useable for SPI2 -#[doc(hidden)] -pub trait Spi2Peripheral: SpiPeripheral + PeripheralMarker {} - -/// Marks channels as useable for SPI3 -#[cfg(any(esp32, esp32s2, esp32s3))] -#[doc(hidden)] -pub trait Spi3Peripheral: SpiPeripheral + PeripheralMarker {} - -/// Marks channels as useable for I2S -#[doc(hidden)] -pub trait I2sPeripheral: PeripheralMarker {} - -/// Marks channels as useable for I2S0 -#[doc(hidden)] -pub trait I2s0Peripheral: I2sPeripheral + PeripheralMarker {} - -/// Marks channels as useable for I2S1 -#[doc(hidden)] -pub trait I2s1Peripheral: I2sPeripheral + PeripheralMarker {} - -/// Marks channels as useable for PARL_IO +/// Marker trait #[doc(hidden)] -pub trait ParlIoPeripheral: PeripheralMarker {} +pub trait PeripheralMarker {} -/// Marks channels as useable for AES #[doc(hidden)] -pub trait AesPeripheral: PeripheralMarker {} +pub trait DmaCompatible {} -/// Marks channels as usable for LCD_CAM -#[doc(hidden)] -pub trait LcdCamPeripheral: PeripheralMarker {} +#[cfg(gdma)] +impl DmaCompatible for (CH, P) +where + CH: DmaChannel, + P: PeripheralMarker, +{ +} -/// Marker trait -#[doc(hidden)] -pub trait PeripheralMarker {} +#[cfg(pdma)] +impl DmaCompatible for (CH, P) +where + CH: PeripheralDmaChannel

, + P: PeripheralMarker, +{ +} #[doc(hidden)] #[derive(Debug)] @@ -1543,6 +1525,7 @@ pub trait DmaChannel: crate::private::Sealed { } /// A description of a DMA Channel that can be used with a peripheral. +#[cfg(pdma)] pub trait PeripheralDmaChannel: DmaChannel { /// A suitable peripheral for this DMA channel. type P: PeripheralMarker; diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index f4304518e27..3a36d52a184 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -887,35 +887,27 @@ macro_rules! ImplI2sChannel { #[non_exhaustive] pub struct Spi2DmaSuitablePeripheral {} impl PeripheralMarker for Spi2DmaSuitablePeripheral {} -impl SpiPeripheral for Spi2DmaSuitablePeripheral {} -impl Spi2Peripheral for Spi2DmaSuitablePeripheral {} #[doc(hidden)] #[non_exhaustive] pub struct Spi3DmaSuitablePeripheral {} impl PeripheralMarker for Spi3DmaSuitablePeripheral {} -impl SpiPeripheral for Spi3DmaSuitablePeripheral {} -impl Spi3Peripheral for Spi3DmaSuitablePeripheral {} ImplSpiChannel!(2); +#[cfg(spi3)] ImplSpiChannel!(3); #[doc(hidden)] #[non_exhaustive] pub struct I2s0DmaSuitablePeripheral {} impl PeripheralMarker for I2s0DmaSuitablePeripheral {} -impl I2sPeripheral for I2s0DmaSuitablePeripheral {} -impl I2s0Peripheral for I2s0DmaSuitablePeripheral {} - -ImplI2sChannel!(0); #[doc(hidden)] #[non_exhaustive] pub struct I2s1DmaSuitablePeripheral {} impl PeripheralMarker for I2s1DmaSuitablePeripheral {} -impl I2sPeripheral for I2s1DmaSuitablePeripheral {} -impl I2s1Peripheral for I2s1DmaSuitablePeripheral {} +ImplI2sChannel!(0); #[cfg(i2s1)] ImplI2sChannel!(1); diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index 29a29d5322c..479b89dd0e4 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -84,8 +84,6 @@ use core::marker::PhantomData; use enumset::{EnumSet, EnumSetType}; use private::*; -#[cfg(i2s1)] -use crate::dma::I2s1Peripheral; use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, @@ -101,8 +99,6 @@ use crate::{ DmaTransferRxCircular, DmaTransferTx, DmaTransferTxCircular, - I2s0Peripheral, - PeripheralDmaChannel, ReadBuffer, Rx, Tx, @@ -444,9 +440,8 @@ where tx_descriptors: &'static mut [DmaDescriptor], ) -> Self where - I: I2s0Instance, - CH: PeripheralDmaChannel, - CH::P: I2s0Peripheral, + CH: crate::dma::DmaChannel, + (CH, I::Peripheral): crate::dma::DmaCompatible, DmaMode: Mode, { Self::new_internal( @@ -460,35 +455,6 @@ where ) } - /// Construct a new I2S peripheral driver instance for the second I2S - /// peripheral - #[allow(clippy::too_many_arguments)] - #[cfg(i2s1)] - pub fn new_i2s1( - i2s: impl Peripheral

+ 'd, - standard: Standard, - data_format: DataFormat, - sample_rate: impl Into, - channel: Channel<'d, CH, DmaMode>, - rx_descriptors: &'static mut [DmaDescriptor], - tx_descriptors: &'static mut [DmaDescriptor], - ) -> Self - where - I: I2s1Instance, - CH: PeripheralDmaChannel, - CH::P: I2s1Peripheral, - { - Self::new_internal( - i2s, - standard, - data_format, - sample_rate, - channel, - rx_descriptors, - tx_descriptors, - ) - } - /// Configures the I2S peripheral to use a master clock (MCLK) output pin. pub fn with_mclk(self, pin: impl Peripheral

+ 'd) -> Self { into_ref!(pin); @@ -840,6 +806,7 @@ where /// Provides an abstraction for accessing the I2S peripheral registers. pub trait RegisterAccess: RegisterAccessPrivate {} +impl RegisterAccess for T where T: RegisterAccessPrivate {} mod private { use core::marker::PhantomData; @@ -1007,6 +974,8 @@ mod private { #[cfg(any(esp32, esp32s2))] pub trait RegisterAccessPrivate: Signals + RegBlock { + type Peripheral; + fn set_interrupt_handler(handler: InterruptHandler); fn enable_listen(interrupts: EnumSet, enable: bool) { @@ -1261,6 +1230,8 @@ mod private { #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] pub trait RegisterAccessPrivate: Signals + RegBlock { + type Peripheral; + fn set_interrupt_handler(handler: InterruptHandler); fn enable_listen(interrupts: EnumSet, enable: bool) { @@ -1939,34 +1910,31 @@ mod private { } impl RegisterAccessPrivate for I2S0 { + #[cfg(pdma)] + type Peripheral = crate::dma::I2s0DmaSuitablePeripheral; + #[cfg(gdma)] + type Peripheral = crate::dma::SuitablePeripheral; + fn set_interrupt_handler(handler: InterruptHandler) { unsafe { crate::peripherals::I2S0::steal() }.bind_i2s0_interrupt(handler.handler()); crate::interrupt::enable(crate::peripherals::Interrupt::I2S0, handler.priority()) .unwrap(); } } - impl super::RegisterAccess for I2S0 {} #[cfg(i2s1)] impl RegisterAccessPrivate for I2S1 { + #[cfg(pdma)] + type Peripheral = crate::dma::I2s1DmaSuitablePeripheral; + #[cfg(gdma)] + type Peripheral = crate::dma::SuitablePeripheral; + fn set_interrupt_handler(handler: InterruptHandler) { unsafe { crate::peripherals::I2S1::steal() }.bind_i2s1_interrupt(handler.handler()); crate::interrupt::enable(crate::peripherals::Interrupt::I2S1, handler.priority()) .unwrap(); } } - #[cfg(i2s1)] - impl super::RegisterAccess for I2S1 {} - - pub trait I2s0Instance {} - - #[cfg(any(esp32s3, esp32))] - pub trait I2s1Instance {} - - impl I2s0Instance for I2S0 {} - - #[cfg(any(esp32s3, esp32))] - impl I2s1Instance for I2S1 {} pub struct I2sClockDividers { mclk_divider: u32, diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index 574fc578f31..bb6c0adf821 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -74,16 +74,7 @@ use fugit::HertzU32; use crate::{ clock::Clocks, - dma::{ - AnyDmaChannel, - ChannelRx, - DmaError, - DmaPeripheral, - DmaRxBuffer, - LcdCamPeripheral, - PeripheralDmaChannel, - Rx, - }, + dma::{AnyDmaChannel, ChannelRx, DmaChannel, DmaError, DmaPeripheral, DmaRxBuffer, Rx}, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull}, lcd_cam::{cam::private::RxPins, private::calculate_clkm, BitOrder, ByteOrder}, peripheral::{Peripheral, PeripheralRef}, @@ -143,8 +134,7 @@ impl<'d> Camera<'d> { frequency: HertzU32, ) -> Self where - CH: PeripheralDmaChannel, - CH::P: LcdCamPeripheral, + CH: DmaChannel, P: RxPins, { let lcd_cam = cam.lcd_cam; diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index bc443a5ca4d..fb58218bfec 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -69,16 +69,7 @@ use fugit::HertzU32; use crate::{ clock::Clocks, - dma::{ - AnyDmaChannel, - ChannelTx, - DmaError, - DmaPeripheral, - DmaTxBuffer, - LcdCamPeripheral, - PeripheralDmaChannel, - Tx, - }, + dma::{AnyDmaChannel, ChannelTx, DmaChannel, DmaError, DmaPeripheral, DmaTxBuffer, Tx}, gpio::{OutputSignal, PeripheralOutput}, lcd_cam::{ asynch::LCD_DONE_WAKER, @@ -110,8 +101,7 @@ impl<'d, DM: Mode> I8080<'d, DM> { config: Config, ) -> Self where - CH: PeripheralDmaChannel, - CH::P: LcdCamPeripheral, + CH: DmaChannel, P: TxPins, { let lcd_cam = lcd.lcd_cam; diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index cb00f7ee96c..d001a20194f 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -485,6 +485,29 @@ where } } +impl<'d, T, M> Spi<'d, T, M> +where + T: InstanceDma, + M: DuplexMode, +{ + /// Configures the SPI3 instance to use DMA with the specified channel. + /// + /// This method prepares the SPI instance for DMA transfers using SPI3 + /// and returns an instance of `SpiDma` that supports DMA + /// operations. + pub fn with_dma( + self, + channel: crate::dma::Channel<'d, CH, DmaMode>, + ) -> SpiDma<'d, T, M, DmaMode> + where + CH: crate::dma::DmaChannel, + (CH, T::Peripheral): crate::dma::DmaCompatible, + DmaMode: crate::Mode, + { + SpiDma::new(self.spi, channel) + } +} + impl<'d, T> Spi<'d, T, FullDuplexMode> where T: Instance, @@ -913,72 +936,23 @@ mod dma { }; use super::*; - #[cfg(spi3)] - use crate::dma::Spi3Peripheral; use crate::{ dma::{ asynch::{DmaRxFuture, DmaTxFuture}, AnyDmaChannel, Channel, + DmaChannel, DmaRxBuf, DmaRxBuffer, DmaTxBuf, DmaTxBuffer, - PeripheralDmaChannel, Rx, - Spi2Peripheral, - SpiPeripheral, Tx, }, InterruptConfigurable, Mode, }; - impl<'d, M> Spi<'d, crate::peripherals::SPI2, M> - where - M: DuplexMode, - { - /// Configures the SPI instance to use DMA with the specified channel. - /// - /// This method prepares the SPI instance for DMA transfers. It - /// initializes the DMA channel for transmission and returns an - /// instance of `SpiDma` that supports DMA operations. - pub fn with_dma( - self, - channel: Channel<'d, CH, DmaMode>, - ) -> SpiDma<'d, crate::peripherals::SPI2, M, DmaMode> - where - CH: PeripheralDmaChannel, - CH::P: Spi2Peripheral, - DmaMode: Mode, - { - SpiDma::new(self.spi, channel) - } - } - - #[cfg(spi3)] - impl<'d, M> Spi<'d, crate::peripherals::SPI3, M> - where - M: DuplexMode, - { - /// Configures the SPI3 instance to use DMA with the specified channel. - /// - /// This method prepares the SPI instance for DMA transfers using SPI3 - /// and returns an instance of `SpiDma` that supports DMA - /// operations. - pub fn with_dma( - self, - channel: Channel<'d, CH, DmaMode>, - ) -> SpiDma<'d, crate::peripherals::SPI3, M, DmaMode> - where - CH: PeripheralDmaChannel, - CH::P: Spi3Peripheral, - DmaMode: Mode, - { - SpiDma::new(self.spi, channel) - } - } - /// A DMA capable SPI instance. /// /// Using `SpiDma` is not recommended unless you wish @@ -1028,10 +1002,9 @@ mod dma { D: DuplexMode, M: Mode, { - fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, CH, M>) -> Self + pub(super) fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, CH, M>) -> Self where - CH: PeripheralDmaChannel, - CH::P: SpiPeripheral, + CH: DmaChannel, { #[cfg(all(esp32, spi_address_workaround))] let address_buffer = { @@ -2240,6 +2213,8 @@ mod ehal1 { #[doc(hidden)] pub trait InstanceDma: Instance { + type Peripheral; + #[allow(clippy::too_many_arguments)] unsafe fn start_transfer_dma( &mut self, @@ -2447,10 +2422,20 @@ pub trait InstanceDma: Instance { } } -impl InstanceDma for crate::peripherals::SPI2 {} +impl InstanceDma for crate::peripherals::SPI2 { + #[cfg(pdma)] + type Peripheral = crate::dma::Spi2DmaSuitablePeripheral; + #[cfg(gdma)] + type Peripheral = crate::dma::SuitablePeripheral; +} #[cfg(spi3)] -impl InstanceDma for crate::peripherals::SPI3 {} +impl InstanceDma for crate::peripherals::SPI3 { + #[cfg(pdma)] + type Peripheral = crate::dma::Spi3DmaSuitablePeripheral; + #[cfg(gdma)] + type Peripheral = crate::dma::SuitablePeripheral; +} #[doc(hidden)] pub trait ExtendedInstance: Instance { diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index 831ee657f0c..b3d50483154 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -150,8 +150,6 @@ where /// DMA (Direct Memory Access) functionality (Slave). pub mod dma { use super::*; - #[cfg(spi3)] - use crate::dma::Spi3Peripheral; use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, @@ -165,38 +163,18 @@ pub mod dma { DmaTransferRx, DmaTransferRxTx, DmaTransferTx, - PeripheralDmaChannel, ReadBuffer, Rx, - Spi2Peripheral, Tx, WriteBuffer, }, Mode, }; - impl<'d> Spi<'d, crate::peripherals::SPI2, FullDuplexMode> { - /// Configures the SPI3 peripheral with the provided DMA channel and - /// descriptors. - #[cfg_attr(esp32, doc = "\n\n**Note**: ESP32 only supports Mode 1 and 3.")] - pub fn with_dma( - mut self, - channel: Channel<'d, CH, DmaMode>, - rx_descriptors: &'static mut [DmaDescriptor], - tx_descriptors: &'static mut [DmaDescriptor], - ) -> SpiDma<'d, crate::peripherals::SPI2, DmaMode> - where - CH: PeripheralDmaChannel, - CH::P: Spi2Peripheral, - DmaMode: Mode, - { - self.spi.set_data_mode(self.data_mode, true); - SpiDma::new(self.spi, channel, rx_descriptors, tx_descriptors) - } - } - - #[cfg(spi3)] - impl<'d> Spi<'d, crate::peripherals::SPI3, FullDuplexMode> { + impl<'d, T> Spi<'d, T, FullDuplexMode> + where + T: InstanceDma, + { /// Configures the SPI3 peripheral with the provided DMA channel and /// descriptors. #[cfg_attr(esp32, doc = "\n\n**Note**: ESP32 only supports Mode 1 and 3.")] @@ -205,10 +183,10 @@ pub mod dma { channel: Channel<'d, CH, DmaMode>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], - ) -> SpiDma<'d, crate::peripherals::SPI3, DmaMode> + ) -> SpiDma<'d, T, DmaMode> where - CH: PeripheralDmaChannel, - CH::P: Spi3Peripheral, + CH: DmaChannel, + (CH, T::Peripheral): crate::dma::DmaCompatible, DmaMode: Mode, { self.spi.set_data_mode(self.data_mode, true); @@ -421,6 +399,8 @@ pub mod dma { #[doc(hidden)] pub trait InstanceDma: Instance { + type Peripheral; + fn dma_peripheral(&self) -> DmaPeripheral; #[allow(clippy::too_many_arguments)] @@ -565,12 +545,22 @@ fn reset_dma_before_usr_cmd(reg_block: &RegisterBlock) { } impl InstanceDma for crate::peripherals::SPI2 { + #[cfg(pdma)] + type Peripheral = crate::dma::Spi2DmaSuitablePeripheral; + #[cfg(gdma)] + type Peripheral = crate::dma::SuitablePeripheral; + fn dma_peripheral(&self) -> DmaPeripheral { DmaPeripheral::Spi2 } } #[cfg(spi3)] impl InstanceDma for crate::peripherals::SPI3 { + #[cfg(pdma)] + type Peripheral = crate::dma::Spi3DmaSuitablePeripheral; + #[cfg(gdma)] + type Peripheral = crate::dma::SuitablePeripheral; + fn dma_peripheral(&self) -> DmaPeripheral { DmaPeripheral::Spi3 } From 7bafec99cfd62158567ee9eb1e3f9055d5fd032e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Thu, 3 Oct 2024 11:33:32 +0200 Subject: [PATCH 12/36] Document i2s change --- esp-hal/CHANGELOG.md | 1 + esp-hal/MIGRATING-0.20.md | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index b6977bb6cf6..d2d398c8854 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -108,6 +108,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed `esp_hal::spi::slave::prelude` (#2260) - Removed `esp_hal::spi::slave::WithDmaSpiN` traits (#2260) - The `WithDmaAes` trait has been removed (#2261) +- The `I2s::new_i2s1` constructor has been removed (#2261) ## [0.20.1] - 2024-08-30 diff --git a/esp-hal/MIGRATING-0.20.md b/esp-hal/MIGRATING-0.20.md index 6c04aa0a4ff..3dcbad9da06 100644 --- a/esp-hal/MIGRATING-0.20.md +++ b/esp-hal/MIGRATING-0.20.md @@ -126,6 +126,10 @@ When using the asymmetric variant of the macro to create DMA buffers and descrip The `Uart::new_with_default_pins` and `Uart::new_async_with_default_pins` constructors have been removed. Use `new` or `new_async` instead. +## Removed I2S1-specific constructor + +The `I2s::new_i2s1` constructor has been removed. Use `I2s::new` instead. + ## Timer changes ### `ErasedTimer` rename From 9111e56c44a73b62365e7f34f2359b7e61a434eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Thu, 3 Oct 2024 14:03:56 +0200 Subject: [PATCH 13/36] Clean up parl_io --- esp-hal/src/parl_io.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index e0a55d4aaf9..fa88b88fcab 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -38,13 +38,12 @@ use crate::{ ChannelRx, ChannelTx, DescriptorChain, + DmaChannel, DmaDescriptor, DmaError, DmaPeripheral, DmaTransferRx, DmaTransferTx, - ParlIoPeripheral, - PeripheralDmaChannel, ReadBuffer, Rx, Tx, @@ -1101,8 +1100,7 @@ where frequency: HertzU32, ) -> Result where - CH: PeripheralDmaChannel, - CH::P: ParlIoPeripheral, + CH: DmaChannel, { internal_init(frequency)?; @@ -1182,8 +1180,7 @@ where frequency: HertzU32, ) -> Result where - CH: PeripheralDmaChannel, - CH::P: ParlIoPeripheral, + CH: DmaChannel, { internal_init(frequency)?; @@ -1258,8 +1255,7 @@ where frequency: HertzU32, ) -> Result where - CH: PeripheralDmaChannel, - CH::P: ParlIoPeripheral, + CH: DmaChannel, { internal_init(frequency)?; From dd4605d714624a287fb72fe0a89df7d6a72674a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Thu, 3 Oct 2024 22:10:44 +0200 Subject: [PATCH 14/36] Deduplicate InterruptAccess --- esp-hal/src/dma/pdma.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 3a36d52a184..e4c8b29211d 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -116,8 +116,8 @@ impl TxRegisterAccess for SpiDmaTxChannelImpl { impl InterruptAccess for SpiDmaTxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { - let spi = self.0.register_block(); - spi.dma_int_ena().modify(|_, w| { + let reg_block = self.0.register_block(); + reg_block.dma_int_ena().modify(|_, w| { for interrupt in interrupts { match interrupt { DmaTxInterrupt::TotalEof => w.out_total_eof().bit(enable), @@ -238,8 +238,8 @@ impl RxRegisterAccess for SpiDmaRxChannelImpl {} impl InterruptAccess for SpiDmaRxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { - let spi = self.0.register_block(); - spi.dma_int_ena().modify(|_, w| { + let reg_block = self.0.register_block(); + reg_block.dma_int_ena().modify(|_, w| { for interrupt in interrupts { match interrupt { DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().bit(enable), @@ -677,7 +677,7 @@ impl RxRegisterAccess for I2sDmaRxChannelImpl {} impl InterruptAccess for I2sDmaRxChannelImpl { fn enable_listen(&self, interrupts: EnumSet, enable: bool) { - let spi = self.0.register_block(); + let reg_block = self.0.register_block(); reg_block.int_ena().modify(|_, w| { for interrupt in interrupts { match interrupt { @@ -980,8 +980,7 @@ impl InterruptAccess for AnyPdmaRxChannelImpl { #[cfg(i2s1)] AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaRxChannelImpl(channel.clone_unchecked()) }, } { - fn listen(&self, interrupts: impl Into>); - fn unlisten(&self, interrupts: impl Into>); + fn enable_listen(&self, interrupts: EnumSet, enable: bool); fn is_listening(&self) -> EnumSet; fn clear(&self, interrupts: impl Into>); fn pending_interrupts(&self) -> EnumSet; @@ -1000,7 +999,6 @@ impl RegisterAccess for AnyPdmaRxChannelImpl { } { fn set_burst_mode(&self, burst_mode: bool); fn set_priority(&self, priority: DmaPriority); - fn clear_interrupts(&self); fn reset(&self); fn set_link_addr(&self, address: u32); fn set_peripheral(&self, peripheral: u8); @@ -1025,8 +1023,7 @@ impl InterruptAccess for AnyPdmaTxChannelImpl { #[cfg(i2s1)] AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, } { - fn listen(&self, interrupts: impl Into>); - fn unlisten(&self, interrupts: impl Into>); + fn enable_listen(&self, interrupts: EnumSet, enable: bool); fn is_listening(&self) -> EnumSet; fn clear(&self, interrupts: impl Into>); fn pending_interrupts(&self) -> EnumSet; @@ -1045,7 +1042,6 @@ impl RegisterAccess for AnyPdmaTxChannelImpl { } { fn set_burst_mode(&self, burst_mode: bool); fn set_priority(&self, priority: DmaPriority); - fn clear_interrupts(&self); fn reset(&self); fn set_link_addr(&self, address: u32); fn set_peripheral(&self, peripheral: u8); From 0e5a20fb9c0cd43f2d49850983640b71d611aef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Thu, 3 Oct 2024 23:36:10 +0200 Subject: [PATCH 15/36] Fix cfg --- esp-hal/src/dma/pdma.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index e4c8b29211d..3503c52fbd0 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -923,7 +923,7 @@ pub struct Dma<'d> { /// DMA channel for I2S0 pub i2s0channel: I2s0DmaChannelCreator, /// DMA channel for I2S1 - #[cfg(esp32)] + #[cfg(i2s1)] pub i2s1channel: I2s1DmaChannelCreator, } From d2e3a4b40632561a9701906a4464da4db9ad7635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Thu, 3 Oct 2024 23:33:33 +0200 Subject: [PATCH 16/36] Implement runtime compatibility check --- esp-hal/src/dma/gdma.rs | 16 +++++++- esp-hal/src/dma/mod.rs | 24 ++++------- esp-hal/src/dma/pdma.rs | 86 +++++++++++++++++++++++++++++++++++---- esp-hal/src/i2s.rs | 41 +++++++++++++++++-- esp-hal/src/spi/master.rs | 27 +++++++++++- esp-hal/src/spi/slave.rs | 27 +++++++++++- esp-hal/src/system.rs | 2 + 7 files changed, 189 insertions(+), 34 deletions(-) diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index ba0ae9fd1bd..43c7c84d7e4 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -418,7 +418,7 @@ pub struct ChannelCreator {} #[non_exhaustive] #[doc(hidden)] -pub struct SuitablePeripheral {} +pub struct SuitablePeripheral; impl PeripheralMarker for SuitablePeripheral {} impl DmaChannel for AnyDmaChannel { @@ -433,6 +433,20 @@ impl DmaChannel for AnyDmaChannel { } } +impl Channel<'_, CH, M> { + /// Asserts that the channel is compatible with the given peripheral. + pub fn runtime_ensure_compatible(&self, _peripheral: P) { + // GDMA channels are compatible with any peripheral + } +} + +impl DmaCompatible for (CH, P) +where + CH: DmaChannel, + P: PeripheralMarker, +{ +} + macro_rules! impl_channel { ($num: literal, $async_handler: path, $($interrupt: ident),* ) => { paste::paste! { diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 129632403fd..9b4dd265c0e 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -902,27 +902,14 @@ pub trait DmaEligible { /// Marker trait #[doc(hidden)] -pub trait PeripheralMarker {} +pub trait PeripheralMarker { + #[cfg(pdma)] + fn peripheral(&self) -> crate::system::Peripheral; +} #[doc(hidden)] pub trait DmaCompatible {} -#[cfg(gdma)] -impl DmaCompatible for (CH, P) -where - CH: DmaChannel, - P: PeripheralMarker, -{ -} - -#[cfg(pdma)] -impl DmaCompatible for (CH, P) -where - CH: PeripheralDmaChannel

, - P: PeripheralMarker, -{ -} - #[doc(hidden)] #[derive(Debug)] pub struct DescriptorChain { @@ -2004,6 +1991,9 @@ pub trait RegisterAccess: crate::private::Sealed { #[cfg(esp32s3)] fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize); + + #[cfg(pdma)] + fn is_compatible_with(&self, peripheral: P) -> bool; } #[doc(hidden)] diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 3503c52fbd0..6177dc4bf9b 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -27,6 +27,7 @@ pub trait SpiPdmaChannel: crate::private::Sealed { fn register_block(&self) -> &SpiRegisterBlock; fn tx_waker(&self) -> &'static AtomicWaker; fn rx_waker(&self) -> &'static AtomicWaker; + fn is_compatible_with(&self, peripheral: P) -> bool; } #[doc(hidden)] @@ -34,6 +35,7 @@ pub trait I2sPdmaChannel: crate::private::Sealed { fn register_block(&self) -> &I2sRegisterBlock; fn tx_waker(&self) -> &'static AtomicWaker; fn rx_waker(&self) -> &'static AtomicWaker; + fn is_compatible_with(&self, peripheral: P) -> bool; } #[doc(hidden)] @@ -105,6 +107,10 @@ impl RegisterAccess for SpiDmaTxChannelImpl { spi.dma_out_link() .modify(|_, w| w.outlink_restart().set_bit()); } + + fn is_compatible_with(&self, peripheral: P) -> bool { + self.0.is_compatible_with(peripheral) + } } impl TxRegisterAccess for SpiDmaTxChannelImpl { @@ -232,6 +238,10 @@ impl RegisterAccess for SpiDmaRxChannelImpl { spi.dma_in_link() .modify(|_, w| w.inlink_restart().set_bit()); } + + fn is_compatible_with(&self, peripheral: P) -> bool { + self.0.is_compatible_with(peripheral) + } } impl RxRegisterAccess for SpiDmaRxChannelImpl {} @@ -390,6 +400,10 @@ macro_rules! ImplSpiChannel { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } + + fn is_compatible_with(&self, peripheral: P) -> bool { + p.peripheral() == crate::system::Peripheral::[] + } } impl $crate::private::Sealed for [] {} @@ -535,6 +549,10 @@ impl RegisterAccess for I2sDmaTxChannelImpl { .out_link() .modify(|_, w| w.outlink_restart().set_bit()); } + + fn is_compatible_with(&self, peripheral: P) -> bool { + self.0.is_compatible_with(peripheral) + } } impl TxRegisterAccess for I2sDmaTxChannelImpl { @@ -671,6 +689,10 @@ impl RegisterAccess for I2sDmaRxChannelImpl { .in_link() .modify(|_, w| w.inlink_restart().set_bit()); } + + fn is_compatible_with(&self, peripheral: P) -> bool { + self.0.is_compatible_with(peripheral) + } } impl RxRegisterAccess for I2sDmaRxChannelImpl {} @@ -825,6 +847,9 @@ macro_rules! ImplI2sChannel { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } + fn is_compatible_with(&self, peripheral: P) -> bool { + p.peripheral() == crate::system::Peripheral::[] + } } #[doc = concat!("Creates a channel for I2S", $num)] @@ -885,13 +910,21 @@ macro_rules! ImplI2sChannel { #[doc(hidden)] #[non_exhaustive] -pub struct Spi2DmaSuitablePeripheral {} -impl PeripheralMarker for Spi2DmaSuitablePeripheral {} +pub struct Spi2DmaSuitablePeripheral; +impl PeripheralMarker for Spi2DmaSuitablePeripheral { + fn peripheral(&self) -> crate::system::Peripheral { + crate::system::Peripheral::Spi2 + } +} #[doc(hidden)] #[non_exhaustive] -pub struct Spi3DmaSuitablePeripheral {} -impl PeripheralMarker for Spi3DmaSuitablePeripheral {} +pub struct Spi3DmaSuitablePeripheral; +impl PeripheralMarker for Spi3DmaSuitablePeripheral { + fn peripheral(&self) -> crate::system::Peripheral { + crate::system::Peripheral::Spi3 + } +} ImplSpiChannel!(2); #[cfg(spi3)] @@ -899,13 +932,23 @@ ImplSpiChannel!(3); #[doc(hidden)] #[non_exhaustive] -pub struct I2s0DmaSuitablePeripheral {} -impl PeripheralMarker for I2s0DmaSuitablePeripheral {} +pub struct I2s0DmaSuitablePeripheral; +impl PeripheralMarker for I2s0DmaSuitablePeripheral { + fn peripheral(&self) -> crate::system::Peripheral { + crate::system::Peripheral::I2s0 + } +} #[doc(hidden)] #[non_exhaustive] -pub struct I2s1DmaSuitablePeripheral {} -impl PeripheralMarker for I2s1DmaSuitablePeripheral {} +#[cfg(i2s1)] +pub struct I2s1DmaSuitablePeripheral; +#[cfg(i2s1)] +impl PeripheralMarker for I2s1DmaSuitablePeripheral { + fn peripheral(&self) -> crate::system::Peripheral { + crate::system::Peripheral::I2s1 + } +} ImplI2sChannel!(0); #[cfg(i2s1)] @@ -1005,6 +1048,7 @@ impl RegisterAccess for AnyPdmaRxChannelImpl { fn start(&self); fn stop(&self); fn restart(&self); + fn is_compatible_with(&self, peripheral: P) -> bool; } } } @@ -1048,6 +1092,7 @@ impl RegisterAccess for AnyPdmaTxChannelImpl { fn start(&self); fn stop(&self); fn restart(&self); + fn is_compatible_with(&self, peripheral: P) -> bool; } } } @@ -1064,3 +1109,28 @@ impl TxRegisterAccess for AnyPdmaTxChannelImpl { } } } + +impl<'d, C, M: Mode> Channel<'d, C, M> +where + C: DmaChannel, +{ + /// Asserts that the channel is compatible with the given peripheral. + pub fn runtime_ensure_compatible(&self, peripheral: P) { + assert!( + self.tx.tx_impl.is_compatible_with(p), + "This DMA channel is not compatible with {:?}", + p.peripheral() + ); + } +} + +#[cfg(pdma)] +impl DmaCompatible for (CH, P) +where + CH: PeripheralDmaChannel

, + P: PeripheralMarker, +{ +} + +#[cfg(pdma)] +impl

DmaCompatible for (AnyDmaChannel, P) where P: PeripheralMarker {} diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index 479b89dd0e4..a9a7bf5da42 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -334,7 +334,7 @@ where { #[allow(clippy::too_many_arguments)] fn new_internal( - _i2s: impl Peripheral

+ 'd, + i2s: impl Peripheral

+ 'd, standard: Standard, data_format: DataFormat, sample_rate: impl Into, @@ -342,6 +342,8 @@ where rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> Self { + crate::into_ref!(i2s); + channel.runtime_ensure_compatible(i2s.dma_peripheral_marker()); // on ESP32-C3 / ESP32-S3 and later RX and TX are independent and // could be configured totally independently but for now handle all // the targets the same and force same configuration for both, TX and RX @@ -830,7 +832,14 @@ mod private { #[cfg(any(esp32, esp32s3))] use crate::peripherals::{i2s1::RegisterBlock, I2S1}; use crate::{ - dma::{AnyDmaChannel, ChannelRx, ChannelTx, DmaDescriptor, DmaPeripheral}, + dma::{ + AnyDmaChannel, + ChannelRx, + ChannelTx, + DmaDescriptor, + DmaPeripheral, + PeripheralMarker, + }, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, into_ref, @@ -974,7 +983,9 @@ mod private { #[cfg(any(esp32, esp32s2))] pub trait RegisterAccessPrivate: Signals + RegBlock { - type Peripheral; + type Peripheral: PeripheralMarker; + + fn dma_peripheral_marker(&self) -> Self::Peripheral; fn set_interrupt_handler(handler: InterruptHandler); @@ -1230,7 +1241,9 @@ mod private { #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] pub trait RegisterAccessPrivate: Signals + RegBlock { - type Peripheral; + type Peripheral: PeripheralMarker; + + fn dma_peripheral_marker(&self) -> Self::Peripheral; fn set_interrupt_handler(handler: InterruptHandler); @@ -1915,6 +1928,16 @@ mod private { #[cfg(gdma)] type Peripheral = crate::dma::SuitablePeripheral; + fn dma_peripheral_marker(&self) -> Self::Peripheral { + cfg_if::cfg_if! { + if #[cfg(pdma)] { + crate::dma::I2s0DmaSuitablePeripheral + } else { + crate::dma::SuitablePeripheral + } + } + } + fn set_interrupt_handler(handler: InterruptHandler) { unsafe { crate::peripherals::I2S0::steal() }.bind_i2s0_interrupt(handler.handler()); crate::interrupt::enable(crate::peripherals::Interrupt::I2S0, handler.priority()) @@ -1929,6 +1952,16 @@ mod private { #[cfg(gdma)] type Peripheral = crate::dma::SuitablePeripheral; + fn dma_peripheral_marker(&self) -> Self::Peripheral { + cfg_if::cfg_if! { + if #[cfg(pdma)] { + crate::dma::I2s1DmaSuitablePeripheral + } else { + crate::dma::SuitablePeripheral + } + } + } + fn set_interrupt_handler(handler: InterruptHandler) { unsafe { crate::peripherals::I2S1::steal() }.bind_i2s1_interrupt(handler.handler()); crate::interrupt::enable(crate::peripherals::Interrupt::I2S1, handler.priority()) diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index d001a20194f..b869f646e46 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -81,7 +81,7 @@ use super::{ }; use crate::{ clock::Clocks, - dma::{DmaPeripheral, DmaRxBuffer, DmaTxBuffer, Rx, Tx}, + dma::{DmaPeripheral, DmaRxBuffer, DmaTxBuffer, PeripheralMarker, Rx, Tx}, gpio::{InputSignal, NoPin, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, @@ -1006,6 +1006,7 @@ mod dma { where CH: DmaChannel, { + channel.runtime_ensure_compatible(spi.dma_peripheral_marker()); #[cfg(all(esp32, spi_address_workaround))] let address_buffer = { use crate::dma::DmaDescriptor; @@ -2213,7 +2214,9 @@ mod ehal1 { #[doc(hidden)] pub trait InstanceDma: Instance { - type Peripheral; + type Peripheral: PeripheralMarker; + + fn dma_peripheral_marker(&self) -> Self::Peripheral; #[allow(clippy::too_many_arguments)] unsafe fn start_transfer_dma( @@ -2427,6 +2430,16 @@ impl InstanceDma for crate::peripherals::SPI2 { type Peripheral = crate::dma::Spi2DmaSuitablePeripheral; #[cfg(gdma)] type Peripheral = crate::dma::SuitablePeripheral; + + fn dma_peripheral_marker(&self) -> Self::Peripheral { + cfg_if::cfg_if! { + if #[cfg(pdma)] { + crate::dma::Spi2DmaSuitablePeripheral + } else { + crate::dma::SuitablePeripheral + } + } + } } #[cfg(spi3)] @@ -2435,6 +2448,16 @@ impl InstanceDma for crate::peripherals::SPI3 { type Peripheral = crate::dma::Spi3DmaSuitablePeripheral; #[cfg(gdma)] type Peripheral = crate::dma::SuitablePeripheral; + + fn dma_peripheral_marker(&self) -> Self::Peripheral { + cfg_if::cfg_if! { + if #[cfg(pdma)] { + crate::dma::Spi3DmaSuitablePeripheral + } else { + crate::dma::SuitablePeripheral + } + } + } } #[doc(hidden)] diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index b3d50483154..50fd31ebd60 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -73,7 +73,7 @@ use core::marker::PhantomData; use super::{Error, FullDuplexMode, SpiMode}; use crate::{ - dma::{DescriptorChain, DmaPeripheral, Rx, Tx}, + dma::{DescriptorChain, DmaPeripheral, PeripheralMarker, Rx, Tx}, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, peripheral::{Peripheral, PeripheralRef}, peripherals::spi2::RegisterBlock, @@ -279,6 +279,7 @@ pub mod dma { where CH: DmaChannel, { + channel.runtime_ensure_compatible(spi.dma_peripheral_marker()); Self { spi, channel: channel.degrade(), @@ -399,7 +400,9 @@ pub mod dma { #[doc(hidden)] pub trait InstanceDma: Instance { - type Peripheral; + type Peripheral: PeripheralMarker; + + fn dma_peripheral_marker(&self) -> Self::Peripheral; fn dma_peripheral(&self) -> DmaPeripheral; @@ -550,6 +553,16 @@ impl InstanceDma for crate::peripherals::SPI2 { #[cfg(gdma)] type Peripheral = crate::dma::SuitablePeripheral; + fn dma_peripheral_marker(&self) -> Self::Peripheral { + cfg_if::cfg_if! { + if #[cfg(pdma)] { + crate::dma::Spi2DmaSuitablePeripheral + } else { + crate::dma::SuitablePeripheral + } + } + } + fn dma_peripheral(&self) -> DmaPeripheral { DmaPeripheral::Spi2 } @@ -561,6 +574,16 @@ impl InstanceDma for crate::peripherals::SPI3 { #[cfg(gdma)] type Peripheral = crate::dma::SuitablePeripheral; + fn dma_peripheral_marker(&self) -> Self::Peripheral { + cfg_if::cfg_if! { + if #[cfg(pdma)] { + crate::dma::Spi3DmaSuitablePeripheral + } else { + crate::dma::SuitablePeripheral + } + } + } + fn dma_peripheral(&self) -> DmaPeripheral { DmaPeripheral::Spi3 } diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index 4b031e91c17..0406d89d0f4 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -15,6 +15,8 @@ use crate::peripherals::SYSTEM; // FIXME: This enum needs to be public because it's exposed via a bunch of traits, but it's not // useful to users. #[doc(hidden)] +#[derive(Debug, Clone, Copy, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Peripheral { /// SPI2 peripheral. #[cfg(spi2)] From f75007810f6acdb45e692da0dd7627e4a66e0109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 4 Oct 2024 10:26:51 +0200 Subject: [PATCH 17/36] Clean up a bit --- esp-hal/src/dma/gdma.rs | 15 ++++---- esp-hal/src/dma/mod.rs | 7 ++-- esp-hal/src/dma/pdma.rs | 76 +++++++++++---------------------------- esp-hal/src/i2s.rs | 58 +++++++++--------------------- esp-hal/src/spi/master.rs | 69 ++++------------------------------- esp-hal/src/spi/mod.rs | 18 +++++++++- esp-hal/src/spi/slave.rs | 58 ++++-------------------------- 7 files changed, 80 insertions(+), 221 deletions(-) diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index 43c7c84d7e4..e54d1a58808 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -416,11 +416,6 @@ impl InterruptAccess for ChannelRxImpl { #[non_exhaustive] pub struct ChannelCreator {} -#[non_exhaustive] -#[doc(hidden)] -pub struct SuitablePeripheral; -impl PeripheralMarker for SuitablePeripheral {} - impl DmaChannel for AnyDmaChannel { type Rx = ChannelRxImpl; type Tx = ChannelTxImpl; @@ -435,15 +430,19 @@ impl DmaChannel for AnyDmaChannel { impl Channel<'_, CH, M> { /// Asserts that the channel is compatible with the given peripheral. - pub fn runtime_ensure_compatible(&self, _peripheral: P) { - // GDMA channels are compatible with any peripheral + pub fn runtime_ensure_compatible( + &self, + _peripheral: &PeripheralRef<'_, P>, + ) { + // No runtime checks; GDMA channels are compatible with any peripheral } } +// Every DMA channel is compatible with every (DMA eligible) peripheral. impl DmaCompatible for (CH, P) where CH: DmaChannel, - P: PeripheralMarker, + P: PeripheralMarker + DmaEligible, { } diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 9b4dd265c0e..3a4caec8d17 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -890,7 +890,6 @@ impl From for Owner { } } -/// Marks channels as useable for SPI #[doc(hidden)] pub trait DmaEligible { /// The DMA peripheral @@ -903,10 +902,12 @@ pub trait DmaEligible { /// Marker trait #[doc(hidden)] pub trait PeripheralMarker { - #[cfg(pdma)] fn peripheral(&self) -> crate::system::Peripheral; } +/// Trait implemented for (DmaChannel, Peripheral) pairs that are compatible. +/// This is used to statically verify that the DMA channel is compatible with +/// the peripheral. #[doc(hidden)] pub trait DmaCompatible {} @@ -1993,7 +1994,7 @@ pub trait RegisterAccess: crate::private::Sealed { fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize); #[cfg(pdma)] - fn is_compatible_with(&self, peripheral: P) -> bool; + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool; } #[doc(hidden)] diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 6177dc4bf9b..2503815f637 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -27,7 +27,7 @@ pub trait SpiPdmaChannel: crate::private::Sealed { fn register_block(&self) -> &SpiRegisterBlock; fn tx_waker(&self) -> &'static AtomicWaker; fn rx_waker(&self) -> &'static AtomicWaker; - fn is_compatible_with(&self, peripheral: P) -> bool; + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool; } #[doc(hidden)] @@ -35,7 +35,7 @@ pub trait I2sPdmaChannel: crate::private::Sealed { fn register_block(&self) -> &I2sRegisterBlock; fn tx_waker(&self) -> &'static AtomicWaker; fn rx_waker(&self) -> &'static AtomicWaker; - fn is_compatible_with(&self, peripheral: P) -> bool; + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool; } #[doc(hidden)] @@ -108,7 +108,7 @@ impl RegisterAccess for SpiDmaTxChannelImpl { .modify(|_, w| w.outlink_restart().set_bit()); } - fn is_compatible_with(&self, peripheral: P) -> bool { + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool { self.0.is_compatible_with(peripheral) } } @@ -239,7 +239,7 @@ impl RegisterAccess for SpiDmaRxChannelImpl { .modify(|_, w| w.inlink_restart().set_bit()); } - fn is_compatible_with(&self, peripheral: P) -> bool { + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool { self.0.is_compatible_with(peripheral) } } @@ -368,7 +368,7 @@ macro_rules! ImplSpiChannel { } } impl PeripheralDmaChannel for [] { - type P = []; + type P = crate::peripherals::[]; } impl DmaChannelExt for [] { @@ -401,8 +401,8 @@ macro_rules! ImplSpiChannel { &WAKER } - fn is_compatible_with(&self, peripheral: P) -> bool { - p.peripheral() == crate::system::Peripheral::[] + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool { + peripheral.peripheral() == crate::system::Peripheral::[] } } @@ -550,7 +550,7 @@ impl RegisterAccess for I2sDmaTxChannelImpl { .modify(|_, w| w.outlink_restart().set_bit()); } - fn is_compatible_with(&self, peripheral: P) -> bool { + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool { self.0.is_compatible_with(peripheral) } } @@ -690,7 +690,7 @@ impl RegisterAccess for I2sDmaRxChannelImpl { .modify(|_, w| w.inlink_restart().set_bit()); } - fn is_compatible_with(&self, peripheral: P) -> bool { + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool { self.0.is_compatible_with(peripheral) } } @@ -815,7 +815,7 @@ macro_rules! ImplI2sChannel { } } impl PeripheralDmaChannel for [] { - type P = []; + type P = crate::peripherals::[]; } impl DmaChannelExt for [] { @@ -847,8 +847,8 @@ macro_rules! ImplI2sChannel { static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new(); &WAKER } - fn is_compatible_with(&self, peripheral: P) -> bool { - p.peripheral() == crate::system::Peripheral::[] + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool { + peripheral.peripheral() == crate::system::Peripheral::[] } } @@ -908,48 +908,10 @@ macro_rules! ImplI2sChannel { }; } -#[doc(hidden)] -#[non_exhaustive] -pub struct Spi2DmaSuitablePeripheral; -impl PeripheralMarker for Spi2DmaSuitablePeripheral { - fn peripheral(&self) -> crate::system::Peripheral { - crate::system::Peripheral::Spi2 - } -} - -#[doc(hidden)] -#[non_exhaustive] -pub struct Spi3DmaSuitablePeripheral; -impl PeripheralMarker for Spi3DmaSuitablePeripheral { - fn peripheral(&self) -> crate::system::Peripheral { - crate::system::Peripheral::Spi3 - } -} - ImplSpiChannel!(2); #[cfg(spi3)] ImplSpiChannel!(3); -#[doc(hidden)] -#[non_exhaustive] -pub struct I2s0DmaSuitablePeripheral; -impl PeripheralMarker for I2s0DmaSuitablePeripheral { - fn peripheral(&self) -> crate::system::Peripheral { - crate::system::Peripheral::I2s0 - } -} - -#[doc(hidden)] -#[non_exhaustive] -#[cfg(i2s1)] -pub struct I2s1DmaSuitablePeripheral; -#[cfg(i2s1)] -impl PeripheralMarker for I2s1DmaSuitablePeripheral { - fn peripheral(&self) -> crate::system::Peripheral { - crate::system::Peripheral::I2s1 - } -} - ImplI2sChannel!(0); #[cfg(i2s1)] ImplI2sChannel!(1); @@ -1048,7 +1010,7 @@ impl RegisterAccess for AnyPdmaRxChannelImpl { fn start(&self); fn stop(&self); fn restart(&self); - fn is_compatible_with(&self, peripheral: P) -> bool; + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool; } } } @@ -1092,7 +1054,7 @@ impl RegisterAccess for AnyPdmaTxChannelImpl { fn start(&self); fn stop(&self); fn restart(&self); - fn is_compatible_with(&self, peripheral: P) -> bool; + fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool; } } } @@ -1115,15 +1077,19 @@ where C: DmaChannel, { /// Asserts that the channel is compatible with the given peripheral. - pub fn runtime_ensure_compatible(&self, peripheral: P) { + pub fn runtime_ensure_compatible(&self, peripheral: &PeripheralRef<'_, impl PeripheralMarker>) { assert!( - self.tx.tx_impl.is_compatible_with(p), + self.tx.tx_impl.is_compatible_with(&**peripheral), "This DMA channel is not compatible with {:?}", - p.peripheral() + peripheral.peripheral() ); } } +// Every DMA channel is compatible with a single peripheral. +// TODO: While on ESP32 we have two DMA channels for three SPI peripherals, we +// currently only support 2 out of the 3 SPI peripherals. Complicating this +// further to cover SPI1 is not useful right now. #[cfg(pdma)] impl DmaCompatible for (CH, P) where diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index a9a7bf5da42..1f3a5d5d3d9 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -343,7 +343,7 @@ where tx_descriptors: &'static mut [DmaDescriptor], ) -> Self { crate::into_ref!(i2s); - channel.runtime_ensure_compatible(i2s.dma_peripheral_marker()); + channel.runtime_ensure_compatible(&i2s); // on ESP32-C3 / ESP32-S3 and later RX and TX are independent and // could be configured totally independently but for now handle all // the targets the same and force same configuration for both, TX and RX @@ -443,7 +443,7 @@ where ) -> Self where CH: crate::dma::DmaChannel, - (CH, I::Peripheral): crate::dma::DmaCompatible, + (CH, I): crate::dma::DmaCompatible, DmaMode: Mode, { Self::new_internal( @@ -837,6 +837,7 @@ mod private { ChannelRx, ChannelTx, DmaDescriptor, + DmaEligible, DmaPeripheral, PeripheralMarker, }, @@ -977,16 +978,12 @@ mod private { fn din_signal() -> InputSignal; } - pub trait RegBlock { + pub trait RegBlock: PeripheralMarker + DmaEligible { fn register_block() -> &'static RegisterBlock; } #[cfg(any(esp32, esp32s2))] pub trait RegisterAccessPrivate: Signals + RegBlock { - type Peripheral: PeripheralMarker; - - fn dma_peripheral_marker(&self) -> Self::Peripheral; - fn set_interrupt_handler(handler: InterruptHandler); fn enable_listen(interrupts: EnumSet, enable: bool) { @@ -1241,10 +1238,6 @@ mod private { #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] pub trait RegisterAccessPrivate: Signals + RegBlock { - type Peripheral: PeripheralMarker; - - fn dma_peripheral_marker(&self) -> Self::Peripheral; - fn set_interrupt_handler(handler: InterruptHandler); fn enable_listen(interrupts: EnumSet, enable: bool) { @@ -1909,6 +1902,19 @@ mod private { } } + impl PeripheralMarker for I2S0 { + fn peripheral(&self) -> crate::system::Peripheral { + crate::system::Peripheral::I2s0 + } + } + + #[cfg(i2s1)] + impl PeripheralMarker for I2S1 { + fn peripheral(&self) -> crate::system::Peripheral { + crate::system::Peripheral::I2s1 + } + } + impl RegBlock for I2S0 { fn register_block() -> &'static RegisterBlock { unsafe { &*I2S0::PTR.cast::() } @@ -1923,21 +1929,6 @@ mod private { } impl RegisterAccessPrivate for I2S0 { - #[cfg(pdma)] - type Peripheral = crate::dma::I2s0DmaSuitablePeripheral; - #[cfg(gdma)] - type Peripheral = crate::dma::SuitablePeripheral; - - fn dma_peripheral_marker(&self) -> Self::Peripheral { - cfg_if::cfg_if! { - if #[cfg(pdma)] { - crate::dma::I2s0DmaSuitablePeripheral - } else { - crate::dma::SuitablePeripheral - } - } - } - fn set_interrupt_handler(handler: InterruptHandler) { unsafe { crate::peripherals::I2S0::steal() }.bind_i2s0_interrupt(handler.handler()); crate::interrupt::enable(crate::peripherals::Interrupt::I2S0, handler.priority()) @@ -1947,21 +1938,6 @@ mod private { #[cfg(i2s1)] impl RegisterAccessPrivate for I2S1 { - #[cfg(pdma)] - type Peripheral = crate::dma::I2s1DmaSuitablePeripheral; - #[cfg(gdma)] - type Peripheral = crate::dma::SuitablePeripheral; - - fn dma_peripheral_marker(&self) -> Self::Peripheral { - cfg_if::cfg_if! { - if #[cfg(pdma)] { - crate::dma::I2s1DmaSuitablePeripheral - } else { - crate::dma::SuitablePeripheral - } - } - } - fn set_interrupt_handler(handler: InterruptHandler) { unsafe { crate::peripherals::I2S1::steal() }.bind_i2s1_interrupt(handler.handler()); crate::interrupt::enable(crate::peripherals::Interrupt::I2S1, handler.priority()) diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index b869f646e46..987f963a716 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -81,7 +81,7 @@ use super::{ }; use crate::{ clock::Clocks, - dma::{DmaPeripheral, DmaRxBuffer, DmaTxBuffer, PeripheralMarker, Rx, Tx}, + dma::{DmaEligible, DmaRxBuffer, DmaTxBuffer, PeripheralMarker, Rx, Tx}, gpio::{InputSignal, NoPin, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, @@ -501,7 +501,7 @@ where ) -> SpiDma<'d, T, M, DmaMode> where CH: crate::dma::DmaChannel, - (CH, T::Peripheral): crate::dma::DmaCompatible, + (CH, T): crate::dma::DmaCompatible, DmaMode: crate::Mode, { SpiDma::new(self.spi, channel) @@ -1006,7 +1006,7 @@ mod dma { where CH: DmaChannel, { - channel.runtime_ensure_compatible(spi.dma_peripheral_marker()); + channel.runtime_ensure_compatible(&spi); #[cfg(all(esp32, spi_address_workaround))] let address_buffer = { use crate::dma::DmaDescriptor; @@ -2213,11 +2213,7 @@ mod ehal1 { } #[doc(hidden)] -pub trait InstanceDma: Instance { - type Peripheral: PeripheralMarker; - - fn dma_peripheral_marker(&self) -> Self::Peripheral; - +pub trait InstanceDma: Instance + DmaEligible { #[allow(clippy::too_many_arguments)] unsafe fn start_transfer_dma( &mut self, @@ -2339,15 +2335,6 @@ pub trait InstanceDma: Instance { Ok(()) } - fn dma_peripheral(&self) -> DmaPeripheral { - match self.spi_num() { - 2 => DmaPeripheral::Spi2, - #[cfg(spi3)] - 3 => DmaPeripheral::Spi3, - _ => panic!("Illegal SPI instance"), - } - } - fn enable_dma(&self) { #[cfg(gdma)] { @@ -2425,40 +2412,10 @@ pub trait InstanceDma: Instance { } } -impl InstanceDma for crate::peripherals::SPI2 { - #[cfg(pdma)] - type Peripheral = crate::dma::Spi2DmaSuitablePeripheral; - #[cfg(gdma)] - type Peripheral = crate::dma::SuitablePeripheral; - - fn dma_peripheral_marker(&self) -> Self::Peripheral { - cfg_if::cfg_if! { - if #[cfg(pdma)] { - crate::dma::Spi2DmaSuitablePeripheral - } else { - crate::dma::SuitablePeripheral - } - } - } -} +impl InstanceDma for crate::peripherals::SPI2 {} #[cfg(spi3)] -impl InstanceDma for crate::peripherals::SPI3 { - #[cfg(pdma)] - type Peripheral = crate::dma::Spi3DmaSuitablePeripheral; - #[cfg(gdma)] - type Peripheral = crate::dma::SuitablePeripheral; - - fn dma_peripheral_marker(&self) -> Self::Peripheral { - cfg_if::cfg_if! { - if #[cfg(pdma)] { - crate::dma::Spi3DmaSuitablePeripheral - } else { - crate::dma::SuitablePeripheral - } - } - } -} +impl InstanceDma for crate::peripherals::SPI3 {} #[doc(hidden)] pub trait ExtendedInstance: Instance { @@ -2476,9 +2433,7 @@ pub trait ExtendedInstance: Instance { } #[doc(hidden)] -pub trait Instance: private::Sealed { - fn peripheral(&self) -> crate::system::Peripheral; - +pub trait Instance: private::Sealed + PeripheralMarker { fn register_block(&self) -> &RegisterBlock; fn sclk_signal(&self) -> OutputSignal; @@ -3161,11 +3116,6 @@ impl Instance for crate::peripherals::SPI2 { 2 } - #[inline(always)] - fn peripheral(&self) -> crate::system::Peripheral { - crate::system::Peripheral::Spi2 - } - #[inline(always)] fn set_interrupt_handler(&mut self, handler: InterruptHandler) { self.bind_spi2_interrupt(handler.handler()); @@ -3300,11 +3250,6 @@ impl Instance for crate::peripherals::SPI3 { 3 } - #[inline(always)] - fn peripheral(&self) -> crate::system::Peripheral { - crate::system::Peripheral::Spi3 - } - #[inline(always)] fn set_interrupt_handler(&mut self, handler: InterruptHandler) { self.bind_spi3_interrupt(handler.handler()); diff --git a/esp-hal/src/spi/mod.rs b/esp-hal/src/spi/mod.rs index 32786fb24c0..250ed0e2b4b 100644 --- a/esp-hal/src/spi/mod.rs +++ b/esp-hal/src/spi/mod.rs @@ -9,7 +9,7 @@ //! more information on these modes, please refer to the documentation in their //! respective modules. -use crate::dma::DmaError; +use crate::dma::{DmaError, PeripheralMarker}; pub mod master; pub mod slave; @@ -100,3 +100,19 @@ impl crate::private::Sealed for FullDuplexMode {} pub struct HalfDuplexMode {} impl DuplexMode for HalfDuplexMode {} impl crate::private::Sealed for HalfDuplexMode {} + +#[cfg(spi2)] +impl PeripheralMarker for crate::peripherals::SPI2 { + #[inline(always)] + fn peripheral(&self) -> crate::system::Peripheral { + crate::system::Peripheral::Spi2 + } +} + +#[cfg(spi3)] +impl PeripheralMarker for crate::peripherals::SPI3 { + #[inline(always)] + fn peripheral(&self) -> crate::system::Peripheral { + crate::system::Peripheral::Spi3 + } +} diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index 50fd31ebd60..cc1700560ec 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -73,7 +73,7 @@ use core::marker::PhantomData; use super::{Error, FullDuplexMode, SpiMode}; use crate::{ - dma::{DescriptorChain, DmaPeripheral, PeripheralMarker, Rx, Tx}, + dma::{DescriptorChain, DmaEligible, PeripheralMarker, Rx, Tx}, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, peripheral::{Peripheral, PeripheralRef}, peripherals::spi2::RegisterBlock, @@ -186,7 +186,7 @@ pub mod dma { ) -> SpiDma<'d, T, DmaMode> where CH: DmaChannel, - (CH, T::Peripheral): crate::dma::DmaCompatible, + (CH, T): crate::dma::DmaCompatible, DmaMode: Mode, { self.spi.set_data_mode(self.data_mode, true); @@ -279,7 +279,7 @@ pub mod dma { where CH: DmaChannel, { - channel.runtime_ensure_compatible(spi.dma_peripheral_marker()); + channel.runtime_ensure_compatible(&spi); Self { spi, channel: channel.degrade(), @@ -399,13 +399,7 @@ pub mod dma { } #[doc(hidden)] -pub trait InstanceDma: Instance { - type Peripheral: PeripheralMarker; - - fn dma_peripheral_marker(&self) -> Self::Peripheral; - - fn dma_peripheral(&self) -> DmaPeripheral; - +pub trait InstanceDma: Instance + DmaEligible { #[allow(clippy::too_many_arguments)] unsafe fn start_transfer_dma( &mut self, @@ -547,50 +541,12 @@ fn reset_dma_before_usr_cmd(reg_block: &RegisterBlock) { let _ = reg_block; } -impl InstanceDma for crate::peripherals::SPI2 { - #[cfg(pdma)] - type Peripheral = crate::dma::Spi2DmaSuitablePeripheral; - #[cfg(gdma)] - type Peripheral = crate::dma::SuitablePeripheral; - - fn dma_peripheral_marker(&self) -> Self::Peripheral { - cfg_if::cfg_if! { - if #[cfg(pdma)] { - crate::dma::Spi2DmaSuitablePeripheral - } else { - crate::dma::SuitablePeripheral - } - } - } - - fn dma_peripheral(&self) -> DmaPeripheral { - DmaPeripheral::Spi2 - } -} +impl InstanceDma for crate::peripherals::SPI2 {} #[cfg(spi3)] -impl InstanceDma for crate::peripherals::SPI3 { - #[cfg(pdma)] - type Peripheral = crate::dma::Spi3DmaSuitablePeripheral; - #[cfg(gdma)] - type Peripheral = crate::dma::SuitablePeripheral; - - fn dma_peripheral_marker(&self) -> Self::Peripheral { - cfg_if::cfg_if! { - if #[cfg(pdma)] { - crate::dma::Spi3DmaSuitablePeripheral - } else { - crate::dma::SuitablePeripheral - } - } - } - - fn dma_peripheral(&self) -> DmaPeripheral { - DmaPeripheral::Spi3 - } -} +impl InstanceDma for crate::peripherals::SPI3 {} #[doc(hidden)] -pub trait Instance: private::Sealed { +pub trait Instance: private::Sealed + PeripheralMarker { fn register_block(&self) -> &RegisterBlock; fn peripheral(&self) -> crate::system::Peripheral; From 851c8fcaaf2b47a47873dbe40ee8654a1e63e851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 4 Oct 2024 11:21:01 +0200 Subject: [PATCH 18/36] Document changes --- esp-hal/CHANGELOG.md | 1 + esp-hal/MIGRATING-0.20.md | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index d2d398c8854..78adae34bc2 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -65,6 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Change `DmaTxBuf` to support PSRAM on `esp32s3` (#2161) - I2c `transaction` is now also available as a inherent function, lift size limit on `write`,`read` and `write_read` (#2262) - SPI transactions are now cancelled if the transfer object (or async Future) is dropped. (#2216) +- The DMA channel types have been removed from peripherals (#2261) ### Fixed diff --git a/esp-hal/MIGRATING-0.20.md b/esp-hal/MIGRATING-0.20.md index 3dcbad9da06..a2cfaa1593a 100644 --- a/esp-hal/MIGRATING-0.20.md +++ b/esp-hal/MIGRATING-0.20.md @@ -121,12 +121,14 @@ When using the asymmetric variant of the macro to create DMA buffers and descrip + let (_, _, tx_buffer, tx_descriptors) = dma_buffers!(0, 32000); ``` -## Removed UART constructors +## Removed constructors + +### UART The `Uart::new_with_default_pins` and `Uart::new_async_with_default_pins` constructors have been removed. Use `new` or `new_async` instead. -## Removed I2S1-specific constructor +### I2S1 The `I2s::new_i2s1` constructor has been removed. Use `I2s::new` instead. @@ -323,3 +325,21 @@ Diff of the `psram_quad.rs` example ## eFuse Calling `Efuse::read_field_le::()` no longer compiles. Use `Efuse::read_bit()` instead. + +## DMA + +The DMA channel types have been removed from peripherals. + +A non-exhausitve list demonstrating this change: + +```diff +-I2sTx<'static, I2S0, DmaChannel0, Async> ++I2sTx<'static, I2S0, Async> + +-SpiDma<'static, esp_hal::peripherals::SPI2, DmaChannel0, HalfDuplexMode, Blocking> ++SpiDma<'static, esp_hal::peripherals::SPI2, HalfDuplexMode, Blocking> +``` + +You can now call `dma_channel.degrade()` to obtain a type-erased version of `Channel`. Note that +on ESP32 and ESP32-S2, passing this channel to an incompatible peripheral (for example an +I2S-specific DMA channel to SPI) will result in a panic. From a01b47c724853d937b0ff10cde03e394cbfdd951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 4 Oct 2024 11:33:43 +0200 Subject: [PATCH 19/36] Swap Channel type params, erase dma channel --- esp-hal/CHANGELOG.md | 1 + esp-hal/MIGRATING-0.20.md | 13 ++++++++++-- esp-hal/src/aes/mod.rs | 9 ++++----- esp-hal/src/dma/gdma.rs | 16 +++++++-------- esp-hal/src/dma/mod.rs | 16 +++++++-------- esp-hal/src/dma/pdma.rs | 16 +++++++-------- esp-hal/src/i2s.rs | 37 +++++++++++------------------------ esp-hal/src/parl_io.rs | 25 ++++++++++++----------- esp-hal/src/spi/master.rs | 7 +++---- esp-hal/src/spi/slave.rs | 11 +++++------ hil-test/tests/dma_mem2mem.rs | 4 ++-- hil-test/tests/qspi.rs | 4 ++-- 12 files changed, 75 insertions(+), 84 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 78adae34bc2..b9f86104374 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -66,6 +66,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - I2c `transaction` is now also available as a inherent function, lift size limit on `write`,`read` and `write_read` (#2262) - SPI transactions are now cancelled if the transfer object (or async Future) is dropped. (#2216) - The DMA channel types have been removed from peripherals (#2261) +- The channel type parameter of `dma::Channel` have been moved to the last position and can be erased using `degrade()` (#2261) ### Fixed diff --git a/esp-hal/MIGRATING-0.20.md b/esp-hal/MIGRATING-0.20.md index a2cfaa1593a..66f383e31ae 100644 --- a/esp-hal/MIGRATING-0.20.md +++ b/esp-hal/MIGRATING-0.20.md @@ -340,6 +340,15 @@ A non-exhausitve list demonstrating this change: +SpiDma<'static, esp_hal::peripherals::SPI2, HalfDuplexMode, Blocking> ``` -You can now call `dma_channel.degrade()` to obtain a type-erased version of `Channel`. Note that -on ESP32 and ESP32-S2, passing this channel to an incompatible peripheral (for example an +The type parameters of `Channel` have been reordered. The channel type +has been moved to the last position. For example: + +```diff +-Channel<'d, DmaChannel0, Async> ++Channel<'d, Async, DmaChannel0> +``` + +You can now call `dma_channel.degrade()` to obtain a type-erased version of `Channel`. You +don't have to spell out `Channel<'d, Mode, AnyDmaChannel>`, you can use `Channel<'d, Mode>` instead. +Note that on ESP32 and ESP32-S2, passing this channel to an incompatible peripheral (for example an I2S-specific DMA channel to SPI) will result in a panic. diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index 840bb05da9e..4b684500304 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -235,7 +235,6 @@ pub mod dma { aes::{Key, Mode}, dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, - AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -274,7 +273,7 @@ pub mod dma { /// The underlying [`Aes`](super::Aes) driver pub aes: super::Aes<'d>, - channel: Channel<'d, AnyDmaChannel, crate::Blocking>, + channel: Channel<'d, crate::Blocking>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, } @@ -283,7 +282,7 @@ pub mod dma { /// Enable DMA for the current instance of the AES driver pub fn with_dma( self, - channel: Channel<'d, C, crate::Blocking>, + channel: Channel<'d, crate::Blocking, C>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> AesDma<'d> @@ -323,7 +322,7 @@ pub mod dma { } impl<'d> DmaSupportTx for AesDma<'d> { - type TX = ChannelTx<'d, AnyDmaChannel>; + type TX = ChannelTx<'d>; fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx @@ -335,7 +334,7 @@ pub mod dma { } impl<'d> DmaSupportRx for AesDma<'d> { - type RX = ChannelRx<'d, AnyDmaChannel>; + type RX = ChannelRx<'d>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index e54d1a58808..a173cee2bb4 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -428,7 +428,7 @@ impl DmaChannel for AnyDmaChannel { } } -impl Channel<'_, CH, M> { +impl Channel<'_, M, CH> { /// Asserts that the channel is compatible with the given peripheral. pub fn runtime_ensure_compatible( &self, @@ -490,7 +490,7 @@ macro_rules! impl_channel { self, burst_mode: bool, priority: DmaPriority, - ) -> crate::dma::Channel<'a, [], M> { + ) -> crate::dma::Channel<'a, M, []> { let tx_impl = ChannelTxImpl(SpecificGdmaChannel::<$num> {}); tx_impl.set_burst_mode(burst_mode); tx_impl.set_priority(priority); @@ -517,7 +517,7 @@ macro_rules! impl_channel { self, burst_mode: bool, priority: DmaPriority, - ) -> crate::dma::Channel<'a, [], crate::Blocking> { + ) -> crate::dma::Channel<'a, crate::Blocking, []> { self.do_configure(burst_mode, priority) } @@ -529,7 +529,7 @@ macro_rules! impl_channel { self, burst_mode: bool, priority: DmaPriority, - ) -> crate::dma::Channel<'a, [], $crate::Async> { + ) -> crate::dma::Channel<'a, $crate::Async, []> { let this = self.do_configure(burst_mode, priority); []::set_isr($async_handler); @@ -648,7 +648,7 @@ mod m2m { where M: Mode, { - channel: Channel<'d, AnyDmaChannel, M>, + channel: Channel<'d, M>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, peripheral: DmaPeripheral, @@ -660,7 +660,7 @@ mod m2m { { /// Create a new Mem2Mem instance. pub fn new( - channel: Channel<'d, CH, M>, + channel: Channel<'d, M, CH>, peripheral: impl DmaEligible, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], @@ -681,7 +681,7 @@ mod m2m { /// Create a new Mem2Mem instance with specific chunk size. pub fn new_with_chunk_size( - channel: Channel<'d, CH, M>, + channel: Channel<'d, M, CH>, peripheral: impl DmaEligible, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], @@ -708,7 +708,7 @@ mod m2m { /// You must ensure that your not using DMA for the same peripheral and /// that your the only one using the DmaPeripheral. pub unsafe fn new_unsafe( - channel: Channel<'d, CH, M>, + channel: Channel<'d, M, CH>, peripheral: DmaPeripheral, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 3a4caec8d17..f5cabc95d6a 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1594,7 +1594,7 @@ pub trait Rx: crate::private::Sealed { // DMA receive channel #[non_exhaustive] #[doc(hidden)] -pub struct ChannelRx<'a, CH> +pub struct ChannelRx<'a, CH = AnyDmaChannel> where CH: DmaChannel, { @@ -1616,7 +1616,7 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelRx<'a, AnyDmaChannel> { + pub fn degrade(self) -> ChannelRx<'a> { ChannelRx { burst_mode: self.burst_mode, rx_impl: CH::degrade_rx(self.rx_impl), @@ -1807,7 +1807,7 @@ pub trait Tx: crate::private::Sealed { /// DMA transmit channel #[doc(hidden)] -pub struct ChannelTx<'a, CH> +pub struct ChannelTx<'a, CH = AnyDmaChannel> where CH: DmaChannel, { @@ -1830,7 +1830,7 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelTx<'a, AnyDmaChannel> { + pub fn degrade(self) -> ChannelTx<'a> { ChannelTx { burst_mode: self.burst_mode, tx_impl: CH::degrade_tx(self.tx_impl), @@ -2030,7 +2030,7 @@ pub trait InterruptAccess: crate::private::Sealed { } /// DMA Channel -pub struct Channel<'d, CH, MODE> +pub struct Channel<'d, MODE, CH = AnyDmaChannel> where CH: DmaChannel, MODE: Mode, @@ -2042,7 +2042,7 @@ where phantom: PhantomData, } -impl<'d, C> Channel<'d, C, crate::Blocking> +impl<'d, C> Channel<'d, crate::Blocking, C> where C: DmaChannel, { @@ -2100,13 +2100,13 @@ where } } -impl<'d, C, M: Mode> Channel<'d, C, M> +impl<'d, C, M: Mode> Channel<'d, M, C> where C: DmaChannel, { /// Return a type-erased (degraded) version of this channel (both rx and /// tx). - pub fn degrade(self) -> Channel<'d, AnyDmaChannel, M> { + pub fn degrade(self) -> Channel<'d, M> { Channel { rx: self.rx.degrade(), tx: self.tx.degrade(), diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 2503815f637..0ef68553fcf 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -417,7 +417,7 @@ macro_rules! ImplSpiChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, [], M> { + ) -> Channel<'a, M, []> { #[cfg(esp32)] { // (only) on ESP32 we need to configure DPORT for the SPI DMA channels @@ -450,7 +450,7 @@ macro_rules! ImplSpiChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, [], $crate::Blocking> { + ) -> Channel<'a, $crate::Blocking, []> { Self::do_configure(self, burst_mode, priority) } @@ -462,7 +462,7 @@ macro_rules! ImplSpiChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, [], $crate::Async> { + ) -> Channel<'a, $crate::Async, []> { let this = Self::do_configure(self, burst_mode, priority); []::set_isr(super::asynch::interrupt::[< interrupt_handler_spi $num _dma >]); @@ -860,7 +860,7 @@ macro_rules! ImplI2sChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, [], M> { + ) -> Channel<'a, M, []> { let tx_impl = I2sDmaTxChannelImpl([] {}); tx_impl.set_burst_mode(burst_mode); tx_impl.set_priority(priority); @@ -884,7 +884,7 @@ macro_rules! ImplI2sChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, [], $crate::Blocking> { + ) -> Channel<'a, $crate::Blocking, []> { Self::do_configure(self, burst_mode, priority) } @@ -896,7 +896,7 @@ macro_rules! ImplI2sChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, [], $crate::Async> { + ) -> Channel<'a, $crate::Async, []> { let this = Self::do_configure(self, burst_mode, priority); []::set_isr(super::asynch::interrupt::[< interrupt_handler_i2s $num >]); @@ -1072,9 +1072,9 @@ impl TxRegisterAccess for AnyPdmaTxChannelImpl { } } -impl<'d, C, M: Mode> Channel<'d, C, M> +impl<'d, CH, M: Mode> Channel<'d, M, CH> where - C: DmaChannel, + CH: DmaChannel, { /// Asserts that the channel is compatible with the given peripheral. pub fn runtime_ensure_compatible(&self, peripheral: &PeripheralRef<'_, impl PeripheralMarker>) { diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index 1f3a5d5d3d9..ba77a614d69 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -87,7 +87,6 @@ use private::*; use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, - AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -338,7 +337,7 @@ where standard: Standard, data_format: DataFormat, sample_rate: impl Into, - channel: Channel<'d, CH, DmaMode>, + channel: Channel<'d, DmaMode, CH>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> Self { @@ -437,7 +436,7 @@ where standard: Standard, data_format: DataFormat, sample_rate: impl Into, - channel: Channel<'d, CH, DmaMode>, + channel: Channel<'d, DmaMode, CH>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> Self @@ -473,7 +472,7 @@ where T: RegisterAccess, { register_access: PhantomData, - tx_channel: ChannelTx<'d, AnyDmaChannel>, + tx_channel: ChannelTx<'d>, tx_chain: DescriptorChain, phantom: PhantomData, } @@ -507,7 +506,7 @@ where T: RegisterAccess, DmaMode: Mode, { - type TX = ChannelTx<'d, AnyDmaChannel>; + type TX = ChannelTx<'d>; fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel @@ -523,10 +522,7 @@ where T: RegisterAccess, DmaMode: Mode, { - fn new( - tx_channel: ChannelTx<'d, AnyDmaChannel>, - descriptors: &'static mut [DmaDescriptor], - ) -> Self { + fn new(tx_channel: ChannelTx<'d>, descriptors: &'static mut [DmaDescriptor]) -> Self { Self { register_access: PhantomData, tx_channel, @@ -640,7 +636,7 @@ where DmaMode: Mode, { register_access: PhantomData, - rx_channel: ChannelRx<'d, AnyDmaChannel>, + rx_channel: ChannelRx<'d>, rx_chain: DescriptorChain, phantom: PhantomData, } @@ -674,7 +670,7 @@ where T: RegisterAccess, DmaMode: Mode, { - type RX = ChannelRx<'d, AnyDmaChannel>; + type RX = ChannelRx<'d>; fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel @@ -690,10 +686,7 @@ where T: RegisterAccess, DmaMode: Mode, { - fn new( - rx_channel: ChannelRx<'d, AnyDmaChannel>, - descriptors: &'static mut [DmaDescriptor], - ) -> Self { + fn new(rx_channel: ChannelRx<'d>, descriptors: &'static mut [DmaDescriptor]) -> Self { Self { register_access: PhantomData, rx_channel, @@ -832,15 +825,7 @@ mod private { #[cfg(any(esp32, esp32s3))] use crate::peripherals::{i2s1::RegisterBlock, I2S1}; use crate::{ - dma::{ - AnyDmaChannel, - ChannelRx, - ChannelTx, - DmaDescriptor, - DmaEligible, - DmaPeripheral, - PeripheralMarker, - }, + dma::{ChannelRx, ChannelTx, DmaDescriptor, DmaEligible, DmaPeripheral, PeripheralMarker}, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, into_ref, @@ -856,7 +841,7 @@ mod private { DmaMode: Mode, { pub register_access: PhantomData, - pub tx_channel: ChannelTx<'d, AnyDmaChannel>, + pub tx_channel: ChannelTx<'d>, pub descriptors: &'static mut [DmaDescriptor], pub(crate) phantom: PhantomData, } @@ -910,7 +895,7 @@ mod private { DmaMode: Mode, { pub register_access: PhantomData, - pub rx_channel: ChannelRx<'d, AnyDmaChannel>, + pub rx_channel: ChannelRx<'d>, pub descriptors: &'static mut [DmaDescriptor], pub(crate) phantom: PhantomData, } diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index fa88b88fcab..73854d4d981 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -33,7 +33,6 @@ use private::*; use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, - AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -904,7 +903,7 @@ pub struct ParlIoTx<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d, AnyDmaChannel>, + tx_channel: ChannelTx<'d>, tx_chain: DescriptorChain, phantom: PhantomData, } @@ -983,7 +982,7 @@ pub struct ParlIoRx<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d, AnyDmaChannel>, + rx_channel: ChannelRx<'d>, rx_chain: DescriptorChain, phantom: PhantomData, } @@ -1094,7 +1093,7 @@ where /// Create a new instance of [ParlIoFullDuplex] pub fn new( _parl_io: impl Peripheral

+ 'd, - dma_channel: Channel<'d, CH, DM>, + dma_channel: Channel<'d, DM, CH>, tx_descriptors: &'static mut [DmaDescriptor], rx_descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, @@ -1175,7 +1174,7 @@ where // TODO: only take a TX DMA channel? pub fn new( _parl_io: impl Peripheral

+ 'd, - dma_channel: Channel<'d, CH, DM>, + dma_channel: Channel<'d, DM, CH>, descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, ) -> Result @@ -1250,7 +1249,7 @@ where // TODO: only take a RX DMA channel? pub fn new( _parl_io: impl Peripheral

+ 'd, - dma_channel: Channel<'d, CH, DM>, + dma_channel: Channel<'d, DM, CH>, descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, ) -> Result @@ -1418,7 +1417,7 @@ impl<'d, DM> DmaSupportTx for ParlIoTx<'d, DM> where DM: Mode, { - type TX = ChannelTx<'d, AnyDmaChannel>; + type TX = ChannelTx<'d>; fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel @@ -1460,7 +1459,7 @@ where } fn start_receive_bytes_dma( - rx_channel: &mut ChannelRx<'d, AnyDmaChannel>, + rx_channel: &mut ChannelRx<'d>, rx_chain: &mut DescriptorChain, ptr: *mut u8, len: usize, @@ -1514,7 +1513,7 @@ impl<'d, DM> DmaSupportRx for ParlIoRx<'d, DM> where DM: Mode, { - type RX = ChannelRx<'d, AnyDmaChannel>; + type RX = ChannelRx<'d>; fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel @@ -1530,7 +1529,7 @@ pub struct TxCreator<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d, AnyDmaChannel>, + tx_channel: ChannelTx<'d>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1540,7 +1539,7 @@ pub struct RxCreator<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d, AnyDmaChannel>, + rx_channel: ChannelRx<'d>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1550,7 +1549,7 @@ pub struct TxCreatorFullDuplex<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d, AnyDmaChannel>, + tx_channel: ChannelTx<'d>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1560,7 +1559,7 @@ pub struct RxCreatorFullDuplex<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d, AnyDmaChannel>, + rx_channel: ChannelRx<'d>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 987f963a716..0aaa2ad8c41 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -497,7 +497,7 @@ where /// operations. pub fn with_dma( self, - channel: crate::dma::Channel<'d, CH, DmaMode>, + channel: crate::dma::Channel<'d, DmaMode, CH>, ) -> SpiDma<'d, T, M, DmaMode> where CH: crate::dma::DmaChannel, @@ -939,7 +939,6 @@ mod dma { use crate::{ dma::{ asynch::{DmaRxFuture, DmaTxFuture}, - AnyDmaChannel, Channel, DmaChannel, DmaRxBuf, @@ -966,7 +965,7 @@ mod dma { M: Mode, { pub(crate) spi: PeripheralRef<'d, T>, - pub(crate) channel: Channel<'d, AnyDmaChannel, M>, + pub(crate) channel: Channel<'d, M>, tx_transfer_in_progress: bool, rx_transfer_in_progress: bool, #[cfg(all(esp32, spi_address_workaround))] @@ -1002,7 +1001,7 @@ mod dma { D: DuplexMode, M: Mode, { - pub(super) fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, CH, M>) -> Self + pub(super) fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, M, CH>) -> Self where CH: DmaChannel, { diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index cc1700560ec..e6e8640ec89 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -153,7 +153,6 @@ pub mod dma { use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, - AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -180,7 +179,7 @@ pub mod dma { #[cfg_attr(esp32, doc = "\n\n**Note**: ESP32 only supports Mode 1 and 3.")] pub fn with_dma( mut self, - channel: Channel<'d, CH, DmaMode>, + channel: Channel<'d, DmaMode, CH>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, T, DmaMode> @@ -200,7 +199,7 @@ pub mod dma { DmaMode: Mode, { pub(crate) spi: PeripheralRef<'d, T>, - pub(crate) channel: Channel<'d, AnyDmaChannel, DmaMode>, + pub(crate) channel: Channel<'d, DmaMode>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, } @@ -238,7 +237,7 @@ pub mod dma { T: InstanceDma, DmaMode: Mode, { - type TX = ChannelTx<'d, AnyDmaChannel>; + type TX = ChannelTx<'d>; fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx @@ -254,7 +253,7 @@ pub mod dma { T: InstanceDma, DmaMode: Mode, { - type RX = ChannelRx<'d, AnyDmaChannel>; + type RX = ChannelRx<'d>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx @@ -272,7 +271,7 @@ pub mod dma { { fn new( spi: PeripheralRef<'d, T>, - channel: Channel<'d, CH, DmaMode>, + channel: Channel<'d, DmaMode, CH>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> Self diff --git a/hil-test/tests/dma_mem2mem.rs b/hil-test/tests/dma_mem2mem.rs index 6499f90d9aa..f27ce2eb0ec 100644 --- a/hil-test/tests/dma_mem2mem.rs +++ b/hil-test/tests/dma_mem2mem.rs @@ -6,7 +6,7 @@ #![no_main] use esp_hal::{ - dma::{AnyDmaChannel, Channel, Dma, DmaError, DmaPriority, Mem2Mem}, + dma::{Channel, Dma, DmaError, DmaPriority, Mem2Mem}, dma_buffers, dma_buffers_chunk_size, dma_descriptors, @@ -25,7 +25,7 @@ cfg_if::cfg_if! { } struct Context { - channel: Channel<'static, AnyDmaChannel, Blocking>, + channel: Channel<'static, Blocking>, dma_peripheral: DmaPeripheralType, } diff --git a/hil-test/tests/qspi.rs b/hil-test/tests/qspi.rs index f9358d70458..d4ff9c0cbdd 100644 --- a/hil-test/tests/qspi.rs +++ b/hil-test/tests/qspi.rs @@ -8,7 +8,7 @@ #[cfg(pcnt)] use esp_hal::pcnt::{channel::EdgeMode, unit::Unit, Pcnt}; use esp_hal::{ - dma::{AnyDmaChannel, Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, + dma::{Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::{AnyPin, Input, Io, Level, NoPin, Output, Pull}, prelude::*, @@ -36,7 +36,7 @@ struct Context { spi: esp_hal::peripherals::SPI2, #[cfg(pcnt)] pcnt: esp_hal::peripherals::PCNT, - dma_channel: Channel<'static, AnyDmaChannel, Blocking>, + dma_channel: Channel<'static, Blocking>, gpios: [AnyPin; 3], } From a019533079b646acf0ebcf36289ccd2e4973275a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 4 Oct 2024 15:29:25 +0200 Subject: [PATCH 20/36] Unsplit traits --- esp-hal/src/dma/pdma.rs | 60 ++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 0ef68553fcf..f8b4dab5d88 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -23,16 +23,10 @@ type SpiRegisterBlock = crate::peripherals::spi2::RegisterBlock; type I2sRegisterBlock = crate::peripherals::i2s0::RegisterBlock; #[doc(hidden)] -pub trait SpiPdmaChannel: crate::private::Sealed { - fn register_block(&self) -> &SpiRegisterBlock; - fn tx_waker(&self) -> &'static AtomicWaker; - fn rx_waker(&self) -> &'static AtomicWaker; - fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool; -} +pub trait PdmaChannel: crate::private::Sealed { + type RegisterBlock; -#[doc(hidden)] -pub trait I2sPdmaChannel: crate::private::Sealed { - fn register_block(&self) -> &I2sRegisterBlock; + fn register_block(&self) -> &Self::RegisterBlock; fn tx_waker(&self) -> &'static AtomicWaker; fn rx_waker(&self) -> &'static AtomicWaker; fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool; @@ -43,7 +37,7 @@ pub struct SpiDmaRxChannelImpl(C); impl crate::private::Sealed for SpiDmaRxChannelImpl {} -impl SpiDmaRxChannelImpl +impl SpiDmaRxChannelImpl where AnyPdmaChannel: From, { @@ -57,7 +51,7 @@ pub struct SpiDmaTxChannelImpl(C); impl crate::private::Sealed for SpiDmaTxChannelImpl {} -impl SpiDmaTxChannelImpl +impl SpiDmaTxChannelImpl where AnyPdmaChannel: From, { @@ -66,7 +60,7 @@ where } } -impl RegisterAccess for SpiDmaTxChannelImpl { +impl> RegisterAccess for SpiDmaTxChannelImpl { fn reset(&self) { let spi = self.0.register_block(); spi.dma_conf().modify(|_, w| w.out_rst().set_bit()); @@ -113,14 +107,16 @@ impl RegisterAccess for SpiDmaTxChannelImpl { } } -impl TxRegisterAccess for SpiDmaTxChannelImpl { +impl> TxRegisterAccess for SpiDmaTxChannelImpl { fn last_dscr_address(&self) -> usize { let spi = self.0.register_block(); spi.out_eof_des_addr().read().dma_out_eof_des_addr().bits() as usize } } -impl InterruptAccess for SpiDmaTxChannelImpl { +impl> InterruptAccess + for SpiDmaTxChannelImpl +{ fn enable_listen(&self, interrupts: EnumSet, enable: bool) { let reg_block = self.0.register_block(); reg_block.dma_int_ena().modify(|_, w| { @@ -198,7 +194,7 @@ impl InterruptAccess for SpiDmaTxChannelImpl< } } -impl RegisterAccess for SpiDmaRxChannelImpl { +impl> RegisterAccess for SpiDmaRxChannelImpl { fn reset(&self) { let spi = self.0.register_block(); spi.dma_conf().modify(|_, w| w.in_rst().set_bit()); @@ -244,9 +240,11 @@ impl RegisterAccess for SpiDmaRxChannelImpl { } } -impl RxRegisterAccess for SpiDmaRxChannelImpl {} +impl> RxRegisterAccess for SpiDmaRxChannelImpl {} -impl InterruptAccess for SpiDmaRxChannelImpl { +impl> InterruptAccess + for SpiDmaRxChannelImpl +{ fn enable_listen(&self, interrupts: EnumSet, enable: bool) { let reg_block = self.0.register_block(); reg_block.dma_int_ena().modify(|_, w| { @@ -388,7 +386,9 @@ macro_rules! ImplSpiChannel { } } - impl SpiPdmaChannel for [] { + impl PdmaChannel for [] { + type RegisterBlock = SpiRegisterBlock; + fn register_block(&self) -> &SpiRegisterBlock { unsafe { &*crate::peripherals::[]::PTR } } @@ -479,7 +479,7 @@ pub struct I2sDmaRxChannelImpl(C); impl crate::private::Sealed for I2sDmaRxChannelImpl {} -impl I2sDmaRxChannelImpl +impl I2sDmaRxChannelImpl where AnyPdmaChannel: From, { @@ -493,7 +493,7 @@ pub struct I2sDmaTxChannelImpl(C); impl crate::private::Sealed for I2sDmaTxChannelImpl {} -impl I2sDmaTxChannelImpl +impl I2sDmaTxChannelImpl where AnyPdmaChannel: From, { @@ -502,7 +502,7 @@ where } } -impl RegisterAccess for I2sDmaTxChannelImpl { +impl> RegisterAccess for I2sDmaTxChannelImpl { fn set_burst_mode(&self, burst_mode: bool) { let reg_block = self.0.register_block(); reg_block @@ -555,7 +555,7 @@ impl RegisterAccess for I2sDmaTxChannelImpl { } } -impl TxRegisterAccess for I2sDmaTxChannelImpl { +impl> TxRegisterAccess for I2sDmaTxChannelImpl { fn last_dscr_address(&self) -> usize { let reg_block = self.0.register_block(); reg_block @@ -566,7 +566,9 @@ impl TxRegisterAccess for I2sDmaTxChannelImpl { } } -impl InterruptAccess for I2sDmaTxChannelImpl { +impl> InterruptAccess + for I2sDmaTxChannelImpl +{ fn enable_listen(&self, interrupts: EnumSet, enable: bool) { let reg_block = self.0.register_block(); reg_block.int_ena().modify(|_, w| { @@ -644,7 +646,7 @@ impl InterruptAccess for I2sDmaTxChannelImpl< } } -impl RegisterAccess for I2sDmaRxChannelImpl { +impl> RegisterAccess for I2sDmaRxChannelImpl { fn set_burst_mode(&self, burst_mode: bool) { let reg_block = self.0.register_block(); reg_block @@ -695,9 +697,11 @@ impl RegisterAccess for I2sDmaRxChannelImpl { } } -impl RxRegisterAccess for I2sDmaRxChannelImpl {} +impl> RxRegisterAccess for I2sDmaRxChannelImpl {} -impl InterruptAccess for I2sDmaRxChannelImpl { +impl> InterruptAccess + for I2sDmaRxChannelImpl +{ fn enable_listen(&self, interrupts: EnumSet, enable: bool) { let reg_block = self.0.register_block(); reg_block.int_ena().modify(|_, w| { @@ -835,7 +839,9 @@ macro_rules! ImplI2sChannel { } } - impl I2sPdmaChannel for [] { + impl PdmaChannel for [] { + type RegisterBlock = I2sRegisterBlock; + fn register_block(&self) -> &I2sRegisterBlock { unsafe { &*crate::peripherals::[< I2S $num >]::PTR } } From a5cc2f3637e02daadfd9803075e4ae3ac9ffb5e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 4 Oct 2024 15:33:20 +0200 Subject: [PATCH 21/36] Remove redundant cfg --- esp-hal/src/dma/pdma.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index f8b4dab5d88..47400db25b4 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -915,7 +915,6 @@ macro_rules! ImplI2sChannel { } ImplSpiChannel!(2); -#[cfg(spi3)] ImplSpiChannel!(3); ImplI2sChannel!(0); From 4a91bfaee0038fa43a093088a3211aa0bb8bd3d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 15:10:01 +0200 Subject: [PATCH 22/36] Fix docs --- esp-hal/src/spi/master.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 0aaa2ad8c41..48f88f6af99 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -490,9 +490,9 @@ where T: InstanceDma, M: DuplexMode, { - /// Configures the SPI3 instance to use DMA with the specified channel. + /// Configures the SPI instance to use DMA with the specified channel. /// - /// This method prepares the SPI instance for DMA transfers using SPI3 + /// This method prepares the SPI instance for DMA transfers using SPI /// and returns an instance of `SpiDma` that supports DMA /// operations. pub fn with_dma( From 8865e999aaac78dd6f914065fa0b9611125d15c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 13:53:04 +0200 Subject: [PATCH 23/36] Simplify DmaEligible --- esp-hal/src/dma/mod.rs | 6 +----- esp-hal/src/peripheral.rs | 4 +++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index f5cabc95d6a..a6b1f7a6a5b 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -892,11 +892,7 @@ impl From for Owner { #[doc(hidden)] pub trait DmaEligible { - /// The DMA peripheral - const DMA_PERIPHERAL: DmaPeripheral; - fn dma_peripheral(&self) -> DmaPeripheral { - Self::DMA_PERIPHERAL - } + fn dma_peripheral(&self) -> DmaPeripheral; } /// Marker trait diff --git a/esp-hal/src/peripheral.rs b/esp-hal/src/peripheral.rs index 8b20a1e8cd2..45c11b45288 100644 --- a/esp-hal/src/peripheral.rs +++ b/esp-hal/src/peripheral.rs @@ -171,7 +171,9 @@ mod peripheral_macros { macro_rules! impl_dma_eligible { ($name:ident => $dma:ident) => { impl $crate::dma::DmaEligible for $name { - const DMA_PERIPHERAL: $crate::dma::DmaPeripheral = $crate::dma::DmaPeripheral::$dma; + fn dma_peripheral(&self) -> $crate::dma::DmaPeripheral { + $crate::dma::DmaPeripheral::$dma + } } }; From c7058547cee57e12dd5171ea7f9c4ba68010c037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 20:43:51 +0200 Subject: [PATCH 24/36] Remove unsafe code --- esp-hal/src/dma/pdma.rs | 146 +++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 61 deletions(-) diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 47400db25b4..c7f3f32a4e0 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -39,10 +39,10 @@ impl crate::private::Sealed for SpiDmaRxChannelImpl {} impl SpiDmaRxChannelImpl where - AnyPdmaChannel: From, + AnyPdmaRxChannel: From, { fn degrade(self) -> AnyPdmaRxChannelImpl { - AnyPdmaRxChannelImpl(AnyPdmaChannel::from(self.0)) + AnyPdmaRxChannelImpl(AnyPdmaRxChannel::from(self)) } } @@ -53,10 +53,10 @@ impl crate::private::Sealed for SpiDmaTxChannelImpl {} impl SpiDmaTxChannelImpl where - AnyPdmaChannel: From, + AnyPdmaTxChannel: From, { fn degrade(self) -> AnyPdmaTxChannelImpl { - AnyPdmaTxChannelImpl(AnyPdmaChannel::from(self.0)) + AnyPdmaTxChannelImpl(AnyPdmaTxChannel::from(self)) } } @@ -342,18 +342,6 @@ macro_rules! ImplSpiChannel { #[non_exhaustive] pub struct [] {} - impl [] { - unsafe fn clone_unchecked(&self) -> Self { - Self {} - } - } - - impl From<[]> for AnyPdmaChannel { - fn from(channel: []) -> Self { - AnyPdmaChannel::[](channel) - } - } - impl DmaChannel for [] { type Rx = SpiDmaRxChannelImpl; type Tx = SpiDmaTxChannelImpl; @@ -481,10 +469,10 @@ impl crate::private::Sealed for I2sDmaRxChannelImpl {} impl I2sDmaRxChannelImpl where - AnyPdmaChannel: From, + AnyPdmaRxChannel: From, { fn degrade(self) -> AnyPdmaRxChannelImpl { - AnyPdmaRxChannelImpl(AnyPdmaChannel::from(self.0)) + AnyPdmaRxChannelImpl(AnyPdmaRxChannel::from(self)) } } @@ -495,10 +483,10 @@ impl crate::private::Sealed for I2sDmaTxChannelImpl {} impl I2sDmaTxChannelImpl where - AnyPdmaChannel: From, + AnyPdmaTxChannel: From, { fn degrade(self) -> AnyPdmaTxChannelImpl { - AnyPdmaTxChannelImpl(AnyPdmaChannel::from(self.0)) + AnyPdmaTxChannelImpl(AnyPdmaTxChannel::from(self)) } } @@ -793,18 +781,6 @@ macro_rules! ImplI2sChannel { #[doc = concat!("DMA channel suitable for I2S", $num)] pub struct [] {} - impl [] { - unsafe fn clone_unchecked(&self) -> Self { - Self {} - } - } - - impl From<[]> for AnyPdmaChannel { - fn from(channel: []) -> Self { - AnyPdmaChannel::[](channel) - } - } - impl $crate::private::Sealed for [] {} impl DmaChannel for [] { @@ -955,13 +931,39 @@ impl<'d> Dma<'d> { } } -#[doc(hidden)] -pub enum AnyPdmaChannel { - Spi2(Spi2DmaChannel), - Spi3(Spi3DmaChannel), - I2s0(I2s0DmaChannel), - #[cfg(i2s1)] - I2s1(I2s1DmaChannel), +macro_rules! define_enum { + ( + $(#[$meta:meta])* + $vis:vis enum $ty:ident { + $($(#[$cfg:meta])? + $variant:ident($inner:ty),)* + } + ) => { + $(#[$meta])* + $vis enum $ty { + $($variant($inner)),* + } + + $( + $(#[$cfg])? + impl From<$inner> for $ty { + fn from(inner: $inner) -> Self { + Self::$variant(inner) + } + } + )* + } +} + +define_enum! { + #[doc(hidden)] + pub enum AnyPdmaChannel { + Spi2(Spi2DmaChannel), + Spi3(Spi3DmaChannel), + I2s0(I2s0DmaChannel), + #[cfg(i2s1)] + I2s1(I2s1DmaChannel), + } } impl DmaChannel for AnyDmaChannel { @@ -977,18 +979,29 @@ impl DmaChannel for AnyDmaChannel { } } +define_enum! { + #[doc(hidden)] + pub enum AnyPdmaRxChannel { + Spi2(SpiDmaRxChannelImpl), + Spi3(SpiDmaRxChannelImpl), + I2s0(I2sDmaRxChannelImpl), + #[cfg(i2s1)] + I2s1(I2sDmaRxChannelImpl), + } +} + #[doc(hidden)] -pub struct AnyPdmaRxChannelImpl(AnyPdmaChannel); +pub struct AnyPdmaRxChannelImpl(AnyPdmaRxChannel); impl crate::private::Sealed for AnyPdmaRxChannelImpl {} impl InterruptAccess for AnyPdmaRxChannelImpl { delegate::delegate! { to match &self.0 { - AnyPdmaChannel::Spi2(channel) => unsafe { SpiDmaRxChannelImpl(channel.clone_unchecked()) }, - AnyPdmaChannel::Spi3(channel) => unsafe { SpiDmaRxChannelImpl(channel.clone_unchecked()) }, - AnyPdmaChannel::I2s0(channel) => unsafe { I2sDmaRxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaRxChannel::Spi2(channel) => channel, + AnyPdmaRxChannel::Spi3(channel) => channel, + AnyPdmaRxChannel::I2s0(channel) => channel, #[cfg(i2s1)] - AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaRxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaRxChannel::I2s1(channel) => channel, } { fn enable_listen(&self, interrupts: EnumSet, enable: bool); fn is_listening(&self) -> EnumSet; @@ -1001,11 +1014,11 @@ impl InterruptAccess for AnyPdmaRxChannelImpl { impl RegisterAccess for AnyPdmaRxChannelImpl { delegate::delegate! { to match &self.0 { - AnyPdmaChannel::Spi2(channel) => unsafe { SpiDmaRxChannelImpl(channel.clone_unchecked()) }, - AnyPdmaChannel::Spi3(channel) => unsafe { SpiDmaRxChannelImpl(channel.clone_unchecked()) }, - AnyPdmaChannel::I2s0(channel) => unsafe { I2sDmaRxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaRxChannel::Spi2(channel) => channel, + AnyPdmaRxChannel::Spi3(channel) => channel, + AnyPdmaRxChannel::I2s0(channel) => channel, #[cfg(i2s1)] - AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaRxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaRxChannel::I2s1(channel) => channel, } { fn set_burst_mode(&self, burst_mode: bool); fn set_priority(&self, priority: DmaPriority); @@ -1021,18 +1034,29 @@ impl RegisterAccess for AnyPdmaRxChannelImpl { } impl RxRegisterAccess for AnyPdmaRxChannelImpl {} +define_enum! { + #[doc(hidden)] + pub enum AnyPdmaTxChannel { + Spi2(SpiDmaTxChannelImpl), + Spi3(SpiDmaTxChannelImpl), + I2s0(I2sDmaTxChannelImpl), + #[cfg(i2s1)] + I2s1(I2sDmaTxChannelImpl), + } +} + #[doc(hidden)] -pub struct AnyPdmaTxChannelImpl(AnyPdmaChannel); +pub struct AnyPdmaTxChannelImpl(AnyPdmaTxChannel); impl crate::private::Sealed for AnyPdmaTxChannelImpl {} impl InterruptAccess for AnyPdmaTxChannelImpl { delegate::delegate! { to match &self.0 { - AnyPdmaChannel::Spi2(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, - AnyPdmaChannel::Spi3(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, - AnyPdmaChannel::I2s0(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaTxChannel::Spi2(channel) => channel, + AnyPdmaTxChannel::Spi3(channel) => channel, + AnyPdmaTxChannel::I2s0(channel) => channel, #[cfg(i2s1)] - AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaTxChannel::I2s1(channel) => channel, } { fn enable_listen(&self, interrupts: EnumSet, enable: bool); fn is_listening(&self) -> EnumSet; @@ -1045,11 +1069,11 @@ impl InterruptAccess for AnyPdmaTxChannelImpl { impl RegisterAccess for AnyPdmaTxChannelImpl { delegate::delegate! { to match &self.0 { - AnyPdmaChannel::Spi2(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, - AnyPdmaChannel::Spi3(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, - AnyPdmaChannel::I2s0(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaTxChannel::Spi2(channel) => channel, + AnyPdmaTxChannel::Spi3(channel) => channel, + AnyPdmaTxChannel::I2s0(channel) => channel, #[cfg(i2s1)] - AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaTxChannel::I2s1(channel) => channel, } { fn set_burst_mode(&self, burst_mode: bool); fn set_priority(&self, priority: DmaPriority); @@ -1066,11 +1090,11 @@ impl RegisterAccess for AnyPdmaTxChannelImpl { impl TxRegisterAccess for AnyPdmaTxChannelImpl { delegate::delegate! { to match &self.0 { - AnyPdmaChannel::Spi2(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, - AnyPdmaChannel::Spi3(channel) => unsafe { SpiDmaTxChannelImpl(channel.clone_unchecked()) }, - AnyPdmaChannel::I2s0(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaTxChannel::Spi2(channel) => channel, + AnyPdmaTxChannel::Spi3(channel) => channel, + AnyPdmaTxChannel::I2s0(channel) => channel, #[cfg(i2s1)] - AnyPdmaChannel::I2s1(channel) => unsafe { I2sDmaTxChannelImpl(channel.clone_unchecked()) }, + AnyPdmaTxChannel::I2s1(channel) => channel, } { fn last_dscr_address(&self) -> usize; } From f3c4cec4d7e352f80398f081036b64095ed04fdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 20:49:35 +0200 Subject: [PATCH 25/36] Revert "Swap Channel type params, erase dma channel" This reverts commit 415e45e44b297fd3cb55b4261c9ce151cca4b9c9. --- esp-hal/CHANGELOG.md | 1 - esp-hal/MIGRATING-0.20.md | 13 ++---------- esp-hal/src/aes/mod.rs | 9 +++++---- esp-hal/src/dma/gdma.rs | 16 +++++++-------- esp-hal/src/dma/mod.rs | 16 +++++++-------- esp-hal/src/dma/pdma.rs | 16 +++++++-------- esp-hal/src/i2s.rs | 37 ++++++++++++++++++++++++----------- esp-hal/src/parl_io.rs | 25 +++++++++++------------ esp-hal/src/spi/master.rs | 7 ++++--- esp-hal/src/spi/slave.rs | 11 ++++++----- hil-test/tests/dma_mem2mem.rs | 4 ++-- hil-test/tests/qspi.rs | 4 ++-- 12 files changed, 84 insertions(+), 75 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index b9f86104374..78adae34bc2 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -66,7 +66,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - I2c `transaction` is now also available as a inherent function, lift size limit on `write`,`read` and `write_read` (#2262) - SPI transactions are now cancelled if the transfer object (or async Future) is dropped. (#2216) - The DMA channel types have been removed from peripherals (#2261) -- The channel type parameter of `dma::Channel` have been moved to the last position and can be erased using `degrade()` (#2261) ### Fixed diff --git a/esp-hal/MIGRATING-0.20.md b/esp-hal/MIGRATING-0.20.md index 66f383e31ae..a2cfaa1593a 100644 --- a/esp-hal/MIGRATING-0.20.md +++ b/esp-hal/MIGRATING-0.20.md @@ -340,15 +340,6 @@ A non-exhausitve list demonstrating this change: +SpiDma<'static, esp_hal::peripherals::SPI2, HalfDuplexMode, Blocking> ``` -The type parameters of `Channel` have been reordered. The channel type -has been moved to the last position. For example: - -```diff --Channel<'d, DmaChannel0, Async> -+Channel<'d, Async, DmaChannel0> -``` - -You can now call `dma_channel.degrade()` to obtain a type-erased version of `Channel`. You -don't have to spell out `Channel<'d, Mode, AnyDmaChannel>`, you can use `Channel<'d, Mode>` instead. -Note that on ESP32 and ESP32-S2, passing this channel to an incompatible peripheral (for example an +You can now call `dma_channel.degrade()` to obtain a type-erased version of `Channel`. Note that +on ESP32 and ESP32-S2, passing this channel to an incompatible peripheral (for example an I2S-specific DMA channel to SPI) will result in a panic. diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index 4b684500304..840bb05da9e 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -235,6 +235,7 @@ pub mod dma { aes::{Key, Mode}, dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, + AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -273,7 +274,7 @@ pub mod dma { /// The underlying [`Aes`](super::Aes) driver pub aes: super::Aes<'d>, - channel: Channel<'d, crate::Blocking>, + channel: Channel<'d, AnyDmaChannel, crate::Blocking>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, } @@ -282,7 +283,7 @@ pub mod dma { /// Enable DMA for the current instance of the AES driver pub fn with_dma( self, - channel: Channel<'d, crate::Blocking, C>, + channel: Channel<'d, C, crate::Blocking>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> AesDma<'d> @@ -322,7 +323,7 @@ pub mod dma { } impl<'d> DmaSupportTx for AesDma<'d> { - type TX = ChannelTx<'d>; + type TX = ChannelTx<'d, AnyDmaChannel>; fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx @@ -334,7 +335,7 @@ pub mod dma { } impl<'d> DmaSupportRx for AesDma<'d> { - type RX = ChannelRx<'d>; + type RX = ChannelRx<'d, AnyDmaChannel>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index a173cee2bb4..e54d1a58808 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -428,7 +428,7 @@ impl DmaChannel for AnyDmaChannel { } } -impl Channel<'_, M, CH> { +impl Channel<'_, CH, M> { /// Asserts that the channel is compatible with the given peripheral. pub fn runtime_ensure_compatible( &self, @@ -490,7 +490,7 @@ macro_rules! impl_channel { self, burst_mode: bool, priority: DmaPriority, - ) -> crate::dma::Channel<'a, M, []> { + ) -> crate::dma::Channel<'a, [], M> { let tx_impl = ChannelTxImpl(SpecificGdmaChannel::<$num> {}); tx_impl.set_burst_mode(burst_mode); tx_impl.set_priority(priority); @@ -517,7 +517,7 @@ macro_rules! impl_channel { self, burst_mode: bool, priority: DmaPriority, - ) -> crate::dma::Channel<'a, crate::Blocking, []> { + ) -> crate::dma::Channel<'a, [], crate::Blocking> { self.do_configure(burst_mode, priority) } @@ -529,7 +529,7 @@ macro_rules! impl_channel { self, burst_mode: bool, priority: DmaPriority, - ) -> crate::dma::Channel<'a, $crate::Async, []> { + ) -> crate::dma::Channel<'a, [], $crate::Async> { let this = self.do_configure(burst_mode, priority); []::set_isr($async_handler); @@ -648,7 +648,7 @@ mod m2m { where M: Mode, { - channel: Channel<'d, M>, + channel: Channel<'d, AnyDmaChannel, M>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, peripheral: DmaPeripheral, @@ -660,7 +660,7 @@ mod m2m { { /// Create a new Mem2Mem instance. pub fn new( - channel: Channel<'d, M, CH>, + channel: Channel<'d, CH, M>, peripheral: impl DmaEligible, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], @@ -681,7 +681,7 @@ mod m2m { /// Create a new Mem2Mem instance with specific chunk size. pub fn new_with_chunk_size( - channel: Channel<'d, M, CH>, + channel: Channel<'d, CH, M>, peripheral: impl DmaEligible, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], @@ -708,7 +708,7 @@ mod m2m { /// You must ensure that your not using DMA for the same peripheral and /// that your the only one using the DmaPeripheral. pub unsafe fn new_unsafe( - channel: Channel<'d, M, CH>, + channel: Channel<'d, CH, M>, peripheral: DmaPeripheral, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index a6b1f7a6a5b..da1130b1024 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1590,7 +1590,7 @@ pub trait Rx: crate::private::Sealed { // DMA receive channel #[non_exhaustive] #[doc(hidden)] -pub struct ChannelRx<'a, CH = AnyDmaChannel> +pub struct ChannelRx<'a, CH> where CH: DmaChannel, { @@ -1612,7 +1612,7 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelRx<'a> { + pub fn degrade(self) -> ChannelRx<'a, AnyDmaChannel> { ChannelRx { burst_mode: self.burst_mode, rx_impl: CH::degrade_rx(self.rx_impl), @@ -1803,7 +1803,7 @@ pub trait Tx: crate::private::Sealed { /// DMA transmit channel #[doc(hidden)] -pub struct ChannelTx<'a, CH = AnyDmaChannel> +pub struct ChannelTx<'a, CH> where CH: DmaChannel, { @@ -1826,7 +1826,7 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelTx<'a> { + pub fn degrade(self) -> ChannelTx<'a, AnyDmaChannel> { ChannelTx { burst_mode: self.burst_mode, tx_impl: CH::degrade_tx(self.tx_impl), @@ -2026,7 +2026,7 @@ pub trait InterruptAccess: crate::private::Sealed { } /// DMA Channel -pub struct Channel<'d, MODE, CH = AnyDmaChannel> +pub struct Channel<'d, CH, MODE> where CH: DmaChannel, MODE: Mode, @@ -2038,7 +2038,7 @@ where phantom: PhantomData, } -impl<'d, C> Channel<'d, crate::Blocking, C> +impl<'d, C> Channel<'d, C, crate::Blocking> where C: DmaChannel, { @@ -2096,13 +2096,13 @@ where } } -impl<'d, C, M: Mode> Channel<'d, M, C> +impl<'d, C, M: Mode> Channel<'d, C, M> where C: DmaChannel, { /// Return a type-erased (degraded) version of this channel (both rx and /// tx). - pub fn degrade(self) -> Channel<'d, M> { + pub fn degrade(self) -> Channel<'d, AnyDmaChannel, M> { Channel { rx: self.rx.degrade(), tx: self.tx.degrade(), diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index c7f3f32a4e0..f2e60d82264 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -405,7 +405,7 @@ macro_rules! ImplSpiChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, M, []> { + ) -> Channel<'a, [], M> { #[cfg(esp32)] { // (only) on ESP32 we need to configure DPORT for the SPI DMA channels @@ -438,7 +438,7 @@ macro_rules! ImplSpiChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, $crate::Blocking, []> { + ) -> Channel<'a, [], $crate::Blocking> { Self::do_configure(self, burst_mode, priority) } @@ -450,7 +450,7 @@ macro_rules! ImplSpiChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, $crate::Async, []> { + ) -> Channel<'a, [], $crate::Async> { let this = Self::do_configure(self, burst_mode, priority); []::set_isr(super::asynch::interrupt::[< interrupt_handler_spi $num _dma >]); @@ -842,7 +842,7 @@ macro_rules! ImplI2sChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, M, []> { + ) -> Channel<'a, [], M> { let tx_impl = I2sDmaTxChannelImpl([] {}); tx_impl.set_burst_mode(burst_mode); tx_impl.set_priority(priority); @@ -866,7 +866,7 @@ macro_rules! ImplI2sChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, $crate::Blocking, []> { + ) -> Channel<'a, [], $crate::Blocking> { Self::do_configure(self, burst_mode, priority) } @@ -878,7 +878,7 @@ macro_rules! ImplI2sChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, $crate::Async, []> { + ) -> Channel<'a, [], $crate::Async> { let this = Self::do_configure(self, burst_mode, priority); []::set_isr(super::asynch::interrupt::[< interrupt_handler_i2s $num >]); @@ -1101,9 +1101,9 @@ impl TxRegisterAccess for AnyPdmaTxChannelImpl { } } -impl<'d, CH, M: Mode> Channel<'d, M, CH> +impl<'d, C, M: Mode> Channel<'d, C, M> where - CH: DmaChannel, + C: DmaChannel, { /// Asserts that the channel is compatible with the given peripheral. pub fn runtime_ensure_compatible(&self, peripheral: &PeripheralRef<'_, impl PeripheralMarker>) { diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index ba77a614d69..1f3a5d5d3d9 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -87,6 +87,7 @@ use private::*; use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, + AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -337,7 +338,7 @@ where standard: Standard, data_format: DataFormat, sample_rate: impl Into, - channel: Channel<'d, DmaMode, CH>, + channel: Channel<'d, CH, DmaMode>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> Self { @@ -436,7 +437,7 @@ where standard: Standard, data_format: DataFormat, sample_rate: impl Into, - channel: Channel<'d, DmaMode, CH>, + channel: Channel<'d, CH, DmaMode>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> Self @@ -472,7 +473,7 @@ where T: RegisterAccess, { register_access: PhantomData, - tx_channel: ChannelTx<'d>, + tx_channel: ChannelTx<'d, AnyDmaChannel>, tx_chain: DescriptorChain, phantom: PhantomData, } @@ -506,7 +507,7 @@ where T: RegisterAccess, DmaMode: Mode, { - type TX = ChannelTx<'d>; + type TX = ChannelTx<'d, AnyDmaChannel>; fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel @@ -522,7 +523,10 @@ where T: RegisterAccess, DmaMode: Mode, { - fn new(tx_channel: ChannelTx<'d>, descriptors: &'static mut [DmaDescriptor]) -> Self { + fn new( + tx_channel: ChannelTx<'d, AnyDmaChannel>, + descriptors: &'static mut [DmaDescriptor], + ) -> Self { Self { register_access: PhantomData, tx_channel, @@ -636,7 +640,7 @@ where DmaMode: Mode, { register_access: PhantomData, - rx_channel: ChannelRx<'d>, + rx_channel: ChannelRx<'d, AnyDmaChannel>, rx_chain: DescriptorChain, phantom: PhantomData, } @@ -670,7 +674,7 @@ where T: RegisterAccess, DmaMode: Mode, { - type RX = ChannelRx<'d>; + type RX = ChannelRx<'d, AnyDmaChannel>; fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel @@ -686,7 +690,10 @@ where T: RegisterAccess, DmaMode: Mode, { - fn new(rx_channel: ChannelRx<'d>, descriptors: &'static mut [DmaDescriptor]) -> Self { + fn new( + rx_channel: ChannelRx<'d, AnyDmaChannel>, + descriptors: &'static mut [DmaDescriptor], + ) -> Self { Self { register_access: PhantomData, rx_channel, @@ -825,7 +832,15 @@ mod private { #[cfg(any(esp32, esp32s3))] use crate::peripherals::{i2s1::RegisterBlock, I2S1}; use crate::{ - dma::{ChannelRx, ChannelTx, DmaDescriptor, DmaEligible, DmaPeripheral, PeripheralMarker}, + dma::{ + AnyDmaChannel, + ChannelRx, + ChannelTx, + DmaDescriptor, + DmaEligible, + DmaPeripheral, + PeripheralMarker, + }, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, into_ref, @@ -841,7 +856,7 @@ mod private { DmaMode: Mode, { pub register_access: PhantomData, - pub tx_channel: ChannelTx<'d>, + pub tx_channel: ChannelTx<'d, AnyDmaChannel>, pub descriptors: &'static mut [DmaDescriptor], pub(crate) phantom: PhantomData, } @@ -895,7 +910,7 @@ mod private { DmaMode: Mode, { pub register_access: PhantomData, - pub rx_channel: ChannelRx<'d>, + pub rx_channel: ChannelRx<'d, AnyDmaChannel>, pub descriptors: &'static mut [DmaDescriptor], pub(crate) phantom: PhantomData, } diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 73854d4d981..fa88b88fcab 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -33,6 +33,7 @@ use private::*; use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, + AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -903,7 +904,7 @@ pub struct ParlIoTx<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d>, + tx_channel: ChannelTx<'d, AnyDmaChannel>, tx_chain: DescriptorChain, phantom: PhantomData, } @@ -982,7 +983,7 @@ pub struct ParlIoRx<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d>, + rx_channel: ChannelRx<'d, AnyDmaChannel>, rx_chain: DescriptorChain, phantom: PhantomData, } @@ -1093,7 +1094,7 @@ where /// Create a new instance of [ParlIoFullDuplex] pub fn new( _parl_io: impl Peripheral

+ 'd, - dma_channel: Channel<'d, DM, CH>, + dma_channel: Channel<'d, CH, DM>, tx_descriptors: &'static mut [DmaDescriptor], rx_descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, @@ -1174,7 +1175,7 @@ where // TODO: only take a TX DMA channel? pub fn new( _parl_io: impl Peripheral

+ 'd, - dma_channel: Channel<'d, DM, CH>, + dma_channel: Channel<'d, CH, DM>, descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, ) -> Result @@ -1249,7 +1250,7 @@ where // TODO: only take a RX DMA channel? pub fn new( _parl_io: impl Peripheral

+ 'd, - dma_channel: Channel<'d, DM, CH>, + dma_channel: Channel<'d, CH, DM>, descriptors: &'static mut [DmaDescriptor], frequency: HertzU32, ) -> Result @@ -1417,7 +1418,7 @@ impl<'d, DM> DmaSupportTx for ParlIoTx<'d, DM> where DM: Mode, { - type TX = ChannelTx<'d>; + type TX = ChannelTx<'d, AnyDmaChannel>; fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel @@ -1459,7 +1460,7 @@ where } fn start_receive_bytes_dma( - rx_channel: &mut ChannelRx<'d>, + rx_channel: &mut ChannelRx<'d, AnyDmaChannel>, rx_chain: &mut DescriptorChain, ptr: *mut u8, len: usize, @@ -1513,7 +1514,7 @@ impl<'d, DM> DmaSupportRx for ParlIoRx<'d, DM> where DM: Mode, { - type RX = ChannelRx<'d>; + type RX = ChannelRx<'d, AnyDmaChannel>; fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel @@ -1529,7 +1530,7 @@ pub struct TxCreator<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d>, + tx_channel: ChannelTx<'d, AnyDmaChannel>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1539,7 +1540,7 @@ pub struct RxCreator<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d>, + rx_channel: ChannelRx<'d, AnyDmaChannel>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1549,7 +1550,7 @@ pub struct TxCreatorFullDuplex<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d>, + tx_channel: ChannelTx<'d, AnyDmaChannel>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1559,7 +1560,7 @@ pub struct RxCreatorFullDuplex<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d>, + rx_channel: ChannelRx<'d, AnyDmaChannel>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 48f88f6af99..8db6f7ed75f 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -497,7 +497,7 @@ where /// operations. pub fn with_dma( self, - channel: crate::dma::Channel<'d, DmaMode, CH>, + channel: crate::dma::Channel<'d, CH, DmaMode>, ) -> SpiDma<'d, T, M, DmaMode> where CH: crate::dma::DmaChannel, @@ -939,6 +939,7 @@ mod dma { use crate::{ dma::{ asynch::{DmaRxFuture, DmaTxFuture}, + AnyDmaChannel, Channel, DmaChannel, DmaRxBuf, @@ -965,7 +966,7 @@ mod dma { M: Mode, { pub(crate) spi: PeripheralRef<'d, T>, - pub(crate) channel: Channel<'d, M>, + pub(crate) channel: Channel<'d, AnyDmaChannel, M>, tx_transfer_in_progress: bool, rx_transfer_in_progress: bool, #[cfg(all(esp32, spi_address_workaround))] @@ -1001,7 +1002,7 @@ mod dma { D: DuplexMode, M: Mode, { - pub(super) fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, M, CH>) -> Self + pub(super) fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, CH, M>) -> Self where CH: DmaChannel, { diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index e6e8640ec89..cc1700560ec 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -153,6 +153,7 @@ pub mod dma { use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, + AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -179,7 +180,7 @@ pub mod dma { #[cfg_attr(esp32, doc = "\n\n**Note**: ESP32 only supports Mode 1 and 3.")] pub fn with_dma( mut self, - channel: Channel<'d, DmaMode, CH>, + channel: Channel<'d, CH, DmaMode>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, T, DmaMode> @@ -199,7 +200,7 @@ pub mod dma { DmaMode: Mode, { pub(crate) spi: PeripheralRef<'d, T>, - pub(crate) channel: Channel<'d, DmaMode>, + pub(crate) channel: Channel<'d, AnyDmaChannel, DmaMode>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, } @@ -237,7 +238,7 @@ pub mod dma { T: InstanceDma, DmaMode: Mode, { - type TX = ChannelTx<'d>; + type TX = ChannelTx<'d, AnyDmaChannel>; fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx @@ -253,7 +254,7 @@ pub mod dma { T: InstanceDma, DmaMode: Mode, { - type RX = ChannelRx<'d>; + type RX = ChannelRx<'d, AnyDmaChannel>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx @@ -271,7 +272,7 @@ pub mod dma { { fn new( spi: PeripheralRef<'d, T>, - channel: Channel<'d, DmaMode, CH>, + channel: Channel<'d, CH, DmaMode>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> Self diff --git a/hil-test/tests/dma_mem2mem.rs b/hil-test/tests/dma_mem2mem.rs index f27ce2eb0ec..6499f90d9aa 100644 --- a/hil-test/tests/dma_mem2mem.rs +++ b/hil-test/tests/dma_mem2mem.rs @@ -6,7 +6,7 @@ #![no_main] use esp_hal::{ - dma::{Channel, Dma, DmaError, DmaPriority, Mem2Mem}, + dma::{AnyDmaChannel, Channel, Dma, DmaError, DmaPriority, Mem2Mem}, dma_buffers, dma_buffers_chunk_size, dma_descriptors, @@ -25,7 +25,7 @@ cfg_if::cfg_if! { } struct Context { - channel: Channel<'static, Blocking>, + channel: Channel<'static, AnyDmaChannel, Blocking>, dma_peripheral: DmaPeripheralType, } diff --git a/hil-test/tests/qspi.rs b/hil-test/tests/qspi.rs index d4ff9c0cbdd..f9358d70458 100644 --- a/hil-test/tests/qspi.rs +++ b/hil-test/tests/qspi.rs @@ -8,7 +8,7 @@ #[cfg(pcnt)] use esp_hal::pcnt::{channel::EdgeMode, unit::Unit, Pcnt}; use esp_hal::{ - dma::{Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, + dma::{AnyDmaChannel, Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::{AnyPin, Input, Io, Level, NoPin, Output, Pull}, prelude::*, @@ -36,7 +36,7 @@ struct Context { spi: esp_hal::peripherals::SPI2, #[cfg(pcnt)] pcnt: esp_hal::peripherals::PCNT, - dma_channel: Channel<'static, Blocking>, + dma_channel: Channel<'static, AnyDmaChannel, Blocking>, gpios: [AnyPin; 3], } From ebf93dba53de12ef2d1553a5a26186321315561c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 22:01:26 +0200 Subject: [PATCH 26/36] Allow different degraded DMA types --- esp-hal/src/aes/mod.rs | 11 ++++---- esp-hal/src/dma/gdma.rs | 42 +++++++++++++++------------- esp-hal/src/dma/mod.rs | 25 ++++++++--------- esp-hal/src/dma/pdma.rs | 21 ++++++-------- esp-hal/src/i2s.rs | 45 +++++++++++------------------- esp-hal/src/lcd_cam/cam.rs | 16 +++++++++-- esp-hal/src/lcd_cam/lcd/i8080.rs | 6 ++-- esp-hal/src/lcd_cam/mod.rs | 14 ++++++++-- esp-hal/src/parl_io.rs | 48 ++++++++++++++------------------ esp-hal/src/peripheral.rs | 5 ++++ esp-hal/src/spi/master.rs | 26 ++++++++++++----- esp-hal/src/spi/slave.rs | 13 +++++---- 12 files changed, 146 insertions(+), 126 deletions(-) diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index 840bb05da9e..22fe02781d7 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -235,13 +235,13 @@ pub mod dma { aes::{Key, Mode}, dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, - AnyDmaChannel, Channel, ChannelRx, ChannelTx, DescriptorChain, DmaChannel, DmaDescriptor, + DmaEligible, DmaPeripheral, DmaTransferRxTx, ReadBuffer, @@ -249,6 +249,7 @@ pub mod dma { Tx, WriteBuffer, }, + peripherals::AES, }; const ALIGN_SIZE: usize = core::mem::size_of::(); @@ -274,7 +275,7 @@ pub mod dma { /// The underlying [`Aes`](super::Aes) driver pub aes: super::Aes<'d>, - channel: Channel<'d, AnyDmaChannel, crate::Blocking>, + channel: Channel<'d, ::Dma, crate::Blocking>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, } @@ -289,7 +290,7 @@ pub mod dma { ) -> AesDma<'d> where Self: Sized, - C: DmaChannel, + C: DmaChannel::Dma>, { AesDma { aes: self, @@ -323,7 +324,7 @@ pub mod dma { } impl<'d> DmaSupportTx for AesDma<'d> { - type TX = ChannelTx<'d, AnyDmaChannel>; + type TX = ChannelTx<'d, ::Dma>; fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx @@ -335,7 +336,7 @@ pub mod dma { } impl<'d> DmaSupportRx for AesDma<'d> { - type RX = ChannelRx<'d, AnyDmaChannel>; + type RX = ChannelRx<'d, ::Dma>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index e54d1a58808..00ec8aef18b 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -25,9 +25,24 @@ pub trait GdmaChannel { fn number(&self) -> u8; } +/// An arbitrary GDMA channel #[non_exhaustive] -#[doc(hidden)] pub struct AnyGdmaChannel(u8); + +impl crate::private::Sealed for AnyGdmaChannel {} +impl DmaChannel for AnyGdmaChannel { + type Degraded = Self; + type Rx = ChannelRxImpl; + type Tx = ChannelTxImpl; + + fn degrade_rx(rx: Self::Rx) -> ChannelRxImpl { + rx + } + fn degrade_tx(tx: Self::Tx) -> ChannelTxImpl { + tx + } +} + #[non_exhaustive] #[doc(hidden)] pub struct SpecificGdmaChannel {} @@ -416,18 +431,6 @@ impl InterruptAccess for ChannelRxImpl { #[non_exhaustive] pub struct ChannelCreator {} -impl DmaChannel for AnyDmaChannel { - type Rx = ChannelRxImpl; - type Tx = ChannelTxImpl; - - fn degrade_rx(rx: Self::Rx) -> ChannelRxImpl { - rx - } - fn degrade_tx(tx: Self::Tx) -> ChannelTxImpl { - tx - } -} - impl Channel<'_, CH, M> { /// Asserts that the channel is compatible with the given peripheral. pub fn runtime_ensure_compatible( @@ -456,6 +459,7 @@ macro_rules! impl_channel { impl crate::private::Sealed for [] {} impl DmaChannel for [] { + type Degraded = AnyGdmaChannel; type Rx = ChannelRxImpl>; type Tx = ChannelTxImpl>; @@ -621,7 +625,7 @@ mod m2m { use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx}, - AnyDmaChannel, + AnyGdmaChannel, Channel, ChannelRx, DescriptorChain, @@ -648,7 +652,7 @@ mod m2m { where M: Mode, { - channel: Channel<'d, AnyDmaChannel, M>, + channel: Channel<'d, AnyGdmaChannel, M>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, peripheral: DmaPeripheral, @@ -666,7 +670,7 @@ mod m2m { tx_descriptors: &'static mut [DmaDescriptor], ) -> Result where - CH: DmaChannel, + CH: DmaChannel, { unsafe { Self::new_unsafe( @@ -688,7 +692,7 @@ mod m2m { chunk_size: usize, ) -> Result where - CH: DmaChannel, + CH: DmaChannel, { unsafe { Self::new_unsafe( @@ -715,7 +719,7 @@ mod m2m { chunk_size: usize, ) -> Result where - CH: DmaChannel, + CH: DmaChannel, { if !(1..=4092).contains(&chunk_size) { return Err(DmaError::InvalidChunkSize); @@ -792,7 +796,7 @@ mod m2m { where MODE: Mode, { - type RX = ChannelRx<'d, AnyDmaChannel>; + type RX = ChannelRx<'d, AnyGdmaChannel>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index da1130b1024..8262a75c5b2 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -892,6 +892,8 @@ impl From for Owner { #[doc(hidden)] pub trait DmaEligible { + type Dma: DmaChannel; + fn dma_peripheral(&self) -> DmaPeripheral; } @@ -1495,6 +1497,9 @@ impl RxCircularState { /// A description of a DMA Channel. pub trait DmaChannel: crate::private::Sealed { + /// The type-erased version of this DMA channel type. + type Degraded: DmaChannel; + /// A description of the RX half of a DMA Channel. type Rx: RxRegisterAccess + InterruptAccess; @@ -1503,9 +1508,9 @@ pub trait DmaChannel: crate::private::Sealed { // TODO: maybe document #[doc(hidden)] - fn degrade_rx(rx: Self::Rx) -> ::Rx; + fn degrade_rx(rx: Self::Rx) -> ::Rx; #[doc(hidden)] - fn degrade_tx(tx: Self::Tx) -> ::Tx; + fn degrade_tx(tx: Self::Tx) -> ::Tx; } /// A description of a DMA Channel that can be used with a peripheral. @@ -1515,12 +1520,6 @@ pub trait PeripheralDmaChannel: DmaChannel { type P: PeripheralMarker; } -/// A description of any DMA channel -#[non_exhaustive] -pub struct AnyDmaChannel {} - -impl crate::private::Sealed for AnyDmaChannel {} - #[doc(hidden)] pub trait DmaChannelExt: DmaChannel { fn get_rx_interrupts() -> impl InterruptAccess; @@ -1612,7 +1611,7 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelRx<'a, AnyDmaChannel> { + pub fn degrade(self) -> ChannelRx<'a, CH::Degraded> { ChannelRx { burst_mode: self.burst_mode, rx_impl: CH::degrade_rx(self.rx_impl), @@ -1826,7 +1825,7 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelTx<'a, AnyDmaChannel> { + pub fn degrade(self) -> ChannelTx<'a, CH::Degraded> { ChannelTx { burst_mode: self.burst_mode, tx_impl: CH::degrade_tx(self.tx_impl), @@ -2096,13 +2095,13 @@ where } } -impl<'d, C, M: Mode> Channel<'d, C, M> +impl<'d, CH, M: Mode> Channel<'d, CH, M> where - C: DmaChannel, + CH: DmaChannel, { /// Return a type-erased (degraded) version of this channel (both rx and /// tx). - pub fn degrade(self) -> Channel<'d, AnyDmaChannel, M> { + pub fn degrade(self) -> Channel<'d, CH::Degraded, M> { Channel { rx: self.rx.degrade(), tx: self.tx.degrade(), diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index f2e60d82264..7367e1acfa9 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -343,6 +343,7 @@ macro_rules! ImplSpiChannel { pub struct [] {} impl DmaChannel for [] { + type Degraded = AnyPdmaChannel; type Rx = SpiDmaRxChannelImpl; type Tx = SpiDmaTxChannelImpl; @@ -784,6 +785,7 @@ macro_rules! ImplI2sChannel { impl $crate::private::Sealed for [] {} impl DmaChannel for [] { + type Degraded = AnyPdmaChannel; type Rx = I2sDmaRxChannelImpl; type Tx = I2sDmaTxChannelImpl; @@ -955,18 +957,13 @@ macro_rules! define_enum { } } -define_enum! { - #[doc(hidden)] - pub enum AnyPdmaChannel { - Spi2(Spi2DmaChannel), - Spi3(Spi3DmaChannel), - I2s0(I2s0DmaChannel), - #[cfg(i2s1)] - I2s1(I2s1DmaChannel), - } -} +/// An arbitrary PDMA channel +#[non_exhaustive] +pub struct AnyPdmaChannel; +impl crate::private::Sealed for AnyPdmaChannel {} -impl DmaChannel for AnyDmaChannel { +impl DmaChannel for AnyPdmaChannel { + type Degraded = Self; type Rx = AnyPdmaRxChannelImpl; type Tx = AnyPdmaTxChannelImpl; @@ -1128,4 +1125,4 @@ where } #[cfg(pdma)] -impl

DmaCompatible for (AnyDmaChannel, P) where P: PeripheralMarker {} +impl

DmaCompatible for (AnyPdmaChannel, P) where P: PeripheralMarker {} diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index 1f3a5d5d3d9..77addf6990d 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -87,12 +87,12 @@ use private::*; use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, - AnyDmaChannel, Channel, ChannelRx, ChannelTx, DescriptorChain, DmaChannel, + DmaCompatible, DmaDescriptor, DmaError, DmaTransferRx, @@ -333,7 +333,7 @@ where DmaMode: Mode, { #[allow(clippy::too_many_arguments)] - fn new_internal( + fn new_internal( i2s: impl Peripheral

+ 'd, standard: Standard, data_format: DataFormat, @@ -341,7 +341,10 @@ where channel: Channel<'d, CH, DmaMode>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], - ) -> Self { + ) -> Self + where + CH: DmaChannel, + { crate::into_ref!(i2s); channel.runtime_ensure_compatible(&i2s); // on ESP32-C3 / ESP32-S3 and later RX and TX are independent and @@ -442,8 +445,8 @@ where tx_descriptors: &'static mut [DmaDescriptor], ) -> Self where - CH: crate::dma::DmaChannel, - (CH, I): crate::dma::DmaCompatible, + CH: DmaChannel, + (CH, I): DmaCompatible, DmaMode: Mode, { Self::new_internal( @@ -473,7 +476,7 @@ where T: RegisterAccess, { register_access: PhantomData, - tx_channel: ChannelTx<'d, AnyDmaChannel>, + tx_channel: ChannelTx<'d, T::Dma>, tx_chain: DescriptorChain, phantom: PhantomData, } @@ -507,7 +510,7 @@ where T: RegisterAccess, DmaMode: Mode, { - type TX = ChannelTx<'d, AnyDmaChannel>; + type TX = ChannelTx<'d, T::Dma>; fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel @@ -523,10 +526,7 @@ where T: RegisterAccess, DmaMode: Mode, { - fn new( - tx_channel: ChannelTx<'d, AnyDmaChannel>, - descriptors: &'static mut [DmaDescriptor], - ) -> Self { + fn new(tx_channel: ChannelTx<'d, T::Dma>, descriptors: &'static mut [DmaDescriptor]) -> Self { Self { register_access: PhantomData, tx_channel, @@ -640,7 +640,7 @@ where DmaMode: Mode, { register_access: PhantomData, - rx_channel: ChannelRx<'d, AnyDmaChannel>, + rx_channel: ChannelRx<'d, T::Dma>, rx_chain: DescriptorChain, phantom: PhantomData, } @@ -674,7 +674,7 @@ where T: RegisterAccess, DmaMode: Mode, { - type RX = ChannelRx<'d, AnyDmaChannel>; + type RX = ChannelRx<'d, T::Dma>; fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel @@ -690,10 +690,7 @@ where T: RegisterAccess, DmaMode: Mode, { - fn new( - rx_channel: ChannelRx<'d, AnyDmaChannel>, - descriptors: &'static mut [DmaDescriptor], - ) -> Self { + fn new(rx_channel: ChannelRx<'d, T::Dma>, descriptors: &'static mut [DmaDescriptor]) -> Self { Self { register_access: PhantomData, rx_channel, @@ -832,15 +829,7 @@ mod private { #[cfg(any(esp32, esp32s3))] use crate::peripherals::{i2s1::RegisterBlock, I2S1}; use crate::{ - dma::{ - AnyDmaChannel, - ChannelRx, - ChannelTx, - DmaDescriptor, - DmaEligible, - DmaPeripheral, - PeripheralMarker, - }, + dma::{ChannelRx, ChannelTx, DmaDescriptor, DmaEligible, DmaPeripheral, PeripheralMarker}, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, into_ref, @@ -856,7 +845,7 @@ mod private { DmaMode: Mode, { pub register_access: PhantomData, - pub tx_channel: ChannelTx<'d, AnyDmaChannel>, + pub tx_channel: ChannelTx<'d, T::Dma>, pub descriptors: &'static mut [DmaDescriptor], pub(crate) phantom: PhantomData, } @@ -910,7 +899,7 @@ mod private { DmaMode: Mode, { pub register_access: PhantomData, - pub rx_channel: ChannelRx<'d, AnyDmaChannel>, + pub rx_channel: ChannelRx<'d, T::Dma>, pub descriptors: &'static mut [DmaDescriptor], pub(crate) phantom: PhantomData, } diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index bb6c0adf821..0c026665f61 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -74,7 +74,16 @@ use fugit::HertzU32; use crate::{ clock::Clocks, - dma::{AnyDmaChannel, ChannelRx, DmaChannel, DmaError, DmaPeripheral, DmaRxBuffer, Rx}, + dma::{ + ChannelRx, + DmaChannel, + DmaCompatible, + DmaEligible, + DmaError, + DmaPeripheral, + DmaRxBuffer, + Rx, + }, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull}, lcd_cam::{cam::private::RxPins, private::calculate_clkm, BitOrder, ByteOrder}, peripheral::{Peripheral, PeripheralRef}, @@ -122,7 +131,7 @@ pub struct Cam<'d> { /// Represents the camera interface with DMA support. pub struct Camera<'d> { lcd_cam: PeripheralRef<'d, LCD_CAM>, - rx_channel: ChannelRx<'d, AnyDmaChannel>, + rx_channel: ChannelRx<'d, ::Dma>, } impl<'d> Camera<'d> { @@ -134,7 +143,8 @@ impl<'d> Camera<'d> { frequency: HertzU32, ) -> Self where - CH: DmaChannel, + CH: DmaChannel::Dma>, + (CH, LCD_CAM): DmaCompatible, P: RxPins, { let lcd_cam = cam.lcd_cam; diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index fb58218bfec..8c11f2e6f0c 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -69,7 +69,7 @@ use fugit::HertzU32; use crate::{ clock::Clocks, - dma::{AnyDmaChannel, ChannelTx, DmaChannel, DmaError, DmaPeripheral, DmaTxBuffer, Tx}, + dma::{ChannelTx, DmaChannel, DmaEligible, DmaError, DmaPeripheral, DmaTxBuffer, Tx}, gpio::{OutputSignal, PeripheralOutput}, lcd_cam::{ asynch::LCD_DONE_WAKER, @@ -87,7 +87,7 @@ use crate::{ /// Represents the I8080 LCD interface. pub struct I8080<'d, DM: Mode> { lcd_cam: PeripheralRef<'d, LCD_CAM>, - tx_channel: ChannelTx<'d, AnyDmaChannel>, + tx_channel: ChannelTx<'d, ::Dma>, _phantom: PhantomData, } @@ -101,7 +101,7 @@ impl<'d, DM: Mode> I8080<'d, DM> { config: Config, ) -> Self where - CH: DmaChannel, + CH: DmaChannel::Dma>, P: TxPins, { let lcd_cam = lcd.lcd_cam; diff --git a/esp-hal/src/lcd_cam/mod.rs b/esp-hal/src/lcd_cam/mod.rs index f47b639e6e5..a1f55b7e13c 100644 --- a/esp-hal/src/lcd_cam/mod.rs +++ b/esp-hal/src/lcd_cam/mod.rs @@ -136,6 +136,14 @@ pub mod asynch { } mod private { + use crate::{dma::PeripheralMarker, peripherals::LCD_CAM}; + + impl PeripheralMarker for LCD_CAM { + fn peripheral(&self) -> crate::system::Peripheral { + crate::system::Peripheral::LcdCam + } + } + pub(crate) struct Instance; // NOTE: the LCD_CAM interrupt registers are shared between LCD and Camera and @@ -143,21 +151,21 @@ mod private { // CriticalSection will be needed to protect these shared registers. impl Instance { pub(crate) fn listen_lcd_done() { - let lcd_cam = unsafe { crate::peripherals::LCD_CAM::steal() }; + let lcd_cam = unsafe { LCD_CAM::steal() }; lcd_cam .lc_dma_int_ena() .modify(|_, w| w.lcd_trans_done_int_ena().set_bit()); } pub(crate) fn unlisten_lcd_done() { - let lcd_cam = unsafe { crate::peripherals::LCD_CAM::steal() }; + let lcd_cam = unsafe { LCD_CAM::steal() }; lcd_cam .lc_dma_int_ena() .modify(|_, w| w.lcd_trans_done_int_ena().clear_bit()); } pub(crate) fn is_lcd_done_set() -> bool { - let lcd_cam = unsafe { crate::peripherals::LCD_CAM::steal() }; + let lcd_cam = unsafe { LCD_CAM::steal() }; lcd_cam .lc_dma_int_raw() .read() diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index fa88b88fcab..66ee48ae924 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -33,13 +33,13 @@ use private::*; use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, - AnyDmaChannel, Channel, ChannelRx, ChannelTx, DescriptorChain, DmaChannel, DmaDescriptor, + DmaEligible, DmaError, DmaPeripheral, DmaTransferRx, @@ -52,7 +52,7 @@ use crate::{ gpio::{PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, peripheral::{self, Peripheral}, - peripherals, + peripherals::{self, PARL_IO}, system::PeripheralClockControl, Blocking, InterruptConfigurable, @@ -904,7 +904,7 @@ pub struct ParlIoTx<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d, AnyDmaChannel>, + tx_channel: ChannelTx<'d, ::Dma>, tx_chain: DescriptorChain, phantom: PhantomData, } @@ -983,7 +983,7 @@ pub struct ParlIoRx<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d, AnyDmaChannel>, + rx_channel: ChannelRx<'d, ::Dma>, rx_chain: DescriptorChain, phantom: PhantomData, } @@ -1000,17 +1000,15 @@ where fn internal_set_interrupt_handler(handler: InterruptHandler) { #[cfg(esp32c6)] { - unsafe { crate::peripherals::PARL_IO::steal() }.bind_parl_io_interrupt(handler.handler()); + unsafe { PARL_IO::steal() }.bind_parl_io_interrupt(handler.handler()); crate::interrupt::enable(crate::peripherals::Interrupt::PARL_IO, handler.priority()) .unwrap(); } #[cfg(esp32h2)] { - unsafe { crate::peripherals::PARL_IO::steal() } - .bind_parl_io_tx_interrupt(handler.handler()); - unsafe { crate::peripherals::PARL_IO::steal() } - .bind_parl_io_rx_interrupt(handler.handler()); + unsafe { PARL_IO::steal() }.bind_parl_io_tx_interrupt(handler.handler()); + unsafe { PARL_IO::steal() }.bind_parl_io_rx_interrupt(handler.handler()); crate::interrupt::enable( crate::peripherals::Interrupt::PARL_IO_TX, @@ -1026,7 +1024,7 @@ fn internal_set_interrupt_handler(handler: InterruptHandler) { } fn internal_listen(interrupts: EnumSet, enable: bool) { - let parl_io = unsafe { crate::peripherals::PARL_IO::steal() }; + let parl_io = unsafe { PARL_IO::steal() }; for interrupt in interrupts { match interrupt { ParlIoInterrupt::TxFifoReEmpty => parl_io @@ -1042,7 +1040,7 @@ fn internal_listen(interrupts: EnumSet, enable: bool) { fn internal_interrupts() -> EnumSet { let mut res = EnumSet::new(); - let parl_io = unsafe { crate::peripherals::PARL_IO::steal() }; + let parl_io = unsafe { PARL_IO::steal() }; let ints = parl_io.int_st().read(); if ints.tx_fifo_rempty().bit() { res.insert(ParlIoInterrupt::TxFifoReEmpty); @@ -1058,7 +1056,7 @@ fn internal_interrupts() -> EnumSet { } fn internal_clear_interrupts(interrupts: EnumSet) { - let parl_io = unsafe { crate::peripherals::PARL_IO::steal() }; + let parl_io = unsafe { PARL_IO::steal() }; for interrupt in interrupts { match interrupt { ParlIoInterrupt::TxFifoReEmpty => parl_io @@ -1100,7 +1098,7 @@ where frequency: HertzU32, ) -> Result where - CH: DmaChannel, + CH: DmaChannel::Dma>, { internal_init(frequency)?; @@ -1180,7 +1178,7 @@ where frequency: HertzU32, ) -> Result where - CH: DmaChannel, + CH: DmaChannel::Dma>, { internal_init(frequency)?; @@ -1255,7 +1253,7 @@ where frequency: HertzU32, ) -> Result where - CH: DmaChannel, + CH: DmaChannel::Dma>, { internal_init(frequency)?; @@ -1384,11 +1382,7 @@ where .and_then(|_| self.tx_channel.start_transfer())?; } - loop { - if Instance::is_tx_ready() { - break; - } - } + while !Instance::is_tx_ready() {} Instance::set_tx_start(true); @@ -1418,7 +1412,7 @@ impl<'d, DM> DmaSupportTx for ParlIoTx<'d, DM> where DM: Mode, { - type TX = ChannelTx<'d, AnyDmaChannel>; + type TX = ChannelTx<'d, ::Dma>; fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel @@ -1460,7 +1454,7 @@ where } fn start_receive_bytes_dma( - rx_channel: &mut ChannelRx<'d, AnyDmaChannel>, + rx_channel: &mut ChannelRx<'d, ::Dma>, rx_chain: &mut DescriptorChain, ptr: *mut u8, len: usize, @@ -1514,7 +1508,7 @@ impl<'d, DM> DmaSupportRx for ParlIoRx<'d, DM> where DM: Mode, { - type RX = ChannelRx<'d, AnyDmaChannel>; + type RX = ChannelRx<'d, ::Dma>; fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel @@ -1530,7 +1524,7 @@ pub struct TxCreator<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d, AnyDmaChannel>, + tx_channel: ChannelTx<'d, ::Dma>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1540,7 +1534,7 @@ pub struct RxCreator<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d, AnyDmaChannel>, + rx_channel: ChannelRx<'d, ::Dma>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1550,7 +1544,7 @@ pub struct TxCreatorFullDuplex<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d, AnyDmaChannel>, + tx_channel: ChannelTx<'d, ::Dma>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } @@ -1560,7 +1554,7 @@ pub struct RxCreatorFullDuplex<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d, AnyDmaChannel>, + rx_channel: ChannelRx<'d, ::Dma>, descriptors: &'static mut [DmaDescriptor], phantom: PhantomData, } diff --git a/esp-hal/src/peripheral.rs b/esp-hal/src/peripheral.rs index 45c11b45288..ac0f4032f3f 100644 --- a/esp-hal/src/peripheral.rs +++ b/esp-hal/src/peripheral.rs @@ -171,6 +171,11 @@ mod peripheral_macros { macro_rules! impl_dma_eligible { ($name:ident => $dma:ident) => { impl $crate::dma::DmaEligible for $name { + #[cfg(pdma)] + type Dma = $crate::dma::AnyPdmaChannel; + #[cfg(gdma)] + type Dma = $crate::dma::AnyGdmaChannel; + fn dma_peripheral(&self) -> $crate::dma::DmaPeripheral { $crate::dma::DmaPeripheral::$dma } diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 8db6f7ed75f..416e0cf8fc8 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -81,13 +81,23 @@ use super::{ }; use crate::{ clock::Clocks, - dma::{DmaEligible, DmaRxBuffer, DmaTxBuffer, PeripheralMarker, Rx, Tx}, + dma::{ + DmaChannel, + DmaCompatible, + DmaEligible, + DmaRxBuffer, + DmaTxBuffer, + PeripheralMarker, + Rx, + Tx, + }, gpio::{InputSignal, NoPin, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, peripherals::spi2::RegisterBlock, private, system::PeripheralClockControl, + Mode, }; /// Enumeration of possible SPI interrupt events. @@ -500,9 +510,9 @@ where channel: crate::dma::Channel<'d, CH, DmaMode>, ) -> SpiDma<'d, T, M, DmaMode> where - CH: crate::dma::DmaChannel, - (CH, T): crate::dma::DmaCompatible, - DmaMode: crate::Mode, + CH: DmaChannel, + (CH, T): DmaCompatible, + DmaMode: Mode, { SpiDma::new(self.spi, channel) } @@ -939,7 +949,6 @@ mod dma { use crate::{ dma::{ asynch::{DmaRxFuture, DmaTxFuture}, - AnyDmaChannel, Channel, DmaChannel, DmaRxBuf, @@ -962,11 +971,12 @@ mod dma { /// embedded-hal traits. pub struct SpiDma<'d, T, D, M> where + T: InstanceDma, D: DuplexMode, M: Mode, { pub(crate) spi: PeripheralRef<'d, T>, - pub(crate) channel: Channel<'d, AnyDmaChannel, M>, + pub(crate) channel: Channel<'d, T::Dma, M>, tx_transfer_in_progress: bool, rx_transfer_in_progress: bool, #[cfg(all(esp32, spi_address_workaround))] @@ -977,6 +987,7 @@ mod dma { #[cfg(all(esp32, spi_address_workaround))] unsafe impl<'d, T, D, M> Send for SpiDma<'d, T, D, M> where + T: InstanceDma, D: DuplexMode, M: Mode, { @@ -984,6 +995,7 @@ mod dma { impl<'d, T, D, M> core::fmt::Debug for SpiDma<'d, T, D, M> where + T: InstanceDma, D: DuplexMode, M: Mode, { @@ -1004,7 +1016,7 @@ mod dma { { pub(super) fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, CH, M>) -> Self where - CH: DmaChannel, + CH: DmaChannel, { channel.runtime_ensure_compatible(&spi); #[cfg(all(esp32, spi_address_workaround))] diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index cc1700560ec..fcfc2351b8e 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -153,7 +153,6 @@ pub mod dma { use crate::{ dma::{ dma_private::{DmaSupport, DmaSupportRx, DmaSupportTx}, - AnyDmaChannel, Channel, ChannelRx, ChannelTx, @@ -185,7 +184,7 @@ pub mod dma { tx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, T, DmaMode> where - CH: DmaChannel, + CH: DmaChannel, (CH, T): crate::dma::DmaCompatible, DmaMode: Mode, { @@ -197,16 +196,18 @@ pub mod dma { /// A DMA capable SPI instance. pub struct SpiDma<'d, T, DmaMode> where + T: InstanceDma, DmaMode: Mode, { pub(crate) spi: PeripheralRef<'d, T>, - pub(crate) channel: Channel<'d, AnyDmaChannel, DmaMode>, + pub(crate) channel: Channel<'d, T::Dma, DmaMode>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, } impl<'d, T, DmaMode> core::fmt::Debug for SpiDma<'d, T, DmaMode> where + T: InstanceDma, DmaMode: Mode, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -238,7 +239,7 @@ pub mod dma { T: InstanceDma, DmaMode: Mode, { - type TX = ChannelTx<'d, AnyDmaChannel>; + type TX = ChannelTx<'d, T::Dma>; fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx @@ -254,7 +255,7 @@ pub mod dma { T: InstanceDma, DmaMode: Mode, { - type RX = ChannelRx<'d, AnyDmaChannel>; + type RX = ChannelRx<'d, T::Dma>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx @@ -277,7 +278,7 @@ pub mod dma { tx_descriptors: &'static mut [DmaDescriptor], ) -> Self where - CH: DmaChannel, + CH: DmaChannel, { channel.runtime_ensure_compatible(&spi); Self { From 458266780ed63bd3dfc020b6e9d6cdb3d155a14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 22:24:22 +0200 Subject: [PATCH 27/36] Allow converting into peripheral-specific DMA channel, use it for compat check --- esp-hal/src/aes/mod.rs | 4 +-- esp-hal/src/dma/gdma.rs | 27 ++++------------- esp-hal/src/dma/mod.rs | 50 ++++++++++++++++++++------------ esp-hal/src/dma/pdma.rs | 30 +++---------------- esp-hal/src/i2s.rs | 8 ++--- esp-hal/src/lcd_cam/cam.rs | 14 ++------- esp-hal/src/lcd_cam/lcd/i8080.rs | 4 +-- esp-hal/src/parl_io.rs | 8 ++--- esp-hal/src/spi/master.rs | 17 ++--------- esp-hal/src/spi/slave.rs | 8 ++--- 10 files changed, 61 insertions(+), 109 deletions(-) diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index 22fe02781d7..bbf18752534 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -239,7 +239,7 @@ pub mod dma { ChannelRx, ChannelTx, DescriptorChain, - DmaChannel, + DmaChannelConvert, DmaDescriptor, DmaEligible, DmaPeripheral, @@ -290,7 +290,7 @@ pub mod dma { ) -> AesDma<'d> where Self: Sized, - C: DmaChannel::Dma>, + C: DmaChannelConvert<::Dma>, { AesDma { aes: self, diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index 00ec8aef18b..5b8dbcbb1fa 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -31,16 +31,8 @@ pub struct AnyGdmaChannel(u8); impl crate::private::Sealed for AnyGdmaChannel {} impl DmaChannel for AnyGdmaChannel { - type Degraded = Self; type Rx = ChannelRxImpl; type Tx = ChannelTxImpl; - - fn degrade_rx(rx: Self::Rx) -> ChannelRxImpl { - rx - } - fn degrade_tx(tx: Self::Tx) -> ChannelTxImpl { - tx - } } #[non_exhaustive] @@ -441,14 +433,6 @@ impl Channel<'_, CH, M> { } } -// Every DMA channel is compatible with every (DMA eligible) peripheral. -impl DmaCompatible for (CH, P) -where - CH: DmaChannel, - P: PeripheralMarker + DmaEligible, -{ -} - macro_rules! impl_channel { ($num: literal, $async_handler: path, $($interrupt: ident),* ) => { paste::paste! { @@ -459,10 +443,11 @@ macro_rules! impl_channel { impl crate::private::Sealed for [] {} impl DmaChannel for [] { - type Degraded = AnyGdmaChannel; type Rx = ChannelRxImpl>; type Tx = ChannelTxImpl>; + } + impl DmaChannelConvert for [] { fn degrade_rx(rx: Self::Rx) -> ChannelRxImpl { rx.degrade() } @@ -629,7 +614,7 @@ mod m2m { Channel, ChannelRx, DescriptorChain, - DmaChannel, + DmaChannelConvert, DmaDescriptor, DmaEligible, DmaError, @@ -670,7 +655,7 @@ mod m2m { tx_descriptors: &'static mut [DmaDescriptor], ) -> Result where - CH: DmaChannel, + CH: DmaChannelConvert, { unsafe { Self::new_unsafe( @@ -692,7 +677,7 @@ mod m2m { chunk_size: usize, ) -> Result where - CH: DmaChannel, + CH: DmaChannelConvert, { unsafe { Self::new_unsafe( @@ -719,7 +704,7 @@ mod m2m { chunk_size: usize, ) -> Result where - CH: DmaChannel, + CH: DmaChannelConvert, { if !(1..=4092).contains(&chunk_size) { return Err(DmaError::InvalidChunkSize); diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 8262a75c5b2..200d0eb51d0 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -892,6 +892,7 @@ impl From for Owner { #[doc(hidden)] pub trait DmaEligible { + /// The most specific DMA channel type usable by this peripheral. type Dma: DmaChannel; fn dma_peripheral(&self) -> DmaPeripheral; @@ -903,12 +904,6 @@ pub trait PeripheralMarker { fn peripheral(&self) -> crate::system::Peripheral; } -/// Trait implemented for (DmaChannel, Peripheral) pairs that are compatible. -/// This is used to statically verify that the DMA channel is compatible with -/// the peripheral. -#[doc(hidden)] -pub trait DmaCompatible {} - #[doc(hidden)] #[derive(Debug)] pub struct DescriptorChain { @@ -1497,20 +1492,11 @@ impl RxCircularState { /// A description of a DMA Channel. pub trait DmaChannel: crate::private::Sealed { - /// The type-erased version of this DMA channel type. - type Degraded: DmaChannel; - /// A description of the RX half of a DMA Channel. type Rx: RxRegisterAccess + InterruptAccess; /// A description of the TX half of a DMA Channel. type Tx: TxRegisterAccess + InterruptAccess; - - // TODO: maybe document - #[doc(hidden)] - fn degrade_rx(rx: Self::Rx) -> ::Rx; - #[doc(hidden)] - fn degrade_tx(tx: Self::Tx) -> ::Tx; } /// A description of a DMA Channel that can be used with a peripheral. @@ -1529,6 +1515,25 @@ pub trait DmaChannelExt: DmaChannel { fn set_isr(handler: InterruptHandler); } +#[doc(hidden)] +pub trait DmaChannelConvert: DmaChannel { + // TODO: maybe document + #[doc(hidden)] + fn degrade_rx(rx: Self::Rx) -> DEG::Rx; + #[doc(hidden)] + fn degrade_tx(tx: Self::Tx) -> DEG::Tx; +} + +impl DmaChannelConvert for DEG { + fn degrade_rx(rx: Self::Rx) -> DEG::Rx { + rx + } + + fn degrade_tx(tx: Self::Tx) -> DEG::Tx { + tx + } +} + /// The functions here are not meant to be used outside the HAL #[doc(hidden)] pub trait Rx: crate::private::Sealed { @@ -1611,7 +1616,10 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelRx<'a, CH::Degraded> { + pub fn degrade(self) -> ChannelRx<'a, DEG> + where + CH: DmaChannelConvert, + { ChannelRx { burst_mode: self.burst_mode, rx_impl: CH::degrade_rx(self.rx_impl), @@ -1825,7 +1833,10 @@ where } /// Return a type-erased (degraded) version of this channel. - pub fn degrade(self) -> ChannelTx<'a, CH::Degraded> { + pub fn degrade(self) -> ChannelTx<'a, DEG> + where + CH: DmaChannelConvert, + { ChannelTx { burst_mode: self.burst_mode, tx_impl: CH::degrade_tx(self.tx_impl), @@ -2101,7 +2112,10 @@ where { /// Return a type-erased (degraded) version of this channel (both rx and /// tx). - pub fn degrade(self) -> Channel<'d, CH::Degraded, M> { + pub fn degrade(self) -> Channel<'d, DEG, M> + where + CH: DmaChannelConvert, + { Channel { rx: self.rx.degrade(), tx: self.tx.degrade(), diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 7367e1acfa9..8911ef48c65 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -343,10 +343,11 @@ macro_rules! ImplSpiChannel { pub struct [] {} impl DmaChannel for [] { - type Degraded = AnyPdmaChannel; type Rx = SpiDmaRxChannelImpl; type Tx = SpiDmaTxChannelImpl; + } + impl DmaChannelConvert for [] { fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { rx.degrade() } @@ -785,10 +786,11 @@ macro_rules! ImplI2sChannel { impl $crate::private::Sealed for [] {} impl DmaChannel for [] { - type Degraded = AnyPdmaChannel; type Rx = I2sDmaRxChannelImpl; type Tx = I2sDmaTxChannelImpl; + } + impl DmaChannelConvert for [] { fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { rx.degrade() } @@ -963,17 +965,8 @@ pub struct AnyPdmaChannel; impl crate::private::Sealed for AnyPdmaChannel {} impl DmaChannel for AnyPdmaChannel { - type Degraded = Self; type Rx = AnyPdmaRxChannelImpl; type Tx = AnyPdmaTxChannelImpl; - - fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { - rx - } - - fn degrade_tx(tx: Self::Tx) -> AnyPdmaTxChannelImpl { - tx - } } define_enum! { @@ -1111,18 +1104,3 @@ where ); } } - -// Every DMA channel is compatible with a single peripheral. -// TODO: While on ESP32 we have two DMA channels for three SPI peripherals, we -// currently only support 2 out of the 3 SPI peripherals. Complicating this -// further to cover SPI1 is not useful right now. -#[cfg(pdma)] -impl DmaCompatible for (CH, P) -where - CH: PeripheralDmaChannel

, - P: PeripheralMarker, -{ -} - -#[cfg(pdma)] -impl

DmaCompatible for (AnyPdmaChannel, P) where P: PeripheralMarker {} diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index 77addf6990d..6b9d9035f86 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -91,8 +91,7 @@ use crate::{ ChannelRx, ChannelTx, DescriptorChain, - DmaChannel, - DmaCompatible, + DmaChannelConvert, DmaDescriptor, DmaError, DmaTransferRx, @@ -343,7 +342,7 @@ where tx_descriptors: &'static mut [DmaDescriptor], ) -> Self where - CH: DmaChannel, + CH: DmaChannelConvert, { crate::into_ref!(i2s); channel.runtime_ensure_compatible(&i2s); @@ -445,8 +444,7 @@ where tx_descriptors: &'static mut [DmaDescriptor], ) -> Self where - CH: DmaChannel, - (CH, I): DmaCompatible, + CH: DmaChannelConvert, DmaMode: Mode, { Self::new_internal( diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index 0c026665f61..00841606611 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -74,16 +74,7 @@ use fugit::HertzU32; use crate::{ clock::Clocks, - dma::{ - ChannelRx, - DmaChannel, - DmaCompatible, - DmaEligible, - DmaError, - DmaPeripheral, - DmaRxBuffer, - Rx, - }, + dma::{ChannelRx, DmaChannelConvert, DmaEligible, DmaError, DmaPeripheral, DmaRxBuffer, Rx}, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull}, lcd_cam::{cam::private::RxPins, private::calculate_clkm, BitOrder, ByteOrder}, peripheral::{Peripheral, PeripheralRef}, @@ -143,8 +134,7 @@ impl<'d> Camera<'d> { frequency: HertzU32, ) -> Self where - CH: DmaChannel::Dma>, - (CH, LCD_CAM): DmaCompatible, + CH: DmaChannelConvert<::Dma>, P: RxPins, { let lcd_cam = cam.lcd_cam; diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index 8c11f2e6f0c..0261778f5a9 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -69,7 +69,7 @@ use fugit::HertzU32; use crate::{ clock::Clocks, - dma::{ChannelTx, DmaChannel, DmaEligible, DmaError, DmaPeripheral, DmaTxBuffer, Tx}, + dma::{ChannelTx, DmaChannelConvert, DmaEligible, DmaError, DmaPeripheral, DmaTxBuffer, Tx}, gpio::{OutputSignal, PeripheralOutput}, lcd_cam::{ asynch::LCD_DONE_WAKER, @@ -101,7 +101,7 @@ impl<'d, DM: Mode> I8080<'d, DM> { config: Config, ) -> Self where - CH: DmaChannel::Dma>, + CH: DmaChannelConvert<::Dma>, P: TxPins, { let lcd_cam = lcd.lcd_cam; diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 66ee48ae924..45267024da5 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -37,7 +37,7 @@ use crate::{ ChannelRx, ChannelTx, DescriptorChain, - DmaChannel, + DmaChannelConvert, DmaDescriptor, DmaEligible, DmaError, @@ -1098,7 +1098,7 @@ where frequency: HertzU32, ) -> Result where - CH: DmaChannel::Dma>, + CH: DmaChannelConvert<::Dma>, { internal_init(frequency)?; @@ -1178,7 +1178,7 @@ where frequency: HertzU32, ) -> Result where - CH: DmaChannel::Dma>, + CH: DmaChannelConvert<::Dma>, { internal_init(frequency)?; @@ -1253,7 +1253,7 @@ where frequency: HertzU32, ) -> Result where - CH: DmaChannel::Dma>, + CH: DmaChannelConvert<::Dma>, { internal_init(frequency)?; diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 416e0cf8fc8..5c2b6b86e48 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -81,16 +81,7 @@ use super::{ }; use crate::{ clock::Clocks, - dma::{ - DmaChannel, - DmaCompatible, - DmaEligible, - DmaRxBuffer, - DmaTxBuffer, - PeripheralMarker, - Rx, - Tx, - }, + dma::{DmaChannelConvert, DmaEligible, DmaRxBuffer, DmaTxBuffer, PeripheralMarker, Rx, Tx}, gpio::{InputSignal, NoPin, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, @@ -510,8 +501,7 @@ where channel: crate::dma::Channel<'d, CH, DmaMode>, ) -> SpiDma<'d, T, M, DmaMode> where - CH: DmaChannel, - (CH, T): DmaCompatible, + CH: DmaChannelConvert, DmaMode: Mode, { SpiDma::new(self.spi, channel) @@ -950,7 +940,6 @@ mod dma { dma::{ asynch::{DmaRxFuture, DmaTxFuture}, Channel, - DmaChannel, DmaRxBuf, DmaRxBuffer, DmaTxBuf, @@ -1016,7 +1005,7 @@ mod dma { { pub(super) fn new(spi: PeripheralRef<'d, T>, channel: Channel<'d, CH, M>) -> Self where - CH: DmaChannel, + CH: DmaChannelConvert, { channel.runtime_ensure_compatible(&spi); #[cfg(all(esp32, spi_address_workaround))] diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index fcfc2351b8e..c56add2c3fc 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -73,7 +73,7 @@ use core::marker::PhantomData; use super::{Error, FullDuplexMode, SpiMode}; use crate::{ - dma::{DescriptorChain, DmaEligible, PeripheralMarker, Rx, Tx}, + dma::{DescriptorChain, DmaChannelConvert, DmaEligible, PeripheralMarker, Rx, Tx}, gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, peripheral::{Peripheral, PeripheralRef}, peripherals::spi2::RegisterBlock, @@ -157,7 +157,6 @@ pub mod dma { ChannelRx, ChannelTx, DescriptorChain, - DmaChannel, DmaDescriptor, DmaTransferRx, DmaTransferRxTx, @@ -184,8 +183,7 @@ pub mod dma { tx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, T, DmaMode> where - CH: DmaChannel, - (CH, T): crate::dma::DmaCompatible, + CH: DmaChannelConvert, DmaMode: Mode, { self.spi.set_data_mode(self.data_mode, true); @@ -278,7 +276,7 @@ pub mod dma { tx_descriptors: &'static mut [DmaDescriptor], ) -> Self where - CH: DmaChannel, + CH: DmaChannelConvert, { channel.runtime_ensure_compatible(&spi); Self { From 3c4e93468f12aec2cf75577a028229fb4bd65cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 22:40:18 +0200 Subject: [PATCH 28/36] Erase PDMA types without AnyPdmaChannel --- esp-hal/src/dma/gdma.rs | 51 ++++++++++++++++++++++++++ esp-hal/src/dma/mod.rs | 31 ++++++++++++++-- esp-hal/src/dma/pdma.rs | 13 ++++++- esp-hal/src/peripheral.rs | 77 --------------------------------------- 4 files changed, 91 insertions(+), 81 deletions(-) diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index 5b8dbcbb1fa..a31fff60b40 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -554,6 +554,57 @@ cfg_if::cfg_if! { } } +crate::impl_dma_eligible! { + AnyGdmaChannel { + #[cfg(spi2)] + SPI2 => Spi2, + + #[cfg(spi3)] + SPI3 => Spi3, + + #[cfg(uhci0)] + UHCI0 => Uhci0, + + #[cfg(i2s0)] + I2S0 => I2s0, + + #[cfg(i2s1)] + I2S1 => I2s1, + + #[cfg(all(gdma, aes))] + AES => Aes, + + #[cfg(all(gdma, sha))] + SHA => Sha, + + #[cfg(any(esp32c3, esp32c6, esp32h2))] + ADC1 => Adc, + + #[cfg(esp32c3)] + ADC2 => Adc, + + #[cfg(parl_io)] + PARL_IO => ParlIo, + + #[cfg(any(esp32c2, esp32c6, esp32h2))] + MEM2MEM1 => Mem2Mem1, + } +} + +#[cfg(any(esp32c6, esp32h2))] +crate::impl_dma_eligible! { + AnyGdmaChannel { + MEM2MEM4 => Mem2Mem4, + MEM2MEM5 => Mem2Mem5, + MEM2MEM10 => Mem2Mem10, + MEM2MEM11 => Mem2Mem11, + MEM2MEM12 => Mem2Mem12, + MEM2MEM13 => Mem2Mem13, + MEM2MEM14 => Mem2Mem14, + MEM2MEM15 => Mem2Mem15, + } +} + /// GDMA Peripheral /// /// This offers the available DMA channels. diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 200d0eb51d0..b343cc7f41a 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -898,6 +898,31 @@ pub trait DmaEligible { fn dma_peripheral(&self) -> DmaPeripheral; } +#[doc(hidden)] +#[macro_export] +macro_rules! impl_dma_eligible { + ([$dma_ch:ident] $name:ident => $dma:ident) => { + impl $crate::dma::DmaEligible for $crate::peripherals::$name { + type Dma = $dma_ch; + + fn dma_peripheral(&self) -> $crate::dma::DmaPeripheral { + $crate::dma::DmaPeripheral::$dma + } + } + }; + + ( + $dma_ch:ident { + $($(#[$cfg:meta])? $name:ident => $dma:ident,)* + } + ) => { + $( + $(#[$cfg])? + $crate::impl_dma_eligible!([$dma_ch] $name => $dma); + )* + }; +} + /// Marker trait #[doc(hidden)] pub trait PeripheralMarker { @@ -1615,7 +1640,7 @@ where } } - /// Return a type-erased (degraded) version of this channel. + /// Return a less specific (degraded) version of this channel. pub fn degrade(self) -> ChannelRx<'a, DEG> where CH: DmaChannelConvert, @@ -1832,7 +1857,7 @@ where } } - /// Return a type-erased (degraded) version of this channel. + /// Return a less specific (degraded) version of this channel. pub fn degrade(self) -> ChannelTx<'a, DEG> where CH: DmaChannelConvert, @@ -2110,7 +2135,7 @@ impl<'d, CH, M: Mode> Channel<'d, CH, M> where CH: DmaChannel, { - /// Return a type-erased (degraded) version of this channel (both rx and + /// Return a less specific (degraded) version of this channel (both rx and /// tx). pub fn degrade(self) -> Channel<'d, DEG, M> where diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 8911ef48c65..4dd8bcd2d6c 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -901,6 +901,15 @@ ImplI2sChannel!(0); #[cfg(i2s1)] ImplI2sChannel!(1); +// Specific peripherals use specific channels. Note that this may be overly +// restrictive (ESP32 allows configuring 2 SPI DMA channels between 3 different +// peripherals), but for the current set of restrictions this is sufficient. +crate::impl_dma_eligible!([Spi2DmaChannel] SPI2 => Spi2); +crate::impl_dma_eligible!([Spi3DmaChannel] SPI3 => Spi3); +crate::impl_dma_eligible!([I2s0DmaChannel] I2S0 => I2s0); +#[cfg(i2s1)] +crate::impl_dma_eligible!([I2s1DmaChannel] I2S1 => I2s1); + /// DMA Peripheral /// /// This offers the available DMA channels. @@ -959,7 +968,9 @@ macro_rules! define_enum { } } -/// An arbitrary PDMA channel +/// An arbitrary PDMA channel. +// NOTE: this is unused currently (peripherals prescribe a specific channel) but type-erased +// peripherals will require type-erased channels. #[non_exhaustive] pub struct AnyPdmaChannel; impl crate::private::Sealed for AnyPdmaChannel {} diff --git a/esp-hal/src/peripheral.rs b/esp-hal/src/peripheral.rs index ac0f4032f3f..887835f2214 100644 --- a/esp-hal/src/peripheral.rs +++ b/esp-hal/src/peripheral.rs @@ -166,30 +166,6 @@ where impl crate::private::Sealed for &mut T where T: crate::private::Sealed {} mod peripheral_macros { - #[doc(hidden)] - #[macro_export] - macro_rules! impl_dma_eligible { - ($name:ident => $dma:ident) => { - impl $crate::dma::DmaEligible for $name { - #[cfg(pdma)] - type Dma = $crate::dma::AnyPdmaChannel; - #[cfg(gdma)] - type Dma = $crate::dma::AnyGdmaChannel; - - fn dma_peripheral(&self) -> $crate::dma::DmaPeripheral { - $crate::dma::DmaPeripheral::$dma - } - } - }; - - ($($(#[$cfg:meta])? $name:ident => $dma:ident),*) => { - $( - $(#[$cfg])? - $crate::impl_dma_eligible!($name => $dma); - )* - }; - } - #[doc(hidden)] #[macro_export] macro_rules! peripherals { @@ -201,59 +177,6 @@ mod peripheral_macros { $( $crate::create_peripheral!($(#[$cfg])? $name <= $from_pac); )* - - $crate::impl_dma_eligible! { - #[cfg(spi2)] - SPI2 => Spi2, - - #[cfg(spi3)] - SPI3 => Spi3, - - #[cfg(all(uhci0, gdma))] // TODO: S2? - UHCI0 => Uhci0, - - #[cfg(i2s0)] - I2S0 => I2s0, - - #[cfg(i2s1)] - I2S1 => I2s1, - - #[cfg(esp32s3)] - LCD_CAM => LcdCam, - - #[cfg(all(gdma, aes))] - AES => Aes, - - #[cfg(all(gdma, sha))] - SHA => Sha, - - #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] - ADC1 => Adc, - - #[cfg(any(esp32c3, esp32s3))] - ADC2 => Adc, - - #[cfg(esp32s3)] - RMT => Rmt, - - #[cfg(parl_io)] - PARL_IO => ParlIo, - - #[cfg(any(esp32c2, esp32c6, esp32h2))] - MEM2MEM1 => Mem2Mem1 - } - - #[cfg(any(esp32c6, esp32h2))] - $crate::impl_dma_eligible! { - MEM2MEM4 => Mem2Mem4, - MEM2MEM5 => Mem2Mem5, - MEM2MEM10 => Mem2Mem10, - MEM2MEM11 => Mem2Mem11, - MEM2MEM12 => Mem2Mem12, - MEM2MEM13 => Mem2Mem13, - MEM2MEM14 => Mem2Mem14, - MEM2MEM15 => Mem2Mem15 - } } /// The `Peripherals` struct provides access to all of the hardware peripherals on the chip. From b9c0eb66b9b9eb628a81affe15a0cd577a8d0cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 22:46:04 +0200 Subject: [PATCH 29/36] Hide degrade fns for now, remove from MG --- esp-hal/MIGRATING-0.20.md | 4 ---- esp-hal/src/dma/mod.rs | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/esp-hal/MIGRATING-0.20.md b/esp-hal/MIGRATING-0.20.md index a2cfaa1593a..8682884d1f2 100644 --- a/esp-hal/MIGRATING-0.20.md +++ b/esp-hal/MIGRATING-0.20.md @@ -339,7 +339,3 @@ A non-exhausitve list demonstrating this change: -SpiDma<'static, esp_hal::peripherals::SPI2, DmaChannel0, HalfDuplexMode, Blocking> +SpiDma<'static, esp_hal::peripherals::SPI2, HalfDuplexMode, Blocking> ``` - -You can now call `dma_channel.degrade()` to obtain a type-erased version of `Channel`. Note that -on ESP32 and ESP32-S2, passing this channel to an incompatible peripheral (for example an -I2S-specific DMA channel to SPI) will result in a panic. diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index b343cc7f41a..02c6257f756 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1542,10 +1542,7 @@ pub trait DmaChannelExt: DmaChannel { #[doc(hidden)] pub trait DmaChannelConvert: DmaChannel { - // TODO: maybe document - #[doc(hidden)] fn degrade_rx(rx: Self::Rx) -> DEG::Rx; - #[doc(hidden)] fn degrade_tx(tx: Self::Tx) -> DEG::Tx; } @@ -1641,6 +1638,7 @@ where } /// Return a less specific (degraded) version of this channel. + #[doc(hidden)] pub fn degrade(self) -> ChannelRx<'a, DEG> where CH: DmaChannelConvert, @@ -1858,6 +1856,7 @@ where } /// Return a less specific (degraded) version of this channel. + #[doc(hidden)] pub fn degrade(self) -> ChannelTx<'a, DEG> where CH: DmaChannelConvert, @@ -2137,6 +2136,7 @@ where { /// Return a less specific (degraded) version of this channel (both rx and /// tx). + #[doc(hidden)] pub fn degrade(self) -> Channel<'d, DEG, M> where CH: DmaChannelConvert, From be8ed88a66fcee2fbbbd454525859d7d81e96156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 22:50:57 +0200 Subject: [PATCH 30/36] Clean up SPI slave --- esp-hal/src/spi/slave.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index c56add2c3fc..71e62967aae 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -548,8 +548,6 @@ impl InstanceDma for crate::peripherals::SPI3 {} pub trait Instance: private::Sealed + PeripheralMarker { fn register_block(&self) -> &RegisterBlock; - fn peripheral(&self) -> crate::system::Peripheral; - fn sclk_signal(&self) -> InputSignal; fn mosi_signal(&self) -> InputSignal; @@ -735,11 +733,6 @@ impl Instance for crate::peripherals::SPI2 { 2 } - #[inline(always)] - fn peripheral(&self) -> crate::system::Peripheral { - crate::system::Peripheral::Spi2 - } - #[inline(always)] fn sclk_signal(&self) -> InputSignal { cfg_if::cfg_if! { @@ -797,11 +790,6 @@ impl Instance for crate::peripherals::SPI3 { 3 } - #[inline(always)] - fn peripheral(&self) -> crate::system::Peripheral { - crate::system::Peripheral::Spi3 - } - #[inline(always)] fn sclk_signal(&self) -> InputSignal { cfg_if::cfg_if! { From a09efe90d37122fef85a6adb027abffacf39a558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 22:53:09 +0200 Subject: [PATCH 31/36] Fix QSPI test --- hil-test/tests/qspi.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hil-test/tests/qspi.rs b/hil-test/tests/qspi.rs index f9358d70458..ac60df1a421 100644 --- a/hil-test/tests/qspi.rs +++ b/hil-test/tests/qspi.rs @@ -8,7 +8,7 @@ #[cfg(pcnt)] use esp_hal::pcnt::{channel::EdgeMode, unit::Unit, Pcnt}; use esp_hal::{ - dma::{AnyDmaChannel, Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, + dma::{Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::{AnyPin, Input, Io, Level, NoPin, Output, Pull}, prelude::*, @@ -22,6 +22,14 @@ use esp_hal::{ }; use hil_test as _; +cfg_if::cfg_if! { + if #[cfg(pdma)] { + use esp_hal::dma::Spi2DmaChannel as DmaChannel0; + } else { + use esp_hal::dma::DmaChannel0; + } +} + cfg_if::cfg_if! { if #[cfg(esp32)] { const COMMAND_DATA_MODES: [SpiDataMode; 1] = [SpiDataMode::Single]; @@ -36,7 +44,7 @@ struct Context { spi: esp_hal::peripherals::SPI2, #[cfg(pcnt)] pcnt: esp_hal::peripherals::PCNT, - dma_channel: Channel<'static, AnyDmaChannel, Blocking>, + dma_channel: Channel<'static, DmaChannel0, Blocking>, gpios: [AnyPin; 3], } From bc76e6be5b42d3ab2c1afaa5571472970c53d454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 22:56:00 +0200 Subject: [PATCH 32/36] Fix mem2mem, fix S3 peripherals --- esp-hal/src/dma/gdma.rs | 10 ++++++++-- hil-test/tests/dma_mem2mem.rs | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index a31fff60b40..3cd616cbef7 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -571,18 +571,24 @@ crate::impl_dma_eligible! { #[cfg(i2s1)] I2S1 => I2s1, + #[cfg(esp32s3)] + LCD_CAM => LcdCam, + #[cfg(all(gdma, aes))] AES => Aes, #[cfg(all(gdma, sha))] SHA => Sha, - #[cfg(any(esp32c3, esp32c6, esp32h2))] + #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] ADC1 => Adc, - #[cfg(esp32c3)] + #[cfg(any(esp32c3, esp32s3))] ADC2 => Adc, + #[cfg(esp32s3)] + RMT => Rmt, + #[cfg(parl_io)] PARL_IO => ParlIo, diff --git a/hil-test/tests/dma_mem2mem.rs b/hil-test/tests/dma_mem2mem.rs index 6499f90d9aa..f65873ae6c5 100644 --- a/hil-test/tests/dma_mem2mem.rs +++ b/hil-test/tests/dma_mem2mem.rs @@ -6,7 +6,7 @@ #![no_main] use esp_hal::{ - dma::{AnyDmaChannel, Channel, Dma, DmaError, DmaPriority, Mem2Mem}, + dma::{AnyGdmaChannel, Channel, Dma, DmaError, DmaPriority, Mem2Mem}, dma_buffers, dma_buffers_chunk_size, dma_descriptors, @@ -25,7 +25,7 @@ cfg_if::cfg_if! { } struct Context { - channel: Channel<'static, AnyDmaChannel, Blocking>, + channel: Channel<'static, AnyGdmaChannel, Blocking>, dma_peripheral: DmaPeripheralType, } From d14714d7c4b047b380ba5948ab0cad16f9876f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 23:06:16 +0200 Subject: [PATCH 33/36] Fix S2 --- esp-hal/src/dma/pdma.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 4dd8bcd2d6c..88e81aefcba 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -954,7 +954,10 @@ macro_rules! define_enum { ) => { $(#[$meta])* $vis enum $ty { - $($variant($inner)),* + $( + $(#[$cfg])? + $variant($inner), + )* } $( From 52c500a4e54bc2c9f08ae91558523d13f935c01e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 7 Oct 2024 23:08:41 +0200 Subject: [PATCH 34/36] Remove AnyPdmaChannel --- esp-hal/src/dma/pdma.rs | 213 ---------------------------------------- 1 file changed, 213 deletions(-) diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 88e81aefcba..1a238dbea46 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -37,29 +37,11 @@ pub struct SpiDmaRxChannelImpl(C); impl crate::private::Sealed for SpiDmaRxChannelImpl {} -impl SpiDmaRxChannelImpl -where - AnyPdmaRxChannel: From, -{ - fn degrade(self) -> AnyPdmaRxChannelImpl { - AnyPdmaRxChannelImpl(AnyPdmaRxChannel::from(self)) - } -} - #[doc(hidden)] pub struct SpiDmaTxChannelImpl(C); impl crate::private::Sealed for SpiDmaTxChannelImpl {} -impl SpiDmaTxChannelImpl -where - AnyPdmaTxChannel: From, -{ - fn degrade(self) -> AnyPdmaTxChannelImpl { - AnyPdmaTxChannelImpl(AnyPdmaTxChannel::from(self)) - } -} - impl> RegisterAccess for SpiDmaTxChannelImpl { fn reset(&self) { let spi = self.0.register_block(); @@ -347,14 +329,6 @@ macro_rules! ImplSpiChannel { type Tx = SpiDmaTxChannelImpl; } - impl DmaChannelConvert for [] { - fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { - rx.degrade() - } - fn degrade_tx(tx: Self::Tx) -> AnyPdmaTxChannelImpl { - tx.degrade() - } - } impl PeripheralDmaChannel for [] { type P = crate::peripherals::[]; } @@ -469,29 +443,11 @@ pub struct I2sDmaRxChannelImpl(C); impl crate::private::Sealed for I2sDmaRxChannelImpl {} -impl I2sDmaRxChannelImpl -where - AnyPdmaRxChannel: From, -{ - fn degrade(self) -> AnyPdmaRxChannelImpl { - AnyPdmaRxChannelImpl(AnyPdmaRxChannel::from(self)) - } -} - #[doc(hidden)] pub struct I2sDmaTxChannelImpl(C); impl crate::private::Sealed for I2sDmaTxChannelImpl {} -impl I2sDmaTxChannelImpl -where - AnyPdmaTxChannel: From, -{ - fn degrade(self) -> AnyPdmaTxChannelImpl { - AnyPdmaTxChannelImpl(AnyPdmaTxChannel::from(self)) - } -} - impl> RegisterAccess for I2sDmaTxChannelImpl { fn set_burst_mode(&self, burst_mode: bool) { let reg_block = self.0.register_block(); @@ -790,14 +746,6 @@ macro_rules! ImplI2sChannel { type Tx = I2sDmaTxChannelImpl; } - impl DmaChannelConvert for [] { - fn degrade_rx(rx: Self::Rx) -> AnyPdmaRxChannelImpl { - rx.degrade() - } - fn degrade_tx(tx: Self::Tx) -> AnyPdmaTxChannelImpl { - tx.degrade() - } - } impl PeripheralDmaChannel for [] { type P = crate::peripherals::[]; } @@ -944,167 +892,6 @@ impl<'d> Dma<'d> { } } -macro_rules! define_enum { - ( - $(#[$meta:meta])* - $vis:vis enum $ty:ident { - $($(#[$cfg:meta])? - $variant:ident($inner:ty),)* - } - ) => { - $(#[$meta])* - $vis enum $ty { - $( - $(#[$cfg])? - $variant($inner), - )* - } - - $( - $(#[$cfg])? - impl From<$inner> for $ty { - fn from(inner: $inner) -> Self { - Self::$variant(inner) - } - } - )* - } -} - -/// An arbitrary PDMA channel. -// NOTE: this is unused currently (peripherals prescribe a specific channel) but type-erased -// peripherals will require type-erased channels. -#[non_exhaustive] -pub struct AnyPdmaChannel; -impl crate::private::Sealed for AnyPdmaChannel {} - -impl DmaChannel for AnyPdmaChannel { - type Rx = AnyPdmaRxChannelImpl; - type Tx = AnyPdmaTxChannelImpl; -} - -define_enum! { - #[doc(hidden)] - pub enum AnyPdmaRxChannel { - Spi2(SpiDmaRxChannelImpl), - Spi3(SpiDmaRxChannelImpl), - I2s0(I2sDmaRxChannelImpl), - #[cfg(i2s1)] - I2s1(I2sDmaRxChannelImpl), - } -} - -#[doc(hidden)] -pub struct AnyPdmaRxChannelImpl(AnyPdmaRxChannel); - -impl crate::private::Sealed for AnyPdmaRxChannelImpl {} -impl InterruptAccess for AnyPdmaRxChannelImpl { - delegate::delegate! { - to match &self.0 { - AnyPdmaRxChannel::Spi2(channel) => channel, - AnyPdmaRxChannel::Spi3(channel) => channel, - AnyPdmaRxChannel::I2s0(channel) => channel, - #[cfg(i2s1)] - AnyPdmaRxChannel::I2s1(channel) => channel, - } { - fn enable_listen(&self, interrupts: EnumSet, enable: bool); - fn is_listening(&self) -> EnumSet; - fn clear(&self, interrupts: impl Into>); - fn pending_interrupts(&self) -> EnumSet; - fn waker(&self) -> &'static AtomicWaker; - } - } -} -impl RegisterAccess for AnyPdmaRxChannelImpl { - delegate::delegate! { - to match &self.0 { - AnyPdmaRxChannel::Spi2(channel) => channel, - AnyPdmaRxChannel::Spi3(channel) => channel, - AnyPdmaRxChannel::I2s0(channel) => channel, - #[cfg(i2s1)] - AnyPdmaRxChannel::I2s1(channel) => channel, - } { - fn set_burst_mode(&self, burst_mode: bool); - fn set_priority(&self, priority: DmaPriority); - fn reset(&self); - fn set_link_addr(&self, address: u32); - fn set_peripheral(&self, peripheral: u8); - fn start(&self); - fn stop(&self); - fn restart(&self); - fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool; - } - } -} -impl RxRegisterAccess for AnyPdmaRxChannelImpl {} - -define_enum! { - #[doc(hidden)] - pub enum AnyPdmaTxChannel { - Spi2(SpiDmaTxChannelImpl), - Spi3(SpiDmaTxChannelImpl), - I2s0(I2sDmaTxChannelImpl), - #[cfg(i2s1)] - I2s1(I2sDmaTxChannelImpl), - } -} - -#[doc(hidden)] -pub struct AnyPdmaTxChannelImpl(AnyPdmaTxChannel); - -impl crate::private::Sealed for AnyPdmaTxChannelImpl {} -impl InterruptAccess for AnyPdmaTxChannelImpl { - delegate::delegate! { - to match &self.0 { - AnyPdmaTxChannel::Spi2(channel) => channel, - AnyPdmaTxChannel::Spi3(channel) => channel, - AnyPdmaTxChannel::I2s0(channel) => channel, - #[cfg(i2s1)] - AnyPdmaTxChannel::I2s1(channel) => channel, - } { - fn enable_listen(&self, interrupts: EnumSet, enable: bool); - fn is_listening(&self) -> EnumSet; - fn clear(&self, interrupts: impl Into>); - fn pending_interrupts(&self) -> EnumSet; - fn waker(&self) -> &'static AtomicWaker; - } - } -} -impl RegisterAccess for AnyPdmaTxChannelImpl { - delegate::delegate! { - to match &self.0 { - AnyPdmaTxChannel::Spi2(channel) => channel, - AnyPdmaTxChannel::Spi3(channel) => channel, - AnyPdmaTxChannel::I2s0(channel) => channel, - #[cfg(i2s1)] - AnyPdmaTxChannel::I2s1(channel) => channel, - } { - fn set_burst_mode(&self, burst_mode: bool); - fn set_priority(&self, priority: DmaPriority); - fn reset(&self); - fn set_link_addr(&self, address: u32); - fn set_peripheral(&self, peripheral: u8); - fn start(&self); - fn stop(&self); - fn restart(&self); - fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool; - } - } -} -impl TxRegisterAccess for AnyPdmaTxChannelImpl { - delegate::delegate! { - to match &self.0 { - AnyPdmaTxChannel::Spi2(channel) => channel, - AnyPdmaTxChannel::Spi3(channel) => channel, - AnyPdmaTxChannel::I2s0(channel) => channel, - #[cfg(i2s1)] - AnyPdmaTxChannel::I2s1(channel) => channel, - } { - fn last_dscr_address(&self) -> usize; - } - } -} - impl<'d, C, M: Mode> Channel<'d, C, M> where C: DmaChannel, From 20fa92d78c1563ec362584af3f8ce4608c9d0720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 8 Oct 2024 08:45:14 +0200 Subject: [PATCH 35/36] Remove PeripheralDmaChannel --- esp-hal/src/dma/mod.rs | 7 ------- esp-hal/src/dma/pdma.rs | 8 -------- 2 files changed, 15 deletions(-) diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 02c6257f756..af7f79667cd 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1524,13 +1524,6 @@ pub trait DmaChannel: crate::private::Sealed { type Tx: TxRegisterAccess + InterruptAccess; } -/// A description of a DMA Channel that can be used with a peripheral. -#[cfg(pdma)] -pub trait PeripheralDmaChannel: DmaChannel { - /// A suitable peripheral for this DMA channel. - type P: PeripheralMarker; -} - #[doc(hidden)] pub trait DmaChannelExt: DmaChannel { fn get_rx_interrupts() -> impl InterruptAccess; diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 1a238dbea46..6399826e30e 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -329,10 +329,6 @@ macro_rules! ImplSpiChannel { type Tx = SpiDmaTxChannelImpl; } - impl PeripheralDmaChannel for [] { - type P = crate::peripherals::[]; - } - impl DmaChannelExt for [] { fn get_rx_interrupts() -> impl InterruptAccess { SpiDmaRxChannelImpl(Self {}) @@ -746,10 +742,6 @@ macro_rules! ImplI2sChannel { type Tx = I2sDmaTxChannelImpl; } - impl PeripheralDmaChannel for [] { - type P = crate::peripherals::[]; - } - impl DmaChannelExt for [] { fn get_rx_interrupts() -> impl InterruptAccess { I2sDmaRxChannelImpl(Self {}) From 7058e6740b8b7d489401857ea7154838c80ca78e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 8 Oct 2024 12:48:09 +0200 Subject: [PATCH 36/36] Remove unnecessary degrade call --- hil-test/tests/qspi.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hil-test/tests/qspi.rs b/hil-test/tests/qspi.rs index ac60df1a421..d1ec44dcebb 100644 --- a/hil-test/tests/qspi.rs +++ b/hil-test/tests/qspi.rs @@ -205,9 +205,7 @@ mod tests { } } - let dma_channel = dma_channel - .configure(false, DmaPriority::Priority0) - .degrade(); + let dma_channel = dma_channel.configure(false, DmaPriority::Priority0); Context { spi: peripherals.SPI2,