diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 90ea7f5edb3..77aab858e03 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 - `I2c` SCL timeout is now defined in bus clock cycles. (#2477) - Trying to send a single-shot RMT transmission will result in an error now, `RMT` deals with `u32` now, `PulseCode` is a convenience trait now (#2463) - Removed `get_` prefixes from functions (#2528) +- The `Camera` and `I8080` drivers' constructors now only accepts blocking-mode DMA channels. (#2519) ### Fixed @@ -180,6 +181,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The DMA channel types have been removed from peripherals (#2261) - `I2C` driver renamed to `I2c` (#2320) - The GPIO pins are now accessible via `Peripherals` and are no longer part of the `Io` struct (#2508) +- `dma::{ChannelRx, ChannelTx}` now have a `Mode` type parameter (#2519) ### Fixed diff --git a/esp-hal/MIGRATING-0.21.md b/esp-hal/MIGRATING-0.21.md index 6211533dba6..c6cb5fa5f0e 100644 --- a/esp-hal/MIGRATING-0.21.md +++ b/esp-hal/MIGRATING-0.21.md @@ -276,7 +276,9 @@ For example: } ``` -## Circular DMA transfer's `available` returns `Result` now +## DMA related changes + +### Circular DMA transfer's `available` returns `Result` now In case of any error you should drop the transfer and restart it. @@ -293,6 +295,22 @@ In case of any error you should drop the transfer and restart it. + }; ``` +### Channel, ChannelRx and ChannelTx types have changed + +- `Channel`'s `Async`/`Blocking` mode has been moved before the channel instance parameter. +- `ChannelRx` and `ChannelTx` have gained a new `Async`/`Blocking` mode parameter. + +```diff +-Channel<'d, DmaChannel0, Async> ++Channel<'d, Async, DmaChannel0> + +-ChannelRx<'d, DmaChannel0> ++ChannelRx<'d, Async, DmaChannel0> + +-ChannelTx<'d, DmaChannel0> ++ChannelTx<'d, Async, DmaChannel0> +``` + ## Removed `peripheral_input` and `into_peripheral_output` from GPIO pin types Creating peripheral interconnect signals now consume the GPIO pin used for the connection. @@ -357,7 +375,9 @@ refer to the `Config` struct as `uart::Config`. +) ``` -## I8080 driver split `set_byte_order()` into `set_8bits_order()` and `set_byte_order()`. +## LCD_CAM changes + +### I8080 driver split `set_byte_order()` into `set_8bits_order()` and `set_byte_order()`. If you were using an 8-bit bus. @@ -371,6 +391,29 @@ If you were using an 16-bit bus, you don't need to change anything, `set_byte_or If you were sharing the bus between an 8-bit and 16-bit device, you will have to call the corresponding method when you switch between devices. Be sure to read the documentation of the new methods. +### Mixed mode constructors + +It is no longer possible to construct `I8080` or `Camera` with an async-mode DMA channel. +Convert the DMA channel into blocking before passing it to these constructors. + +```diff + let lcd_cam = LcdCam::new(peripherals.LCD_CAM); + let channel = ctx + .dma + .channel0 +- .configure(false, DmaPriority::Priority0) +- .into_async(); ++ .configure(false, DmaPriority::Priority0); + + let i8080 = I8080::new( + lcd_cam.lcd, + channel.tx, + pins, + 20.MHz(), + Config::default(), + ); +``` + ## `rmt::Channel::transmit` now returns `Result`, `PulseCode` is now `u32` When trying to send a one-shot transmission will fail if it doesn't end with an end-marker. diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index e6815b8877b..34a14f03ce9 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -276,21 +276,21 @@ pub mod dma { /// The underlying [`Aes`](super::Aes) driver pub aes: super::Aes<'d>, - channel: Channel<'d, ::Dma, Blocking>, + channel: Channel<'d, Blocking, ::Dma>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, } impl<'d> crate::aes::Aes<'d> { /// Enable DMA for the current instance of the AES driver - pub fn with_dma( + pub fn with_dma( self, - channel: Channel<'d, C, Blocking>, + channel: Channel<'d, Blocking, CH>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> AesDma<'d> where - C: DmaChannelConvert<::Dma>, + CH: DmaChannelConvert<::Dma>, { AesDma { aes: self, @@ -324,7 +324,7 @@ pub mod dma { } impl<'d> DmaSupportTx for AesDma<'d> { - type TX = ChannelTx<'d, ::Dma>; + type TX = ChannelTx<'d, Blocking, ::Dma>; fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx @@ -336,7 +336,7 @@ pub mod dma { } impl<'d> DmaSupportRx for AesDma<'d> { - type RX = ChannelRx<'d, ::Dma>; + type RX = ChannelRx<'d, Blocking, ::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 8ac8b6b4731..21459966429 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -25,48 +25,78 @@ use crate::{ #[doc(hidden)] pub trait GdmaChannel { fn number(&self) -> u8; -} -/// An arbitrary GDMA channel -#[non_exhaustive] -pub struct AnyGdmaChannel(u8); + fn async_handler_out(&self) -> Option { + match self.number() { + 0 => DmaChannel0::handler_out(), + #[cfg(not(esp32c2))] + 1 => DmaChannel1::handler_out(), + #[cfg(not(esp32c2))] + 2 => DmaChannel2::handler_out(), + #[cfg(esp32s3)] + 3 => DmaChannel3::handler_out(), + #[cfg(esp32s3)] + 4 => DmaChannel4::handler_out(), + _ => unreachable!(), + } + } -impl crate::private::Sealed for AnyGdmaChannel {} -impl DmaChannel for AnyGdmaChannel { - type Rx = ChannelRxImpl; - type Tx = ChannelTxImpl; + fn peripheral_interrupt_out(&self) -> Option { + match self.number() { + 0 => DmaChannel0::isr_out(), + #[cfg(not(esp32c2))] + 1 => DmaChannel1::isr_out(), + #[cfg(not(esp32c2))] + 2 => DmaChannel2::isr_out(), + #[cfg(esp32s3)] + 3 => DmaChannel3::isr_out(), + #[cfg(esp32s3)] + 4 => DmaChannel4::isr_out(), + _ => unreachable!(), + } + } - fn async_handler(ch: &Channel<'_, Self, M>) -> InterruptHandler { - match ch.tx.tx_impl.0.number() { - 0 => DmaChannel0::handler(), + fn async_handler_in(&self) -> Option { + match self.number() { + 0 => DmaChannel0::handler_in(), #[cfg(not(esp32c2))] - 1 => DmaChannel1::handler(), + 1 => DmaChannel1::handler_in(), #[cfg(not(esp32c2))] - 2 => DmaChannel2::handler(), + 2 => DmaChannel2::handler_in(), #[cfg(esp32s3)] - 3 => DmaChannel3::handler(), + 3 => DmaChannel3::handler_in(), #[cfg(esp32s3)] - 4 => DmaChannel4::handler(), + 4 => DmaChannel4::handler_in(), _ => unreachable!(), } } - fn interrupts(ch: &Channel<'_, Self, M>) -> &'static [Interrupt] { - match ch.tx.tx_impl.0.number() { - 0 => DmaChannel0::isrs(), + fn peripheral_interrupt_in(&self) -> Option { + match self.number() { + 0 => DmaChannel0::isr_in(), #[cfg(not(esp32c2))] - 1 => DmaChannel1::isrs(), + 1 => DmaChannel1::isr_in(), #[cfg(not(esp32c2))] - 2 => DmaChannel2::isrs(), + 2 => DmaChannel2::isr_in(), #[cfg(esp32s3)] - 3 => DmaChannel3::isrs(), + 3 => DmaChannel3::isr_in(), #[cfg(esp32s3)] - 4 => DmaChannel4::isrs(), + 4 => DmaChannel4::isr_in(), _ => unreachable!(), } } } +/// An arbitrary GDMA channel +#[non_exhaustive] +pub struct AnyGdmaChannel(u8); + +impl crate::private::Sealed for AnyGdmaChannel {} +impl DmaChannel for AnyGdmaChannel { + type Rx = ChannelRxImpl; + type Tx = ChannelTxImpl; +} + #[non_exhaustive] #[doc(hidden)] pub struct SpecificGdmaChannel {} @@ -202,6 +232,14 @@ impl TxRegisterAccess for ChannelTxImpl { .out_eof_des_addr() .bits() as _ } + + fn async_handler(&self) -> Option { + self.0.async_handler_out() + } + + fn peripheral_interrupt(&self) -> Option { + self.0.peripheral_interrupt_out() + } } impl InterruptAccess for ChannelTxImpl { @@ -385,6 +423,14 @@ impl RxRegisterAccess for ChannelRxImpl { .in_conf0() .modify(|_, w| w.mem_trans_en().bit(value)); } + + fn async_handler(&self) -> Option { + self.0.async_handler_in() + } + + fn peripheral_interrupt(&self) -> Option { + self.0.peripheral_interrupt_in() + } } impl InterruptAccess for ChannelRxImpl { @@ -473,7 +519,7 @@ impl InterruptAccess for ChannelRxImpl { #[non_exhaustive] pub struct ChannelCreator {} -impl Channel<'_, CH, M> { +impl Channel<'_, M, CH> { /// Asserts that the channel is compatible with the given peripheral. pub fn runtime_ensure_compatible(&self, _peripheral: &PeripheralRef<'_, P>) { // No runtime checks; GDMA channels are compatible with any peripheral @@ -481,7 +527,7 @@ impl Channel<'_, CH, M> { } macro_rules! impl_channel { - ($num: literal, $async_handler: path, $($interrupt: ident),* ) => { + ($num:literal, $interrupt_in:ident, $async_handler:path $(, $interrupt_out:ident , $async_handler_out:path)? ) => { paste::paste! { /// A description of a specific GDMA channel #[non_exhaustive] @@ -490,26 +536,26 @@ macro_rules! impl_channel { impl crate::private::Sealed for [] {} impl [] { - fn handler() -> InterruptHandler { - $async_handler + fn handler_in() -> Option { + Some($async_handler) + } + + fn isr_in() -> Option { + Some(Interrupt::$interrupt_in) + } + + fn handler_out() -> Option { + $crate::if_set! { $(Some($async_handler_out))?, None } } - fn isrs() -> &'static [Interrupt] { - &[$(Interrupt::$interrupt),*] + fn isr_out() -> Option { + $crate::if_set! { $(Some(Interrupt::$interrupt_out))?, None } } } impl DmaChannel for [] { type Rx = ChannelRxImpl>; type Tx = ChannelTxImpl>; - - fn async_handler(_ch: &Channel<'_, Self, M>) -> InterruptHandler { - Self::handler() - } - - fn interrupts(_ch: &Channel<'_, Self, M>,) -> &'static [Interrupt] { - Self::isrs() - } } impl DmaChannelConvert for [] { @@ -537,11 +583,10 @@ macro_rules! impl_channel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, [], Blocking> { + ) -> Channel<'a, Blocking, []> { let mut this = Channel { tx: ChannelTx::new(ChannelTxImpl(SpecificGdmaChannel::<$num> {})), rx: ChannelRx::new(ChannelRxImpl(SpecificGdmaChannel::<$num> {})), - phantom: PhantomData, }; this.configure(burst_mode, priority); @@ -553,27 +598,29 @@ macro_rules! impl_channel { }; } +use super::asynch::interrupt as asynch_handler; + cfg_if::cfg_if! { if #[cfg(esp32c2)] { const CHANNEL_COUNT: usize = 1; - impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_CH0); + impl_channel!(0, DMA_CH0, asynch_handler::interrupt_handler_ch0); } else if #[cfg(esp32c3)] { const CHANNEL_COUNT: usize = 3; - impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_CH0); - impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_CH1); - impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_CH2); + impl_channel!(0, DMA_CH0, asynch_handler::interrupt_handler_ch0); + impl_channel!(1, DMA_CH1, asynch_handler::interrupt_handler_ch1); + impl_channel!(2, DMA_CH2, asynch_handler::interrupt_handler_ch2); } else if #[cfg(any(esp32c6, esp32h2))] { const CHANNEL_COUNT: usize = 3; - impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_IN_CH0, DMA_OUT_CH0); - impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_IN_CH1, DMA_OUT_CH1); - impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_IN_CH2, DMA_OUT_CH2); + impl_channel!(0, DMA_IN_CH0, asynch_handler::interrupt_handler_ch0, DMA_OUT_CH0, asynch_handler::interrupt_handler_ch0); + impl_channel!(1, DMA_IN_CH1, asynch_handler::interrupt_handler_ch1, DMA_OUT_CH1, asynch_handler::interrupt_handler_ch1); + impl_channel!(2, DMA_IN_CH2, asynch_handler::interrupt_handler_ch2, DMA_OUT_CH2, asynch_handler::interrupt_handler_ch2); } else if #[cfg(esp32s3)] { const CHANNEL_COUNT: usize = 5; - impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_IN_CH0, DMA_OUT_CH0); - impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_IN_CH1, DMA_OUT_CH1); - impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_IN_CH2, DMA_OUT_CH2); - impl_channel!(3, super::asynch::interrupt::interrupt_handler_ch3, DMA_IN_CH3, DMA_OUT_CH3); - impl_channel!(4, super::asynch::interrupt::interrupt_handler_ch4, DMA_IN_CH4, DMA_OUT_CH4); + impl_channel!(0, DMA_IN_CH0, asynch_handler::interrupt_handler_ch0, DMA_OUT_CH0, asynch_handler::interrupt_handler_ch0); + impl_channel!(1, DMA_IN_CH1, asynch_handler::interrupt_handler_ch1, DMA_OUT_CH1, asynch_handler::interrupt_handler_ch1); + impl_channel!(2, DMA_IN_CH2, asynch_handler::interrupt_handler_ch2, DMA_OUT_CH2, asynch_handler::interrupt_handler_ch2); + impl_channel!(3, DMA_IN_CH3, asynch_handler::interrupt_handler_ch3, DMA_OUT_CH3, asynch_handler::interrupt_handler_ch3); + impl_channel!(4, DMA_IN_CH4, asynch_handler::interrupt_handler_ch4, DMA_OUT_CH4, asynch_handler::interrupt_handler_ch4); } } diff --git a/esp-hal/src/dma/m2m.rs b/esp-hal/src/dma/m2m.rs index b1ff0f60bc5..0b2009950eb 100644 --- a/esp-hal/src/dma/m2m.rs +++ b/esp-hal/src/dma/m2m.rs @@ -32,7 +32,7 @@ pub struct Mem2Mem<'d, M> where M: Mode, { - channel: Channel<'d, AnyGdmaChannel, M>, + channel: Channel<'d, M, AnyGdmaChannel>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, peripheral: DmaPeripheral, @@ -41,7 +41,7 @@ where impl<'d> Mem2Mem<'d, Blocking> { /// Create a new Mem2Mem instance. pub fn new( - channel: Channel<'d, CH, DM>, + channel: Channel<'d, DM, CH>, peripheral: impl DmaEligible, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], @@ -49,7 +49,7 @@ impl<'d> Mem2Mem<'d, Blocking> { where CH: DmaChannelConvert, DM: Mode, - Channel<'d, CH, Blocking>: From>, + Channel<'d, Blocking, CH>: From>, { unsafe { Self::new_unsafe( @@ -64,7 +64,7 @@ impl<'d> Mem2Mem<'d, Blocking> { /// Create a new Mem2Mem instance with specific chunk size. pub fn new_with_chunk_size( - channel: Channel<'d, CH, DM>, + channel: Channel<'d, DM, CH>, peripheral: impl DmaEligible, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], @@ -73,7 +73,7 @@ impl<'d> Mem2Mem<'d, Blocking> { where CH: DmaChannelConvert, DM: Mode, - Channel<'d, CH, Blocking>: From>, + Channel<'d, Blocking, CH>: From>, { unsafe { Self::new_unsafe( @@ -93,7 +93,7 @@ impl<'d> Mem2Mem<'d, Blocking> { /// 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, DM>, + channel: Channel<'d, DM, CH>, peripheral: DmaPeripheral, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], @@ -102,7 +102,7 @@ impl<'d> Mem2Mem<'d, Blocking> { where CH: DmaChannelConvert, DM: Mode, - Channel<'d, CH, Blocking>: From>, + Channel<'d, Blocking, CH>: From>, { if !(1..=4092).contains(&chunk_size) { return Err(DmaError::InvalidChunkSize); @@ -111,7 +111,7 @@ impl<'d> Mem2Mem<'d, Blocking> { return Err(DmaError::OutOfDescriptors); } Ok(Mem2Mem { - channel: Channel::<_, Blocking>::from(channel).degrade(), + channel: Channel::::from(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), @@ -190,11 +190,11 @@ where } } -impl<'d, MODE> DmaSupportRx for Mem2Mem<'d, MODE> +impl<'d, M> DmaSupportRx for Mem2Mem<'d, M> where - MODE: Mode, + M: Mode, { - type RX = ChannelRx<'d, AnyGdmaChannel>; + type RX = ChannelRx<'d, M, 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 6deca41d657..e5bee324491 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -1571,12 +1571,6 @@ pub trait DmaChannel: crate::private::Sealed + Sized { /// A description of the TX half of a DMA Channel. type Tx: TxRegisterAccess + InterruptAccess; - - /// Returns the async interrupt handler. - fn async_handler(ch: &Channel<'_, Self, M>) -> InterruptHandler; - - /// Returns the interrupt. - fn interrupts(ch: &Channel<'_, Self, M>) -> &'static [Interrupt]; } #[doc(hidden)] @@ -1666,16 +1660,16 @@ pub trait Rx: crate::private::Sealed { // DMA receive channel #[non_exhaustive] #[doc(hidden)] -pub struct ChannelRx<'a, CH> +pub struct ChannelRx<'a, M, CH> where CH: DmaChannel, { pub(crate) burst_mode: bool, pub(crate) rx_impl: CH::Rx, - pub(crate) _phantom: PhantomData<(&'a (), CH)>, + pub(crate) _phantom: PhantomData<(&'a (), CH, M)>, } -impl<'a, CH> ChannelRx<'a, CH> +impl<'a, CH> ChannelRx<'a, Blocking, CH> where CH: DmaChannel, { @@ -1692,9 +1686,60 @@ where } } + /// Converts a blocking channel to an async channel. + pub(crate) fn into_async(mut self) -> ChannelRx<'a, Async, CH> { + if let Some(handler) = self.rx_impl.async_handler() { + self.set_interrupt_handler(handler); + } + ChannelRx { + burst_mode: self.burst_mode, + rx_impl: self.rx_impl, + _phantom: PhantomData, + } + } + + fn set_interrupt_handler(&mut self, handler: InterruptHandler) + where + CH: DmaChannel, + { + self.unlisten_in(EnumSet::all()); + self.clear_in(EnumSet::all()); + + if let Some(interrupt) = self.rx_impl.peripheral_interrupt() { + for core in crate::Cpu::other() { + crate::interrupt::disable(core, interrupt); + } + unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) }; + unwrap!(crate::interrupt::enable(interrupt, handler.priority())); + } + } +} + +impl<'a, CH> ChannelRx<'a, Async, CH> +where + CH: DmaChannel, +{ + /// Converts an async channel into a blocking channel. + pub(crate) fn into_blocking(self) -> ChannelRx<'a, Blocking, CH> { + if let Some(interrupt) = self.rx_impl.peripheral_interrupt() { + crate::interrupt::disable(Cpu::current(), interrupt); + } + ChannelRx { + burst_mode: self.burst_mode, + rx_impl: self.rx_impl, + _phantom: PhantomData, + } + } +} + +impl<'a, M, CH> ChannelRx<'a, M, CH> +where + M: Mode, + CH: DmaChannel, +{ /// Return a less specific (degraded) version of this channel. #[doc(hidden)] - pub fn degrade(self) -> ChannelRx<'a, DEG> + pub fn degrade(self) -> ChannelRx<'a, M, DEG> where CH: DmaChannelConvert, { @@ -1712,10 +1757,16 @@ where } } -impl crate::private::Sealed for ChannelRx<'_, CH> where CH: DmaChannel {} +impl crate::private::Sealed for ChannelRx<'_, M, CH> +where + M: Mode, + CH: DmaChannel, +{ +} -impl Rx for ChannelRx<'_, CH> +impl Rx for ChannelRx<'_, M, CH> where + M: Mode, CH: DmaChannel, { unsafe fn prepare_transfer_without_start( @@ -1894,17 +1945,17 @@ pub trait Tx: crate::private::Sealed { /// DMA transmit channel #[doc(hidden)] -pub struct ChannelTx<'a, CH> +pub struct ChannelTx<'a, M, CH> where CH: DmaChannel, { #[allow(unused)] pub(crate) burst_mode: bool, pub(crate) tx_impl: CH::Tx, - pub(crate) _phantom: PhantomData<(&'a (), CH)>, + pub(crate) _phantom: PhantomData<(&'a (), CH, M)>, } -impl<'a, CH> ChannelTx<'a, CH> +impl<'a, CH> ChannelTx<'a, Blocking, CH> where CH: DmaChannel, { @@ -1916,9 +1967,60 @@ where } } + /// Converts a blocking channel to an async channel. + pub(crate) fn into_async(mut self) -> ChannelTx<'a, Async, CH> { + if let Some(handler) = self.tx_impl.async_handler() { + self.set_interrupt_handler(handler); + } + ChannelTx { + burst_mode: self.burst_mode, + tx_impl: self.tx_impl, + _phantom: PhantomData, + } + } + + fn set_interrupt_handler(&mut self, handler: InterruptHandler) + where + CH: DmaChannel, + { + self.unlisten_out(EnumSet::all()); + self.clear_out(EnumSet::all()); + + if let Some(interrupt) = self.tx_impl.peripheral_interrupt() { + for core in crate::Cpu::other() { + crate::interrupt::disable(core, interrupt); + } + unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) }; + unwrap!(crate::interrupt::enable(interrupt, handler.priority())); + } + } +} + +impl<'a, CH> ChannelTx<'a, Async, CH> +where + CH: DmaChannel, +{ + /// Converts an async channel into a blocking channel. + pub(crate) fn into_blocking(self) -> ChannelTx<'a, Blocking, CH> { + if let Some(interrupt) = self.tx_impl.peripheral_interrupt() { + crate::interrupt::disable(Cpu::current(), interrupt); + } + ChannelTx { + burst_mode: self.burst_mode, + tx_impl: self.tx_impl, + _phantom: PhantomData, + } + } +} + +impl<'a, M, CH> ChannelTx<'a, M, CH> +where + M: Mode, + CH: DmaChannel, +{ /// Return a less specific (degraded) version of this channel. #[doc(hidden)] - pub fn degrade(self) -> ChannelTx<'a, DEG> + pub fn degrade(self) -> ChannelTx<'a, M, DEG> where CH: DmaChannelConvert, { @@ -1936,10 +2038,16 @@ where } } -impl crate::private::Sealed for ChannelTx<'_, CH> where CH: DmaChannel {} +impl crate::private::Sealed for ChannelTx<'_, M, CH> +where + M: Mode, + CH: DmaChannel, +{ +} -impl Tx for ChannelTx<'_, CH> +impl Tx for ChannelTx<'_, M, CH> where + M: Mode, CH: DmaChannel, { unsafe fn prepare_transfer_without_start( @@ -2116,6 +2224,9 @@ pub trait RegisterAccess: crate::private::Sealed { pub trait RxRegisterAccess: RegisterAccess { #[cfg(gdma)] fn set_mem2mem_mode(&self, value: bool); + + fn peripheral_interrupt(&self) -> Option; + fn async_handler(&self) -> Option; } #[doc(hidden)] @@ -2125,6 +2236,9 @@ pub trait TxRegisterAccess: RegisterAccess { /// Outlink descriptor address when EOF occurs of Tx channel. fn last_dscr_address(&self) -> usize; + + fn peripheral_interrupt(&self) -> Option; + fn async_handler(&self) -> Option; } #[doc(hidden)] @@ -2148,38 +2262,30 @@ pub trait InterruptAccess: crate::private::Sealed { } /// DMA Channel -pub struct Channel<'d, CH, M> +pub struct Channel<'d, M, CH> where - CH: DmaChannel, M: Mode, + CH: DmaChannel, { /// RX half of the channel - pub rx: ChannelRx<'d, CH>, + pub rx: ChannelRx<'d, M, CH>, /// TX half of the channel - pub tx: ChannelTx<'d, CH>, - pub(crate) phantom: PhantomData, + pub tx: ChannelTx<'d, M, CH>, } -impl<'d, C> Channel<'d, C, Blocking> +impl<'d, CH> Channel<'d, Blocking, CH> where - C: DmaChannel, + CH: DmaChannel, { /// Sets the interrupt handler for RX and TX interrupts. /// /// Interrupts are not enabled at the peripheral level here. pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) where - C: DmaChannel, + CH: DmaChannel, { - self.unlisten(EnumSet::all()); - self.clear_interrupts(EnumSet::all()); - for interrupt in C::interrupts(self).iter().copied() { - for core in crate::Cpu::other() { - crate::interrupt::disable(core, interrupt); - } - unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) }; - unwrap!(crate::interrupt::enable(interrupt, handler.priority())); - } + self.rx.set_interrupt_handler(handler); + self.tx.set_interrupt_handler(handler); } /// Listen for the given interrupts @@ -2226,67 +2332,59 @@ where /// Configure the channel. pub fn configure(&mut self, burst_mode: bool, priority: DmaPriority) { - self.tx.configure(burst_mode, priority); self.rx.configure(burst_mode, priority); + self.tx.configure(burst_mode, priority); } /// Converts a blocking channel to an async channel. - pub fn into_async(mut self) -> Channel<'d, C, Async> { - self.set_interrupt_handler(C::async_handler(&self)); - + pub fn into_async(self) -> Channel<'d, Async, CH> { Channel { - tx: self.tx, - rx: self.rx, - phantom: PhantomData, + rx: self.rx.into_async(), + tx: self.tx.into_async(), } } } -impl<'d, C> Channel<'d, C, Async> +impl<'d, CH> Channel<'d, Async, CH> where - C: DmaChannel, + CH: DmaChannel, { /// Converts an async channel to a blocking channel. - pub fn into_blocking(self) -> Channel<'d, C, Blocking> { - for interrupt in C::interrupts(&self).iter().copied() { - crate::interrupt::disable(Cpu::current(), interrupt); - } - + pub fn into_blocking(self) -> Channel<'d, Blocking, CH> { Channel { - tx: self.tx, - rx: self.rx, - phantom: PhantomData, + rx: self.rx.into_blocking(), + tx: self.tx.into_blocking(), } } } -impl<'d, C: DmaChannel> From> for Channel<'d, C, Async> { - fn from(channel: Channel<'d, C, Blocking>) -> Self { +impl<'d, CH: DmaChannel> From> for Channel<'d, Async, CH> { + fn from(channel: Channel<'d, Blocking, CH>) -> Self { channel.into_async() } } -impl<'d, C: DmaChannel> From> for Channel<'d, C, Blocking> { - fn from(channel: Channel<'d, C, Async>) -> Self { +impl<'d, CH: DmaChannel> From> for Channel<'d, Blocking, CH> { + fn from(channel: Channel<'d, Async, CH>) -> Self { channel.into_blocking() } } -impl<'d, CH, M: Mode> Channel<'d, CH, M> +impl<'d, M, CH> Channel<'d, M, CH> where + M: Mode, CH: DmaChannel, { /// Return a less specific (degraded) version of this channel (both rx and /// tx). #[doc(hidden)] - pub fn degrade(self) -> Channel<'d, DEG, M> + pub fn degrade(self) -> Channel<'d, M, DEG> where CH: DmaChannelConvert, { Channel { rx: self.rx.degrade(), tx: self.tx.degrade(), - phantom: PhantomData, } } } diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index bfbaee48dfc..776ea57fd07 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -32,6 +32,9 @@ pub trait PdmaChannel: crate::private::Sealed { fn tx_waker(&self) -> &'static AtomicWaker; fn rx_waker(&self) -> &'static AtomicWaker; fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool; + + fn peripheral_interrupt(&self) -> Interrupt; + fn async_handler(&self) -> InterruptHandler; } #[doc(hidden)] @@ -107,6 +110,14 @@ impl> TxRegisterAccess for SpiD let spi = self.0.register_block(); spi.out_eof_des_addr().read().dma_out_eof_des_addr().bits() as usize } + + fn peripheral_interrupt(&self) -> Option { + None + } + + fn async_handler(&self) -> Option { + None + } } impl> InterruptAccess @@ -241,7 +252,15 @@ impl> RegisterAccess for SpiDma } } -impl> RxRegisterAccess for SpiDmaRxChannelImpl {} +impl> RxRegisterAccess for SpiDmaRxChannelImpl { + fn peripheral_interrupt(&self) -> Option { + Some(self.0.peripheral_interrupt()) + } + + fn async_handler(&self) -> Option { + Some(self.0.async_handler()) + } +} impl> InterruptAccess for SpiDmaRxChannelImpl @@ -343,27 +362,9 @@ macro_rules! ImplSpiChannel { #[non_exhaustive] pub struct [] {} - impl [] { - fn handler() -> InterruptHandler { - super::asynch::interrupt::[< interrupt_handler_spi $num _dma >] - } - - fn isrs() -> &'static [Interrupt] { - &[Interrupt::[< SPI $num _DMA >]] - } - } - impl DmaChannel for [] { type Rx = SpiDmaRxChannelImpl; type Tx = SpiDmaTxChannelImpl; - - fn async_handler(_ch: &Channel<'_, Self, M>) -> InterruptHandler { - Self::handler() - } - - fn interrupts(_ch: &Channel<'_, Self, M>) -> &'static [Interrupt] { - Self::isrs() - } } impl DmaChannelExt for [] { @@ -393,6 +394,14 @@ macro_rules! ImplSpiChannel { fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool { peripheral == DmaPeripheral::[] } + + fn peripheral_interrupt(&self) -> Interrupt { + Interrupt::[< SPI $num _DMA >] + } + + fn async_handler(&self) -> InterruptHandler { + super::asynch::interrupt::[< interrupt_handler_spi $num _dma >] + } } impl DmaChannelConvert for [] { @@ -416,11 +425,10 @@ macro_rules! ImplSpiChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, [], Blocking> { + ) -> Channel<'a, Blocking, []> { let mut this = Channel { tx: ChannelTx::new(SpiDmaTxChannelImpl([] {})), rx: ChannelRx::new(SpiDmaRxChannelImpl([] {})), - phantom: PhantomData, }; this.configure(burst_mode, priority); @@ -518,6 +526,14 @@ impl> TxRegisterAccess for I2sD .out_eof_des_addr() .bits() as usize } + + fn peripheral_interrupt(&self) -> Option { + None + } + + fn async_handler(&self) -> Option { + None + } } impl> InterruptAccess @@ -658,7 +674,15 @@ impl> RegisterAccess for I2sDma } } -impl> RxRegisterAccess for I2sDmaRxChannelImpl {} +impl> RxRegisterAccess for I2sDmaRxChannelImpl { + fn peripheral_interrupt(&self) -> Option { + Some(self.0.peripheral_interrupt()) + } + + fn async_handler(&self) -> Option { + Some(self.0.async_handler()) + } +} impl> InterruptAccess for I2sDmaRxChannelImpl @@ -756,27 +780,9 @@ macro_rules! ImplI2sChannel { impl $crate::private::Sealed for [] {} - impl [] { - fn handler() -> InterruptHandler { - super::asynch::interrupt::[< interrupt_handler_i2s $num _dma >] - } - - fn isrs() -> &'static [Interrupt] { - &[Interrupt::[< I2S $num >]] - } - } - impl DmaChannel for [] { type Rx = I2sDmaRxChannelImpl; type Tx = I2sDmaTxChannelImpl; - - fn async_handler(_ch: &Channel<'_, Self, M>) -> InterruptHandler { - Self::handler() - } - - fn interrupts(_ch: &Channel<'_, Self, M>) -> &'static [Interrupt] { - Self::isrs() - } } impl DmaChannelExt for [] { @@ -805,6 +811,14 @@ macro_rules! ImplI2sChannel { fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool { peripheral == DmaPeripheral::[] } + + fn peripheral_interrupt(&self) -> Interrupt { + Interrupt::[< I2S $num >] + } + + fn async_handler(&self) -> InterruptHandler { + super::asynch::interrupt::[< interrupt_handler_i2s $num _dma >] + } } impl DmaChannelConvert for [] { @@ -825,11 +839,10 @@ macro_rules! ImplI2sChannel { self, burst_mode: bool, priority: DmaPriority, - ) -> Channel<'a, [], Blocking> { + ) -> Channel<'a, Blocking, []> { let mut this = Channel { tx: ChannelTx::new(I2sDmaTxChannelImpl([] {})), rx: ChannelRx::new(I2sDmaRxChannelImpl([] {})), - phantom: PhantomData, }; this.configure(burst_mode, priority); @@ -904,9 +917,10 @@ impl<'d> Dma<'d> { } } -impl<'d, C, M: Mode> Channel<'d, C, M> +impl<'d, CH, M> Channel<'d, M, CH> where - C: DmaChannel, + CH: DmaChannel, + M: Mode, { /// Asserts that the channel is compatible with the given peripheral. pub fn runtime_ensure_compatible(&self, peripheral: &PeripheralRef<'_, impl DmaEligible>) { @@ -928,20 +942,6 @@ impl crate::private::Sealed for AnySpiDmaChannel {} impl DmaChannel for AnySpiDmaChannel { type Rx = SpiDmaRxChannelImpl; type Tx = SpiDmaTxChannelImpl; - - fn async_handler(ch: &Channel<'_, Self, M>) -> InterruptHandler { - match &ch.tx.tx_impl.0 { - AnySpiDmaChannelInner::Spi2(_) => Spi2DmaChannel::handler(), - AnySpiDmaChannelInner::Spi3(_) => Spi3DmaChannel::handler(), - } - } - - fn interrupts(ch: &Channel<'_, Self, M>) -> &'static [Interrupt] { - match &ch.tx.tx_impl.0 { - AnySpiDmaChannelInner::Spi2(_) => Spi2DmaChannel::isrs(), - AnySpiDmaChannelInner::Spi3(_) => Spi3DmaChannel::isrs(), - } - } } crate::any_enum! { @@ -966,6 +966,8 @@ impl PdmaChannel for AnySpiDmaChannelInner { fn tx_waker(&self) -> &'static AtomicWaker; fn rx_waker(&self) -> &'static AtomicWaker; fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool; + fn peripheral_interrupt(&self) -> Interrupt; + fn async_handler(&self) -> InterruptHandler; } } } @@ -978,22 +980,6 @@ impl crate::private::Sealed for AnyI2sDmaChannel {} impl DmaChannel for AnyI2sDmaChannel { type Rx = I2sDmaRxChannelImpl; type Tx = I2sDmaTxChannelImpl; - - fn async_handler(ch: &Channel<'_, Self, M>) -> InterruptHandler { - match &ch.tx.tx_impl.0 { - AnyI2sDmaChannelInner::I2s0(_) => I2s0DmaChannel::handler(), - #[cfg(i2s1)] - AnyI2sDmaChannelInner::I2s1(_) => I2s1DmaChannel::handler(), - } - } - - fn interrupts(ch: &Channel<'_, Self, M>) -> &'static [Interrupt] { - match &ch.tx.tx_impl.0 { - AnyI2sDmaChannelInner::I2s0(_) => I2s0DmaChannel::isrs(), - #[cfg(i2s1)] - AnyI2sDmaChannelInner::I2s1(_) => I2s1DmaChannel::isrs(), - } - } } crate::any_enum! { @@ -1020,6 +1006,8 @@ impl PdmaChannel for AnyI2sDmaChannelInner { fn tx_waker(&self) -> &'static AtomicWaker; fn rx_waker(&self) -> &'static AtomicWaker; fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool; + fn peripheral_interrupt(&self) -> Interrupt; + fn async_handler(&self) -> InterruptHandler; } } } diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index 1a329590450..98b2d47f708 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -1499,7 +1499,7 @@ pub struct Flex<'d, P = AnyPin> { impl

private::Sealed for Flex<'_, P> {} -impl<'d, P> Peripheral for Flex<'d, P> { +impl

Peripheral for Flex<'_, P> { type P = Self; unsafe fn clone_unchecked(&self) -> Self::P { Self { diff --git a/esp-hal/src/i2c/master/mod.rs b/esp-hal/src/i2c/master/mod.rs index 167a1b855f7..fbbd8729904 100644 --- a/esp-hal/src/i2c/master/mod.rs +++ b/esp-hal/src/i2c/master/mod.rs @@ -816,7 +816,7 @@ where } } -impl<'d, T> embedded_hal_async::i2c::I2c for I2c<'d, Async, T> +impl embedded_hal_async::i2c::I2c for I2c<'_, Async, T> where T: Instance, { diff --git a/esp-hal/src/i2s/master.rs b/esp-hal/src/i2s/master.rs index 95a33d62399..111596ae9ff 100644 --- a/esp-hal/src/i2s/master.rs +++ b/esp-hal/src/i2s/master.rs @@ -74,8 +74,6 @@ //! //! - Only TDM Philips standard is supported. -use core::marker::PhantomData; - use enumset::{EnumSet, EnumSetType}; use private::*; @@ -251,6 +249,7 @@ impl DataFormat { } /// Instance of the I2S peripheral driver +#[non_exhaustive] pub struct I2s<'d, M, T = AnyI2s> where T: RegisterAccess, @@ -260,7 +259,6 @@ where pub i2s_rx: RxCreator<'d, M, T>, /// Handles the transmission (TX) side of the I2S peripheral. pub i2s_tx: TxCreator<'d, M, T>, - phantom: PhantomData, } impl<'d, DmaMode, T> I2s<'d, DmaMode, T> @@ -274,7 +272,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 @@ -299,15 +297,12 @@ where i2s: unsafe { i2s.clone_unchecked() }, rx_channel: channel.rx, descriptors: rx_descriptors, - phantom: PhantomData, }, i2s_tx: TxCreator { i2s, tx_channel: channel.tx, descriptors: tx_descriptors, - phantom: PhantomData, }, - phantom: PhantomData, } } } @@ -376,14 +371,14 @@ impl<'d> I2s<'d, Blocking> { standard: Standard, data_format: DataFormat, sample_rate: impl Into, - channel: Channel<'d, CH, DM>, + channel: Channel<'d, DM, CH>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> Self where CH: DmaChannelConvert<::Dma>, DM: Mode, - Channel<'d, CH, Blocking>: From>, + Channel<'d, Blocking, CH>: From>, { Self::new_typed( i2s.map_into(), @@ -409,14 +404,14 @@ where standard: Standard, data_format: DataFormat, sample_rate: impl Into, - channel: Channel<'d, CH, DM>, + channel: Channel<'d, DM, CH>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> Self where CH: DmaChannelConvert, DM: Mode, - Channel<'d, CH, Blocking>: From>, + Channel<'d, Blocking, CH>: From>, { crate::into_ref!(i2s); Self::new_internal( @@ -432,26 +427,17 @@ where /// Converts the SPI instance into async mode. pub fn into_async(self) -> I2s<'d, Async, T> { - let channel = Channel { - rx: self.i2s_rx.rx_channel, - tx: self.i2s_tx.tx_channel, - phantom: PhantomData::, - }; - let channel = channel.into_async(); I2s { i2s_rx: RxCreator { i2s: self.i2s_rx.i2s, - rx_channel: channel.rx, + rx_channel: self.i2s_rx.rx_channel.into_async(), descriptors: self.i2s_rx.descriptors, - phantom: PhantomData, }, i2s_tx: TxCreator { i2s: self.i2s_tx.i2s, - tx_channel: channel.tx, + tx_channel: self.i2s_tx.tx_channel.into_async(), descriptors: self.i2s_tx.descriptors, - phantom: PhantomData, }, - phantom: PhantomData, } } } @@ -477,9 +463,8 @@ where T: RegisterAccess, { i2s: PeripheralRef<'d, T>, - tx_channel: ChannelTx<'d, T::Dma>, + tx_channel: ChannelTx<'d, DmaMode, T::Dma>, tx_chain: DescriptorChain, - phantom: PhantomData, } impl core::fmt::Debug for I2sTx<'_, DmaMode, T> @@ -511,7 +496,7 @@ where T: RegisterAccess, DmaMode: Mode, { - type TX = ChannelTx<'d, T::Dma>; + type TX = ChannelTx<'d, DmaMode, T::Dma>; fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel @@ -610,9 +595,8 @@ where DmaMode: Mode, { i2s: PeripheralRef<'d, T>, - rx_channel: ChannelRx<'d, T::Dma>, + rx_channel: ChannelRx<'d, DmaMode, T::Dma>, rx_chain: DescriptorChain, - phantom: PhantomData, } impl core::fmt::Debug for I2sRx<'_, DmaMode, T> @@ -644,7 +628,7 @@ where T: RegisterAccess, DmaMode: Mode, { - type RX = ChannelRx<'d, T::Dma>; + type RX = ChannelRx<'d, DmaMode, T::Dma>; fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel @@ -750,8 +734,6 @@ pub trait RegisterAccess: RegisterAccessPrivate {} impl RegisterAccess for T where T: RegisterAccessPrivate {} mod private { - use core::marker::PhantomData; - use enumset::EnumSet; use fugit::HertzU32; @@ -790,22 +772,20 @@ mod private { M: Mode, { pub i2s: PeripheralRef<'d, T>, - pub tx_channel: ChannelTx<'d, T::Dma>, + pub tx_channel: ChannelTx<'d, M, T::Dma>, pub descriptors: &'static mut [DmaDescriptor], - pub(crate) phantom: PhantomData, } - impl<'d, DmaMode, T> TxCreator<'d, DmaMode, T> + impl<'d, M, T> TxCreator<'d, M, T> where + M: Mode, T: RegisterAccess, - DmaMode: Mode, { - pub fn build(self) -> I2sTx<'d, DmaMode, T> { + pub fn build(self) -> I2sTx<'d, M, T> { I2sTx { i2s: self.i2s, tx_channel: self.tx_channel, tx_chain: DescriptorChain::new(self.descriptors), - phantom: PhantomData, } } @@ -849,22 +829,20 @@ mod private { M: Mode, { pub i2s: PeripheralRef<'d, T>, - pub rx_channel: ChannelRx<'d, T::Dma>, + pub rx_channel: ChannelRx<'d, M, T::Dma>, pub descriptors: &'static mut [DmaDescriptor], - pub(crate) phantom: PhantomData, } impl<'d, M, T> RxCreator<'d, M, T> where - T: RegisterAccess, M: Mode, + T: RegisterAccess, { pub fn build(self) -> I2sRx<'d, M, T> { I2sRx { i2s: self.i2s, rx_channel: self.rx_channel, rx_chain: DescriptorChain::new(self.descriptors), - phantom: PhantomData, } } diff --git a/esp-hal/src/i2s/parallel.rs b/esp-hal/src/i2s/parallel.rs index 865346fb648..c7b84e630ce 100644 --- a/esp-hal/src/i2s/parallel.rs +++ b/esp-hal/src/i2s/parallel.rs @@ -35,7 +35,6 @@ //! - `DMA` //! - `system` (to configure and enable the I2S peripheral) use core::{ - marker::PhantomData, mem::ManuallyDrop, ops::{Deref, DerefMut}, }; @@ -177,8 +176,7 @@ where I: Instance, { instance: PeripheralRef<'d, I>, - tx_channel: ChannelTx<'d, I::Dma>, - mode: PhantomData, + tx_channel: ChannelTx<'d, DM, I::Dma>, } impl<'d, DM> I2sParallel<'d, DM> @@ -188,7 +186,7 @@ where /// Create a new I2S Parallel Interface pub fn new( i2s: impl Peripheral

+ 'd, - channel: Channel<'d, CH, DM>, + channel: Channel<'d, DM, CH>, frequency: impl Into, pins: impl TxPins<'d>, clock_pin: impl Peripheral

+ 'd, @@ -208,7 +206,7 @@ where /// Create a new I2S Parallel Interface pub fn new_typed( i2s: impl Peripheral

+ 'd, - channel: Channel<'d, CH, DM>, + channel: Channel<'d, DM, CH>, frequency: impl Into, mut pins: impl TxPins<'d>, clock_pin: impl Peripheral

+ 'd, @@ -234,7 +232,6 @@ where Self { instance: i2s, tx_channel: channel.tx, - mode: PhantomData, } } diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index 5125d8b343d..358643e871e 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -82,6 +82,7 @@ use crate::{ lcd_cam::{calculate_clkm, BitOrder, ByteOrder}, peripheral::{Peripheral, PeripheralRef}, peripherals::LCD_CAM, + Blocking, }; /// Generation of GDMA SUC EOF @@ -125,14 +126,14 @@ 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, ::Dma>, + rx_channel: ChannelRx<'d, Blocking, ::Dma>, } impl<'d> Camera<'d> { /// Creates a new `Camera` instance with DMA support. pub fn new( cam: Cam<'d>, - channel: ChannelRx<'d, CH>, + channel: ChannelRx<'d, Blocking, CH>, _pins: P, frequency: HertzU32, ) -> Self diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index 109b658aa39..bfc7465a623 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -83,21 +83,25 @@ use crate::{ }, peripheral::{Peripheral, PeripheralRef}, peripherals::LCD_CAM, + Blocking, Mode, }; /// Represents the I8080 LCD interface. pub struct I8080<'d, DM: Mode> { lcd_cam: PeripheralRef<'d, LCD_CAM>, - tx_channel: ChannelTx<'d, ::Dma>, - _phantom: PhantomData, + tx_channel: ChannelTx<'d, Blocking, ::Dma>, + _mode: PhantomData, } -impl<'d, DM: Mode> I8080<'d, DM> { +impl<'d, DM> I8080<'d, DM> +where + DM: Mode, +{ /// Creates a new instance of the I8080 LCD interface. pub fn new( lcd: Lcd<'d, DM>, - channel: ChannelTx<'d, CH>, + channel: ChannelTx<'d, Blocking, CH>, mut pins: P, frequency: HertzU32, config: Config, @@ -209,12 +213,10 @@ impl<'d, DM: Mode> I8080<'d, DM> { Self { lcd_cam, tx_channel: channel.degrade(), - _phantom: PhantomData, + _mode: PhantomData, } } -} -impl<'d, DM: Mode> I8080<'d, DM> { /// Configures the byte order for data transmission in 16-bit mode. /// This must be set to [ByteOrder::default()] when transmitting in 8-bit /// mode. diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index 2743efd5457..bef43f900fd 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -45,11 +45,13 @@ //! before proceeding. We also have a [training] that covers some common //! scenarios with examples. //! -//! We have a template for quick starting bare-metal projects, [esp-template]. -//! The template uses [cargo-generate], so ensure that it is installed and run: +//! We have developed a project generation tool, [esp-generate], which we +//! recommend when starting new projects. It can be installed and run, e.g. +//! for the ESP32-C6, as follows: //! //! ```bash -//! cargo generate -a esp-rs/esp-template +//! cargo install esp-generate +//! esp-generate --chip=esp32c6 your-project //! ``` //! //! ## Blinky @@ -128,8 +130,7 @@ //! [embedded-hal]: https://github.com/rust-embedded/embedded-hal/tree/master/embedded-hal //! [embedded-hal-async]: https://github.com/rust-embedded/embedded-hal/tree/master/embedded-hal-async //! [xtask]: https://github.com/matklad/cargo-xtask -//! [esp-template]: https://github.com/esp-rs/esp-template -//! [cargo-generate]: https://github.com/cargo-generate/cargo-generate +//! [esp-generate]: https://github.com/esp-rs/esp-generate //! [book]: https://docs.esp-rs.org/book/ //! [training]: https://docs.esp-rs.org/no_std-training/ //! diff --git a/esp-hal/src/macros.rs b/esp-hal/src/macros.rs index f4274d8033d..1b5764d7b06 100644 --- a/esp-hal/src/macros.rs +++ b/esp-hal/src/macros.rs @@ -118,3 +118,16 @@ macro_rules! any_peripheral { } }; } + +/// Macro to choose between two expressions. Useful for implementing "else" for +/// `$()?` macro syntax. +#[macro_export] +#[doc(hidden)] +macro_rules! if_set { + (, $not_set:expr) => { + $not_set + }; + ($set:expr, $not_set:expr) => { + $set + }; +} diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 2d95e1427ec..1b81ca2901e 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -23,8 +23,6 @@ //! //! [Parallel IO TX]: https://github.com/esp-rs/esp-hal/blob/main/examples/src/bin/parl_io_tx.rs -use core::marker::PhantomData; - use enumset::{EnumSet, EnumSetType}; use fugit::HertzU32; use peripheral::PeripheralRef; @@ -769,7 +767,6 @@ where Ok(ParlIoTx { tx_channel: self.tx_channel, tx_chain: DescriptorChain::new(self.descriptors), - phantom: PhantomData, }) } } @@ -801,7 +798,6 @@ where Ok(ParlIoTx { tx_channel: self.tx_channel, tx_chain: DescriptorChain::new(self.descriptors), - phantom: PhantomData, }) } } @@ -811,9 +807,8 @@ pub struct ParlIoTx<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d, ::Dma>, + tx_channel: ChannelTx<'d, DM, ::Dma>, tx_chain: DescriptorChain, - phantom: PhantomData, } impl core::fmt::Debug for ParlIoTx<'_, DM> @@ -850,7 +845,6 @@ where Ok(ParlIoRx { rx_channel: self.rx_channel, rx_chain: DescriptorChain::new(self.descriptors), - phantom: PhantomData, }) } } @@ -880,7 +874,6 @@ where Ok(ParlIoRx { rx_channel: self.rx_channel, rx_chain: DescriptorChain::new(self.descriptors), - phantom: PhantomData, }) } } @@ -890,9 +883,8 @@ pub struct ParlIoRx<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d, ::Dma>, + rx_channel: ChannelRx<'d, DM, ::Dma>, rx_chain: DescriptorChain, - phantom: PhantomData, } impl core::fmt::Debug for ParlIoRx<'_, DM> @@ -1005,7 +997,7 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> { /// 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, @@ -1013,43 +1005,33 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> { where DM: Mode, CH: DmaChannelConvert<::Dma>, - Channel<'d, CH, Blocking>: From>, + Channel<'d, Blocking, CH>: From>, { - let dma_channel = Channel::<'d, CH, Blocking>::from(dma_channel); + let dma_channel = Channel::::from(dma_channel); internal_init(frequency)?; Ok(Self { tx: TxCreatorFullDuplex { tx_channel: dma_channel.tx.degrade(), descriptors: tx_descriptors, - phantom: PhantomData, }, rx: RxCreatorFullDuplex { rx_channel: dma_channel.rx.degrade(), descriptors: rx_descriptors, - phantom: PhantomData, }, }) } /// Convert to an async version. pub fn into_async(self) -> ParlIoFullDuplex<'d, Async> { - let channel = Channel { - tx: self.tx.tx_channel, - rx: self.rx.rx_channel, - phantom: PhantomData::, - }; - let channel = channel.into_async(); ParlIoFullDuplex { tx: TxCreatorFullDuplex { - tx_channel: channel.tx, + tx_channel: self.tx.tx_channel.into_async(), descriptors: self.tx.descriptors, - phantom: PhantomData, }, rx: RxCreatorFullDuplex { - rx_channel: channel.rx, + rx_channel: self.rx.rx_channel.into_async(), descriptors: self.rx.descriptors, - phantom: PhantomData, }, } } @@ -1094,22 +1076,14 @@ impl InterruptConfigurable for ParlIoFullDuplex<'_, Blocking> { impl<'d> ParlIoFullDuplex<'d, Async> { /// Convert to a blocking version. pub fn into_blocking(self) -> ParlIoFullDuplex<'d, Blocking> { - let channel = Channel { - tx: self.tx.tx_channel, - rx: self.rx.rx_channel, - phantom: PhantomData::, - }; - let channel = channel.into_blocking(); ParlIoFullDuplex { tx: TxCreatorFullDuplex { - tx_channel: channel.tx, + tx_channel: self.tx.tx_channel.into_blocking(), descriptors: self.tx.descriptors, - phantom: PhantomData, }, rx: RxCreatorFullDuplex { - rx_channel: channel.rx, + rx_channel: self.rx.rx_channel.into_blocking(), descriptors: self.rx.descriptors, - phantom: PhantomData, }, } } @@ -1133,7 +1107,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 @@ -1146,7 +1120,6 @@ where tx: TxCreator { tx_channel: dma_channel.tx.degrade(), descriptors, - phantom: PhantomData, }, }) } @@ -1208,7 +1181,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 @@ -1221,7 +1194,6 @@ where rx: RxCreator { rx_channel: dma_channel.rx.degrade(), descriptors, - phantom: PhantomData, }, }) } @@ -1372,7 +1344,7 @@ impl<'d, DM> DmaSupportTx for ParlIoTx<'d, DM> where DM: Mode, { - type TX = ChannelTx<'d, ::Dma>; + type TX = ChannelTx<'d, DM, ::Dma>; fn tx(&mut self) -> &mut Self::TX { &mut self.tx_channel @@ -1414,7 +1386,7 @@ where } fn start_receive_bytes_dma( - rx_channel: &mut ChannelRx<'d, ::Dma>, + rx_channel: &mut ChannelRx<'d, DM, ::Dma>, rx_chain: &mut DescriptorChain, ptr: *mut u8, len: usize, @@ -1468,7 +1440,7 @@ impl<'d, DM> DmaSupportRx for ParlIoRx<'d, DM> where DM: Mode, { - type RX = ChannelRx<'d, ::Dma>; + type RX = ChannelRx<'d, DM, ::Dma>; fn rx(&mut self) -> &mut Self::RX { &mut self.rx_channel @@ -1484,9 +1456,8 @@ pub struct TxCreator<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d, ::Dma>, + tx_channel: ChannelTx<'d, DM, ::Dma>, descriptors: &'static mut [DmaDescriptor], - phantom: PhantomData, } /// Creates a RX channel @@ -1494,9 +1465,8 @@ pub struct RxCreator<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d, ::Dma>, + rx_channel: ChannelRx<'d, DM, ::Dma>, descriptors: &'static mut [DmaDescriptor], - phantom: PhantomData, } /// Creates a TX channel @@ -1504,9 +1474,8 @@ pub struct TxCreatorFullDuplex<'d, DM> where DM: Mode, { - tx_channel: ChannelTx<'d, ::Dma>, + tx_channel: ChannelTx<'d, DM, ::Dma>, descriptors: &'static mut [DmaDescriptor], - phantom: PhantomData, } /// Creates a RX channel @@ -1514,9 +1483,8 @@ pub struct RxCreatorFullDuplex<'d, DM> where DM: Mode, { - rx_channel: ChannelRx<'d, ::Dma>, + rx_channel: ChannelRx<'d, DM, ::Dma>, descriptors: &'static mut [DmaDescriptor], - phantom: PhantomData, } #[doc(hidden)] diff --git a/esp-hal/src/rmt.rs b/esp-hal/src/rmt.rs index dc2d4e916e3..f1c0975e6d5 100644 --- a/esp-hal/src/rmt.rs +++ b/esp-hal/src/rmt.rs @@ -1138,7 +1138,7 @@ pub trait TxChannelAsync: TxChannelInternal { /// Start transmitting the given pulse code sequence. /// The length of sequence cannot exceed the size of the allocated RMT /// RAM. - async fn transmit<'a>(&mut self, data: &'a [u32]) -> Result<(), Error> + async fn transmit(&mut self, data: &[u32]) -> Result<(), Error> where Self: Sized, { @@ -1201,7 +1201,7 @@ pub trait RxChannelAsync: RxChannelInternal { /// Start receiving a pulse code sequence. /// The length of sequence cannot exceed the size of the allocated RMT /// RAM. - async fn receive<'a, T: From + Copy>(&mut self, data: &'a mut [T]) -> Result<(), Error> + async fn receive + Copy>(&mut self, data: &mut [T]) -> Result<(), Error> where Self: Sized, { diff --git a/esp-hal/src/soc/esp32/mod.rs b/esp-hal/src/soc/esp32/mod.rs index aeeffa81ee8..a4609a8032a 100644 --- a/esp-hal/src/soc/esp32/mod.rs +++ b/esp-hal/src/soc/esp32/mod.rs @@ -27,6 +27,7 @@ macro_rules! chip { } /// A link to the Technical Reference Manual (TRM) for the chip. +#[doc(hidden)] #[macro_export] macro_rules! trm_link { () => { "https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf" }; diff --git a/esp-hal/src/soc/esp32c2/mod.rs b/esp-hal/src/soc/esp32c2/mod.rs index da4a41fa440..93541428ec7 100644 --- a/esp-hal/src/soc/esp32c2/mod.rs +++ b/esp-hal/src/soc/esp32c2/mod.rs @@ -20,6 +20,7 @@ macro_rules! chip { } /// A link to the Technical Reference Manual (TRM) for the chip. +#[doc(hidden)] #[macro_export] macro_rules! trm_link { () => { "https://www.espressif.com/sites/default/files/documentation/esp8684_technical_reference_manual_en.pdf" }; diff --git a/esp-hal/src/soc/esp32c3/mod.rs b/esp-hal/src/soc/esp32c3/mod.rs index 6955b5c78c7..b8c5ae881ff 100644 --- a/esp-hal/src/soc/esp32c3/mod.rs +++ b/esp-hal/src/soc/esp32c3/mod.rs @@ -24,6 +24,7 @@ macro_rules! chip { } /// A link to the Technical Reference Manual (TRM) for the chip. +#[doc(hidden)] #[macro_export] macro_rules! trm_link { () => { "https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf" }; diff --git a/esp-hal/src/soc/esp32c6/mod.rs b/esp-hal/src/soc/esp32c6/mod.rs index 1ed7e74db87..85040794775 100644 --- a/esp-hal/src/soc/esp32c6/mod.rs +++ b/esp-hal/src/soc/esp32c6/mod.rs @@ -26,6 +26,7 @@ macro_rules! chip { } /// A link to the Technical Reference Manual (TRM) for the chip. +#[doc(hidden)] #[macro_export] macro_rules! trm_link { () => { "https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf" }; diff --git a/esp-hal/src/soc/esp32h2/mod.rs b/esp-hal/src/soc/esp32h2/mod.rs index 9997f73fb2e..8eb9701de2b 100644 --- a/esp-hal/src/soc/esp32h2/mod.rs +++ b/esp-hal/src/soc/esp32h2/mod.rs @@ -25,6 +25,7 @@ macro_rules! chip { } /// A link to the Technical Reference Manual (TRM) for the chip. +#[doc(hidden)] #[macro_export] macro_rules! trm_link { () => { "https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf" }; diff --git a/esp-hal/src/soc/esp32s2/mod.rs b/esp-hal/src/soc/esp32s2/mod.rs index ed39d35546f..c6fdd8db12e 100644 --- a/esp-hal/src/soc/esp32s2/mod.rs +++ b/esp-hal/src/soc/esp32s2/mod.rs @@ -32,6 +32,7 @@ macro_rules! chip { } /// A link to the Technical Reference Manual (TRM) for the chip. +#[doc(hidden)] #[macro_export] macro_rules! trm_link { () => { "https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf" }; diff --git a/esp-hal/src/soc/esp32s3/mod.rs b/esp-hal/src/soc/esp32s3/mod.rs index f0b5171c4f0..69189e2d4b1 100644 --- a/esp-hal/src/soc/esp32s3/mod.rs +++ b/esp-hal/src/soc/esp32s3/mod.rs @@ -33,6 +33,7 @@ macro_rules! chip { } /// A link to the Technical Reference Manual (TRM) for the chip. +#[doc(hidden)] #[macro_export] macro_rules! trm_link { () => { "https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf" }; diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 1430a5269c3..2bc93c5d61c 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -474,11 +474,11 @@ where /// 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(self, channel: Channel<'d, CH, DM>) -> SpiDma<'d, M, T> + pub fn with_dma(self, channel: Channel<'d, DM, CH>) -> SpiDma<'d, M, T> where CH: DmaChannelConvert, DM: Mode, - Channel<'d, CH, M>: From>, + Channel<'d, M, CH>: From>, { SpiDma::new(self.spi, channel.into()) } @@ -880,7 +880,7 @@ mod dma { M: Mode, { pub(crate) spi: PeripheralRef<'d, T>, - pub(crate) channel: Channel<'d, T::Dma, M>, + pub(crate) channel: Channel<'d, M, T::Dma>, tx_transfer_in_progress: bool, rx_transfer_in_progress: bool, #[cfg(all(esp32, spi_address_workaround))] @@ -990,7 +990,7 @@ mod dma { T: Instance, 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: DmaChannelConvert, { @@ -3003,10 +3003,10 @@ macro_rules! spi_instance { cs: OutputSignal::$cs, sio0_input: InputSignal::$mosi, sio1_output: OutputSignal::$miso, - sio2_output: if_set!($(Some(OutputSignal::$sio2))?, None), - sio2_input: if_set!($(Some(InputSignal::$sio2))?, None), - sio3_output: if_set!($(Some(OutputSignal::$sio3))?, None), - sio3_input: if_set!($(Some(InputSignal::$sio3))?, None), + sio2_output: $crate::if_set!($(Some(OutputSignal::$sio2))?, None), + sio2_input: $crate::if_set!($(Some(InputSignal::$sio2))?, None), + sio3_output: $crate::if_set!($(Some(OutputSignal::$sio3))?, None), + sio3_input: $crate::if_set!($(Some(InputSignal::$sio3))?, None), }; &INFO @@ -3022,17 +3022,6 @@ macro_rules! spi_instance { } } -/// Macro to choose between two expressions. Useful for implementing "else" for -/// `$()?` macro syntax. -macro_rules! if_set { - (, $not_set:expr) => { - $not_set - }; - ($set:expr, $not_set:expr) => { - $set - }; -} - #[cfg(spi2)] cfg_if::cfg_if! { if #[cfg(esp32)] { diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index 0ffd707d1eb..7e00288f48f 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -202,14 +202,14 @@ pub mod dma { #[cfg_attr(esp32, doc = "\n\n**Note**: ESP32 only supports Mode 1 and 3.")] pub fn with_dma( self, - channel: Channel<'d, CH, DM>, + channel: Channel<'d, DM, CH>, rx_descriptors: &'static mut [DmaDescriptor], tx_descriptors: &'static mut [DmaDescriptor], ) -> SpiDma<'d, M, T> where CH: DmaChannelConvert, DM: Mode, - Channel<'d, CH, M>: From>, + Channel<'d, M, CH>: From>, { self.spi.info().set_data_mode(self.data_mode, true); SpiDma::new(self.spi, channel.into(), rx_descriptors, tx_descriptors) @@ -223,7 +223,7 @@ pub mod dma { M: Mode, { pub(crate) spi: PeripheralRef<'d, T>, - pub(crate) channel: Channel<'d, T::Dma, M>, + pub(crate) channel: Channel<'d, M, T::Dma>, rx_chain: DescriptorChain, tx_chain: DescriptorChain, } @@ -262,7 +262,7 @@ pub mod dma { T: InstanceDma, DmaMode: Mode, { - type TX = ChannelTx<'d, T::Dma>; + type TX = ChannelTx<'d, DmaMode, T::Dma>; fn tx(&mut self) -> &mut Self::TX { &mut self.channel.tx @@ -278,7 +278,7 @@ pub mod dma { T: InstanceDma, DmaMode: Mode, { - type RX = ChannelRx<'d, T::Dma>; + type RX = ChannelRx<'d, DmaMode, T::Dma>; fn rx(&mut self) -> &mut Self::RX { &mut self.channel.rx @@ -296,7 +296,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/esp-wifi/src/ble/controller/mod.rs b/esp-wifi/src/ble/controller/mod.rs index 41a6ae188cb..07228eb1208 100644 --- a/esp-wifi/src/ble/controller/mod.rs +++ b/esp-wifi/src/ble/controller/mod.rs @@ -11,7 +11,7 @@ pub struct BleConnector<'d> { _device: PeripheralRef<'d, crate::hal::peripherals::BT>, } -impl<'d> Drop for BleConnector<'d> { +impl Drop for BleConnector<'_> { fn drop(&mut self) { crate::ble::ble_deinit(); } diff --git a/esp-wifi/src/esp_now/mod.rs b/esp-wifi/src/esp_now/mod.rs index 4ee12c909e1..83786e1f143 100644 --- a/esp-wifi/src/esp_now/mod.rs +++ b/esp-wifi/src/esp_now/mod.rs @@ -501,7 +501,7 @@ impl EspNowManager<'_> { } } -impl<'d> Drop for EspNowManager<'d> { +impl Drop for EspNowManager<'_> { fn drop(&mut self) { if unwrap!( crate::flags::WIFI.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { diff --git a/esp-wifi/src/lib.rs b/esp-wifi/src/lib.rs index d370bdd707f..fbad7bd34f7 100644 --- a/esp-wifi/src/lib.rs +++ b/esp-wifi/src/lib.rs @@ -233,7 +233,7 @@ pub struct EspWifiController<'d> { _inner: PhantomData<&'d ()>, } -impl<'d> EspWifiController<'d> { +impl EspWifiController<'_> { /// Is the WiFi part of the radio running pub fn wifi(&self) -> bool { crate::flags::WIFI.load(Ordering::Acquire) > 0 @@ -261,7 +261,7 @@ impl<'d> EspWifiController<'d> { } } -impl<'d> Drop for EspWifiController<'d> { +impl Drop for EspWifiController<'_> { fn drop(&mut self) { if crate::flags::ESP_WIFI_INITIALIZED.load(Ordering::Acquire) { // safety: no other driver can be using this if this is callable diff --git a/esp-wifi/src/wifi/mod.rs b/esp-wifi/src/wifi/mod.rs index 7bb5ce6ce06..dbab7ada004 100644 --- a/esp-wifi/src/wifi/mod.rs +++ b/esp-wifi/src/wifi/mod.rs @@ -2399,7 +2399,7 @@ pub struct WifiController<'d> { sniffer_taken: AtomicBool, } -impl<'d> Drop for WifiController<'d> { +impl Drop for WifiController<'_> { fn drop(&mut self) { if unwrap!( crate::flags::WIFI.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { diff --git a/hil-test/tests/dma_mem2mem.rs b/hil-test/tests/dma_mem2mem.rs index f65873ae6c5..d9a3a362be3 100644 --- a/hil-test/tests/dma_mem2mem.rs +++ b/hil-test/tests/dma_mem2mem.rs @@ -25,7 +25,7 @@ cfg_if::cfg_if! { } struct Context { - channel: Channel<'static, AnyGdmaChannel, Blocking>, + channel: Channel<'static, Blocking, AnyGdmaChannel>, dma_peripheral: DmaPeripheralType, } diff --git a/hil-test/tests/lcd_cam_i8080.rs b/hil-test/tests/lcd_cam_i8080.rs index 987a0ad543a..ae34f4506ef 100644 --- a/hil-test/tests/lcd_cam_i8080.rs +++ b/hil-test/tests/lcd_cam_i8080.rs @@ -90,27 +90,6 @@ mod tests { xfer.wait().0.unwrap(); } - #[test] - fn test_i8080_8bit_async_channel(ctx: Context<'static>) { - let channel = ctx - .dma - .channel0 - .configure(false, DmaPriority::Priority0) - .into_async(); - let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin); - - let i8080 = I8080::new( - ctx.lcd_cam.lcd, - channel.tx, - pins, - 20.MHz(), - Config::default(), - ); - - let xfer = i8080.send(Command::::None, 0, ctx.dma_buf).unwrap(); - xfer.wait().0.unwrap(); - } - #[test] fn test_i8080_8bit_is_seen_by_pcnt(ctx: Context<'static>) { // FIXME: Update this test to exercise all the I8080 output signals once the diff --git a/hil-test/tests/lcd_cam_i8080_async.rs b/hil-test/tests/lcd_cam_i8080_async.rs index df44d002289..855d925df58 100644 --- a/hil-test/tests/lcd_cam_i8080_async.rs +++ b/hil-test/tests/lcd_cam_i8080_async.rs @@ -70,31 +70,4 @@ mod tests { transfer.wait().0.unwrap(); } - - #[test] - async fn test_i8080_8bit_async_channel(ctx: Context<'static>) { - let channel = ctx - .dma - .channel0 - .configure(false, DmaPriority::Priority0) - .into_async(); - let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin); - - let i8080 = I8080::new( - ctx.lcd_cam.lcd, - channel.tx, - pins, - 20.MHz(), - Config::default(), - ); - - let mut transfer = i8080.send(Command::::None, 0, ctx.dma_buf).unwrap(); - - transfer.wait_for_done().await; - - // This should not block forever and should immediately return. - transfer.wait_for_done().await; - - transfer.wait().0.unwrap(); - } } diff --git a/hil-test/tests/qspi.rs b/hil-test/tests/qspi.rs index c2f69b9ebdf..43b500d9a7a 100644 --- a/hil-test/tests/qspi.rs +++ b/hil-test/tests/qspi.rs @@ -43,7 +43,7 @@ struct Context { spi: Spi<'static, Blocking>, #[cfg(pcnt)] pcnt: esp_hal::peripherals::PCNT, - dma_channel: Channel<'static, DmaChannel0, Blocking>, + dma_channel: Channel<'static, Blocking, DmaChannel0>, gpios: [AnyPin; 3], } diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index a7d72b76cfd..a6cb19f5ecc 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -103,17 +103,18 @@ pub enum Version { } /// Build the documentation for the specified package and device. -pub fn build_documentation( - workspace: &Path, - package: Package, - chip: Chip, - target: &str, -) -> Result { +pub fn build_documentation(workspace: &Path, package: Package, chip: Chip) -> Result { let package_name = package.to_string(); let package_path = windows_safe_path(&workspace.join(&package_name)); log::info!("Building '{package_name}' documentation targeting '{chip}'"); + // Determine the appropriate build target for the given package and chip: + let target = target_triple(package, &chip)?; + + // We need `nightly` for building the docs, unfortunately: + let toolchain = if chip.is_xtensa() { "esp" } else { "nightly" }; + let mut features = vec![chip.to_string()]; let chip = Config::for_chip(&chip); @@ -122,6 +123,7 @@ pub fn build_documentation( // Build up an array of command-line arguments to pass to `cargo`: let builder = CargoArgsBuilder::default() + .toolchain(toolchain) .subcommand("doc") .target(target) .features(&features) @@ -659,3 +661,12 @@ pub fn package_version(workspace: &Path, package: Package) -> Result PathBuf { PathBuf::from(path.to_str().unwrap().to_string().replace("\\\\?\\", "")) } + +/// Return the target triple for a given package/chip pair. +pub fn target_triple(package: Package, chip: &Chip) -> Result<&str> { + if package == Package::EspLpHal { + chip.lp_target() + } else { + Ok(chip.target()) + } +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index a1c1e18e61e..8da10fbd4bd 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -12,6 +12,7 @@ use minijinja::Value; use strum::IntoEnumIterator; use xtask::{ cargo::{CargoAction, CargoArgsBuilder}, + target_triple, Metadata, Package, Version, @@ -35,13 +36,15 @@ enum Cli { /// Bump the version of the specified package(s). BumpVersion(BumpVersionArgs), /// Format all packages in the workspace with rustfmt + #[clap(alias = "format-packages")] FmtPackages(FmtPackagesArgs), /// Generate the eFuse fields source file from a CSV. GenerateEfuseFields(GenerateEfuseFieldsArgs), /// Lint all packages in the workspace with clippy LintPackages(LintPackagesArgs), /// Run doctests for specified chip and package. - RunDocTest(ExampleArgs), + #[clap(alias = "run-doc-test")] + RunDocTests(ExampleArgs), /// Run the given example for the specified chip. RunExample(ExampleArgs), /// Run all applicable tests or the specified test for a specified chip. @@ -177,7 +180,7 @@ fn main() -> Result<()> { Cli::FmtPackages(args) => fmt_packages(&workspace, args), Cli::GenerateEfuseFields(args) => generate_efuse_src(&workspace, args), Cli::LintPackages(args) => lint_packages(&workspace, args), - Cli::RunDocTest(args) => run_doctests(&workspace, args), + Cli::RunDocTests(args) => run_doc_tests(&workspace, args), Cli::RunElfs(args) => run_elfs(args), Cli::RunExample(args) => examples(&workspace, args, CargoAction::Run), Cli::RunTests(args) => tests(&workspace, args, CargoAction::Run), @@ -436,12 +439,9 @@ fn build_documentation_for_package( // Ensure that the package/chip combination provided are valid: validate_package_chip(&package, chip)?; - // Determine the appropriate build target for the given package and chip: - let target = target_triple(package, chip)?; - // Build the documentation for the specified package, targeting the // specified chip: - let docs_path = xtask::build_documentation(workspace, package, *chip, target)?; + let docs_path = xtask::build_documentation(workspace, package, *chip)?; ensure!( docs_path.exists(), @@ -458,6 +458,7 @@ fn build_documentation_for_package( // Create the output directory, and copy the built documentation into it: fs::create_dir_all(&output_path) .with_context(|| format!("Failed to create {}", output_path.display()))?; + copy_dir_all(&docs_path, &output_path).with_context(|| { format!( "Failed to copy {} to {}", @@ -812,16 +813,23 @@ fn run_elfs(args: RunElfArgs) -> Result<()> { Ok(()) } -fn run_doctests(workspace: &Path, args: ExampleArgs) -> Result<()> { +fn run_doc_tests(workspace: &Path, args: ExampleArgs) -> Result<()> { + let chip = args.chip; + let package_name = args.package.to_string(); let package_path = xtask::windows_safe_path(&workspace.join(&package_name)); - // Determine the appropriate build target for the given package and chip: - let target = target_triple(args.package, &args.chip)?; - let features = vec![args.chip.to_string()]; + // Determine the appropriate build target, and cargo features for the given + // package and chip: + let target = target_triple(args.package, &chip)?; + let features = vec![chip.to_string()]; + + // We need `nightly` for building the doc tests, unfortunately: + let toolchain = if chip.is_xtensa() { "esp" } else { "nightly" }; // Build up an array of command-line arguments to pass to `cargo`: let builder = CargoArgsBuilder::default() + .toolchain(toolchain) .subcommand("test") .arg("--doc") .arg("-Zdoctest-xcompile") @@ -842,14 +850,6 @@ fn run_doctests(workspace: &Path, args: ExampleArgs) -> Result<()> { // ---------------------------------------------------------------------------- // Helper Functions -fn target_triple(package: Package, chip: &Chip) -> Result<&str> { - if package == Package::EspLpHal { - chip.lp_target() - } else { - Ok(chip.target()) - } -} - fn validate_package_chip(package: &Package, chip: &Chip) -> Result<()> { ensure!( *package != Package::EspLpHal || chip.has_lp_core(),