From 9abaa420114b719072e69990c8cbeb187e331c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 15 Nov 2024 15:07:09 +0100 Subject: [PATCH 1/3] Move DMA channels into Peripherals --- esp-hal/CHANGELOG.md | 4 +- esp-hal/MIGRATING-0.22.md | 14 +++++ esp-hal/src/dma/gdma.rs | 56 ++---------------- esp-hal/src/dma/mod.rs | 45 ++++++++++---- esp-hal/src/dma/pdma.rs | 59 ++++--------------- esp-hal/src/i2s/master.rs | 9 +-- esp-hal/src/i2s/parallel.rs | 5 +- esp-hal/src/lcd_cam/cam.rs | 6 +- esp-hal/src/lcd_cam/lcd/dpi.rs | 5 +- esp-hal/src/lcd_cam/lcd/i8080.rs | 7 +-- esp-hal/src/parl_io.rs | 8 +-- esp-hal/src/peripheral.rs | 16 ++++- esp-hal/src/soc/esp32/peripherals.rs | 7 ++- esp-hal/src/soc/esp32c2/peripherals.rs | 4 +- esp-hal/src/soc/esp32c3/peripherals.rs | 6 +- esp-hal/src/soc/esp32c6/peripherals.rs | 6 +- esp-hal/src/soc/esp32h2/peripherals.rs | 6 +- esp-hal/src/soc/esp32s2/peripherals.rs | 6 +- esp-hal/src/soc/esp32s3/peripherals.rs | 8 ++- esp-hal/src/spi/slave.rs | 6 +- esp-hal/src/system.rs | 14 ++++- examples/src/bin/dma_extmem2mem.rs | 10 +--- examples/src/bin/dma_mem2mem.rs | 28 +++++---- examples/src/bin/embassy_spi.rs | 8 +-- examples/src/bin/spi_loopback_dma_psram.rs | 7 +-- examples/src/bin/spi_slave_dma.rs | 6 +- hil-test/tests/aes_dma.rs | 13 ++-- hil-test/tests/dma_mem2mem.rs | 5 +- hil-test/tests/embassy_interrupt_spi_dma.rs | 18 +++--- hil-test/tests/i2s.rs | 9 +-- hil-test/tests/lcd_cam.rs | 5 +- hil-test/tests/lcd_cam_i8080.rs | 30 +++------- hil-test/tests/lcd_cam_i8080_async.rs | 15 ++--- hil-test/tests/parl_io_tx.rs | 5 +- hil-test/tests/parl_io_tx_async.rs | 5 +- hil-test/tests/qspi.rs | 10 ++-- hil-test/tests/spi_full_duplex.rs | 10 ++-- hil-test/tests/spi_half_duplex_read.rs | 10 ++-- hil-test/tests/spi_half_duplex_write.rs | 9 ++- hil-test/tests/spi_half_duplex_write_psram.rs | 5 +- hil-test/tests/spi_slave.rs | 9 +-- qa-test/src/bin/embassy_i2s_read.rs | 13 ++-- qa-test/src/bin/embassy_i2s_sound.rs | 13 ++-- qa-test/src/bin/lcd_cam_ov2640.rs | 5 +- qa-test/src/bin/lcd_dpi.rs | 4 +- qa-test/src/bin/lcd_i8080.rs | 6 +- qa-test/src/bin/qspi_flash.rs | 8 +-- 47 files changed, 249 insertions(+), 314 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 8a1c6ae1809..84c9dd90e19 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -23,7 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- DMA channel objects now implement `Peripheral` (#2526) +- In addition to taking by value, peripheral drivers can now mutably borrow DMA channel objects. (#2526) - DMA channel objects are no longer wrapped in `Channel`. The `Channel` drivers are now managed by DMA enabled peripheral drivers. (#2526) - The `Dpi` driver and `DpiTransfer` now have a `Mode` type parameter. The driver's asyncness is determined by the asyncness of the `Lcd` used to create it. (#2526) - `dma::{Channel, ChannelRx, ChannelTx}::set_priority` for GDMA devices (#2403) @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `SystemTimer`s `Alarm`s are now type erased (#2576) - `TimerGroup` `Timer`s are now type erased (#2581) - PSRAM is now initialized automatically if `quad-psram` or `octal-psram` is enabled (#2546) +- DMA channels are now available via the `Peripherals` struct, and have been renamed accordingly. (#2545) ### Fixed @@ -46,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `SysTimerAlarms` has been removed, alarms are now part of the `SystemTimer` struct (#2576) - `FrozenUnit`, `AnyUnit`, `SpecificUnit`, `SpecificComparator`, `AnyComparator` have been removed from `systimer` (#2576) - `esp_hal::psram::psram_range` (#2546) +- The `Dma` structure has been removed. (#2545) ## [0.22.0] - 2024-11-20 diff --git a/esp-hal/MIGRATING-0.22.md b/esp-hal/MIGRATING-0.22.md index 671618ac1c8..dee0b5734a9 100644 --- a/esp-hal/MIGRATING-0.22.md +++ b/esp-hal/MIGRATING-0.22.md @@ -2,6 +2,20 @@ ## DMA changes +### Accessing channel objects + +DMA channels are now available through the `Peripherals` struct, which is returned +by `esp_hal::init()`. The channels themselves have been renamed to match other peripheral signletons. + +- ESP32-C2, C3, C6, H2 and S3: `channelX -> DMA_CHX` +- ESP32 and S2: `spiXchannel -> DMA_SPIX`, `i2sXchannel -> DMA_I2SX` + +```diff +-let dma = Dma::new(peripherals.DMA); +-let channel = dma.channel2; ++let channel = peripherals.DMA_CH2; +``` + ### Configuration changes - `configure_for_async` and `configure` have been removed diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index 62a916ba3b6..1b363d83504 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -20,7 +20,6 @@ use crate::{ macros::handler, peripheral::{Peripheral, PeripheralRef}, peripherals::Interrupt, - system::{self, PeripheralClockControl}, }; /// An arbitrary GDMA channel @@ -776,53 +775,10 @@ crate::impl_dma_eligible! { } } -/// GDMA Peripheral -/// -/// This offers the available DMA channels. -pub struct Dma<'d> { - _inner: PeripheralRef<'d, crate::peripherals::DMA>, - /// Channel 0 - pub channel0: DmaChannel0, - /// Channel 1 - #[cfg(not(esp32c2))] - pub channel1: DmaChannel1, - /// Channel 2 - #[cfg(not(esp32c2))] - pub channel2: DmaChannel2, - /// Channel 3 - #[cfg(esp32s3)] - pub channel3: DmaChannel3, - /// Channel 4 - #[cfg(esp32s3)] - pub channel4: DmaChannel4, -} - -impl<'d> Dma<'d> { - /// Create a DMA instance. - pub fn new(dma: impl Peripheral

+ 'd) -> Dma<'d> { - crate::into_ref!(dma); - - if PeripheralClockControl::enable(system::Peripheral::Gdma) { - PeripheralClockControl::reset(system::Peripheral::Gdma); - } - dma.misc_conf().modify(|_, w| w.ahbm_rst_inter().set_bit()); - dma.misc_conf() - .modify(|_, w| w.ahbm_rst_inter().clear_bit()); - dma.misc_conf().modify(|_, w| w.clk_en().set_bit()); - - unsafe { - Dma { - _inner: dma, - channel0: DmaChannel0::steal(), - #[cfg(not(esp32c2))] - channel1: DmaChannel1::steal(), - #[cfg(not(esp32c2))] - channel2: DmaChannel2::steal(), - #[cfg(esp32s3)] - channel3: DmaChannel3::steal(), - #[cfg(esp32s3)] - channel4: DmaChannel4::steal(), - } - } - } +pub(super) fn init_dma() { + let dma = unsafe { crate::soc::peripherals::DMA::steal() }; + dma.misc_conf().modify(|_, w| w.ahbm_rst_inter().set_bit()); + dma.misc_conf() + .modify(|_, w| w.ahbm_rst_inter().clear_bit()); + dma.misc_conf().modify(|_, w| w.clk_en().set_bit()); } diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index c667e8f427d..f6e520f71b8 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -19,10 +19,8 @@ #![doc = crate::before_snippet!()] //! # use esp_hal::dma_buffers; //! # use esp_hal::spi::{master::{Config, Spi}, SpiMode}; -//! # use esp_hal::dma::Dma; -//! let dma = Dma::new(peripherals.DMA); -#![cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = dma.spi2channel;")] -#![cfg_attr(not(any(esp32, esp32s2)), doc = "let dma_channel = dma.channel0;")] +#![cfg_attr(pdma, doc = "let dma_channel = peripherals.DMA_SPI2;")] +#![cfg_attr(gdma, doc = "let dma_channel = peripherals.DMA_CH0;")] //! let sclk = peripherals.GPIO0; //! let miso = peripherals.GPIO2; //! let mosi = peripherals.GPIO4; @@ -70,6 +68,7 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::Interrupt, soc::is_slice_in_dram, + system, Async, Blocking, Cpu, @@ -1665,7 +1664,7 @@ impl DmaChannelConvert for DEG { #[cfg_attr(pdma, doc = "")] #[cfg_attr( pdma, - doc = "Note that using mismatching channels (e.g. trying to use `spi2channel` with SPI3) may compile, but will panic in runtime." + doc = "Note that using mismatching channels (e.g. trying to use `DMA_SPI2` with SPI3) may compile, but will panic in runtime." )] #[cfg_attr(pdma, doc = "")] /// ## Example @@ -1679,7 +1678,6 @@ impl DmaChannelConvert for DEG { /// use esp_hal::dma::DmaChannelFor; /// use esp_hal::peripheral::Peripheral; /// use esp_hal::Blocking; -/// use esp_hal::dma::Dma; /// /// fn configures_spi_dma<'d, S, CH>( /// spi: Spi<'d, Blocking, S>, @@ -1691,10 +1689,8 @@ impl DmaChannelConvert for DEG { /// { /// spi.with_dma(channel) /// } -/// -/// let dma = Dma::new(peripherals.DMA); -#[cfg_attr(pdma, doc = "let dma_channel = dma.spi2channel;")] -#[cfg_attr(gdma, doc = "let dma_channel = dma.channel0;")] +#[cfg_attr(pdma, doc = "let dma_channel = peripherals.DMA_SPI2;")] +#[cfg_attr(gdma, doc = "let dma_channel = peripherals.DMA_CH0;")] #[doc = ""] /// let spi = Spi::new_with_config( /// peripherals.SPI2, @@ -1802,6 +1798,21 @@ pub trait Rx: crate::private::Sealed { fn waker(&self) -> &'static crate::asynch::AtomicWaker; } +// NOTE(p4): because the P4 has two different GDMAs, we won't be able to use +// `GenericPeripheralGuard`. +cfg_if::cfg_if! { + if #[cfg(pdma)] { + type PeripheralGuard = system::GenericPeripheralGuard<{ system::Peripheral::Dma as u8}>; + } else { + type PeripheralGuard = system::GenericPeripheralGuard<{ system::Peripheral::Gdma as u8}>; + } +} + +fn create_guard(_ch: &impl RegisterAccess) -> PeripheralGuard { + // NOTE(p4): this function will read the channel's DMA peripheral from `_ch` + system::GenericPeripheralGuard::new_with(init_dma) +} + // DMA receive channel #[non_exhaustive] #[doc(hidden)] @@ -1812,6 +1823,7 @@ where { pub(crate) rx_impl: PeripheralRef<'a, CH>, pub(crate) _phantom: PhantomData, + pub(crate) _guard: PeripheralGuard, } impl<'a, CH> ChannelRx<'a, Blocking, CH> @@ -1821,6 +1833,9 @@ where /// Creates a new RX channel half. pub fn new(rx_impl: impl Peripheral

+ 'a) -> Self { crate::into_ref!(rx_impl); + + let _guard = create_guard(&*rx_impl); + #[cfg(gdma)] // clear the mem2mem mode to avoid failed DMA if this // channel was previously used for a mem2mem transfer. @@ -1836,6 +1851,7 @@ where Self { rx_impl, _phantom: PhantomData, + _guard, } } @@ -1848,6 +1864,7 @@ where ChannelRx { rx_impl: self.rx_impl, _phantom: PhantomData, + _guard: self._guard, } } @@ -1878,6 +1895,7 @@ where ChannelRx { rx_impl: self.rx_impl, _phantom: PhantomData, + _guard: self._guard, } } } @@ -2095,6 +2113,7 @@ where { pub(crate) tx_impl: PeripheralRef<'a, CH>, pub(crate) _phantom: PhantomData, + pub(crate) _guard: PeripheralGuard, } impl<'a, CH> ChannelTx<'a, Blocking, CH> @@ -2104,6 +2123,9 @@ where /// Creates a new TX channel half. pub fn new(tx_impl: impl Peripheral

+ 'a) -> Self { crate::into_ref!(tx_impl); + + let _guard = create_guard(&*tx_impl); + if let Some(interrupt) = tx_impl.peripheral_interrupt() { for cpu in Cpu::all() { crate::interrupt::disable(cpu, interrupt); @@ -2113,6 +2135,7 @@ where Self { tx_impl, _phantom: PhantomData, + _guard, } } @@ -2125,6 +2148,7 @@ where ChannelTx { tx_impl: self.tx_impl, _phantom: PhantomData, + _guard: self._guard, } } @@ -2155,6 +2179,7 @@ where ChannelTx { tx_impl: self.tx_impl, _phantom: PhantomData, + _guard: self._guard, } } } diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index 2a41d2d6c69..e5953fcf2af 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -20,7 +20,6 @@ use crate::{ macros::handler, peripheral::{Peripheral, PeripheralRef}, peripherals::Interrupt, - system::{self, PeripheralClockControl}, }; type SpiRegisterBlock = crate::peripherals::spi2::RegisterBlock; @@ -876,52 +875,18 @@ crate::impl_dma_eligible!([I2s0DmaChannel] I2S0 => I2s0); #[cfg(i2s1)] crate::impl_dma_eligible!([I2s1DmaChannel] I2S1 => I2s1); -/// DMA Peripheral -/// -/// This offers the available DMA channels. -pub struct Dma<'d> { - _inner: PeripheralRef<'d, crate::peripherals::DMA>, - /// DMA channel for SPI2 - pub spi2channel: Spi2DmaChannel, - /// DMA channel for SPI3 - pub spi3channel: Spi3DmaChannel, - /// DMA channel for I2S0 - pub i2s0channel: I2s0DmaChannel, - /// DMA channel for I2S1 - #[cfg(i2s1)] - pub i2s1channel: I2s1DmaChannel, -} - -impl<'d> Dma<'d> { - /// Create a DMA instance. - pub fn new(dma: impl Peripheral

+ 'd) -> Dma<'d> { - if PeripheralClockControl::enable(system::Peripheral::Dma) { - PeripheralClockControl::reset(system::Peripheral::Dma); - } - - #[cfg(esp32)] - { - // (only) on ESP32 we need to configure DPORT for the SPI DMA channels - // This assignes the DMA channels to the SPI peripherals, which is more - // restrictive than necessary but we currently support the same - // number of SPI peripherals as SPI DMA channels so it's not a big - // deal. - let dport = unsafe { &*crate::peripherals::DPORT::PTR }; - dport.spi_dma_chan_sel().modify(|_, w| unsafe { - w.spi2_dma_chan_sel().bits(1).spi3_dma_chan_sel().bits(2) - }); - } - - unsafe { - Dma { - _inner: dma.into_ref(), - spi2channel: Spi2DmaChannel::steal(), - spi3channel: Spi3DmaChannel::steal(), - i2s0channel: I2s0DmaChannel::steal(), - #[cfg(i2s1)] - i2s1channel: I2s1DmaChannel::steal(), - } - } +pub(super) fn init_dma() { + #[cfg(esp32)] + { + // (only) on ESP32 we need to configure DPORT for the SPI DMA channels + // This assignes the DMA channels to the SPI peripherals, which is more + // restrictive than necessary but we currently support the same + // number of SPI peripherals as SPI DMA channels so it's not a big + // deal. + let dport = unsafe { crate::peripherals::DPORT::steal() }; + dport + .spi_dma_chan_sel() + .modify(|_, w| unsafe { w.spi2_dma_chan_sel().bits(1).spi3_dma_chan_sel().bits(2) }); } } diff --git a/esp-hal/src/i2s/master.rs b/esp-hal/src/i2s/master.rs index 885aa9f1d1b..b63e81a2710 100644 --- a/esp-hal/src/i2s/master.rs +++ b/esp-hal/src/i2s/master.rs @@ -31,10 +31,11 @@ #![doc = crate::before_snippet!()] //! # use esp_hal::i2s::master::{I2s, Standard, DataFormat}; //! # use esp_hal::dma_buffers; -//! # use esp_hal::dma::Dma; -//! let dma = Dma::new(peripherals.DMA); -#![cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = dma.i2s0channel;")] -#![cfg_attr(not(any(esp32, esp32s2)), doc = "let dma_channel = dma.channel0;")] +#![cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = peripherals.DMA_I2S0;")] +#![cfg_attr( + not(any(esp32, esp32s2)), + doc = "let dma_channel = peripherals.DMA_CH0;" +)] //! let (mut rx_buffer, rx_descriptors, _, tx_descriptors) = //! dma_buffers!(0, 4 * 4092); //! diff --git a/esp-hal/src/i2s/parallel.rs b/esp-hal/src/i2s/parallel.rs index 7af20a17721..1bb0d8cc7a2 100644 --- a/esp-hal/src/i2s/parallel.rs +++ b/esp-hal/src/i2s/parallel.rs @@ -39,7 +39,7 @@ //! //! ```rust, no_run #![doc = crate::before_snippet!()] -//! # use esp_hal::dma::{Dma, DmaTxBuf}; +//! # use esp_hal::dma::DmaTxBuf; //! # use esp_hal::dma_buffers; //! # use esp_hal::delay::Delay; //! # use esp_hal::i2s::parallel::{I2sParallel, TxEightBits}; @@ -48,8 +48,7 @@ //! const BUFFER_SIZE: usize = 256; //! //! let delay = Delay::new(); -//! let dma = Dma::new(peripherals.DMA); -//! let dma_channel = dma.i2s1channel; +//! let dma_channel = peripherals.DMA_I2S1; //! let i2s = peripherals.I2S1; //! let clock = peripherals.GPIO25; //! diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index e5998faef0a..ad772bf7084 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -19,10 +19,6 @@ //! # use esp_hal::lcd_cam::{cam::{Camera, RxEightBits}, LcdCam}; //! # use fugit::RateExtU32; //! # use esp_hal::dma_rx_stream_buffer; -//! # use esp_hal::dma::Dma; -//! -//! # let dma = Dma::new(peripherals.DMA); -//! # let channel = dma.channel0; //! //! # let dma_buf = dma_rx_stream_buffer!(20 * 1000, 1000); //! @@ -44,7 +40,7 @@ //! let lcd_cam = LcdCam::new(peripherals.LCD_CAM); //! let mut camera = Camera::new( //! lcd_cam.cam, -//! channel, +//! peripherals.DMA_CH0, //! data_pins, //! 20u32.MHz(), //! ) diff --git a/esp-hal/src/lcd_cam/lcd/dpi.rs b/esp-hal/src/lcd_cam/lcd/dpi.rs index 42cef5ed496..c7330a44826 100644 --- a/esp-hal/src/lcd_cam/lcd/dpi.rs +++ b/esp-hal/src/lcd_cam/lcd/dpi.rs @@ -24,11 +24,8 @@ //! # } //! # }; //! # use esp_hal::dma_loop_buffer; -//! # use esp_hal::dma::{Dma, DmaPriority}; -//! -//! # let dma = Dma::new(peripherals.DMA); -//! # let channel = dma.channel0; //! +//! # let channel = peripherals.DMA_CH0; //! # let mut dma_buf = dma_loop_buffer!(32); //! //! let lcd_cam = LcdCam::new(peripherals.LCD_CAM); diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index 6b498b00f65..21350a1d92f 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -17,10 +17,7 @@ #![doc = crate::before_snippet!()] //! # use esp_hal::lcd_cam::{LcdCam, lcd::i8080::{Config, I8080, TxEightBits}}; //! # use esp_hal::dma_tx_buffer; -//! # use esp_hal::dma::{Dma, DmaTxBuf}; -//! -//! # let dma = Dma::new(peripherals.DMA); -//! # let channel = dma.channel0; +//! # use esp_hal::dma::DmaTxBuf; //! //! # let mut dma_buf = dma_tx_buffer!(32678).unwrap(); //! @@ -38,7 +35,7 @@ //! //! let mut i8080 = I8080::new( //! lcd_cam.lcd, -//! channel, +//! peripherals.DMA_CH0, //! tx_pins, //! 20.MHz(), //! Config::default(), diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index e23cf8e0459..64707e4622c 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -16,15 +16,13 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::delay::Delay; -//! # use esp_hal::dma::Dma; //! # use esp_hal::dma_buffers; //! # use esp_hal::gpio::NoPin; //! # use esp_hal::parl_io::{BitPackOrder, ParlIoRxOnly, RxFourBits}; //! //! // Initialize DMA buffer and descriptors for data reception //! let (rx_buffer, rx_descriptors, _, _) = dma_buffers!(32000, 0); -//! let dma = Dma::new(peripherals.DMA); -//! let dma_channel = dma.channel0; +//! let dma_channel = peripherals.DMA_CH0; //! //! // Configure the 4-bit input pins and clock pin //! let mut rx_pins = RxFourBits::new( @@ -74,14 +72,12 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::delay::Delay; -//! # use esp_hal::dma::Dma; //! # use esp_hal::dma_buffers; //! # use esp_hal::parl_io::{BitPackOrder, ParlIoTxOnly, TxFourBits, SampleEdge, ClkOutPin, TxPinConfigWithValidPin}; //! //! // Initialize DMA buffer and descriptors for data reception //! let (_, _, tx_buffer, tx_descriptors) = dma_buffers!(0, 32000); -//! let dma = Dma::new(peripherals.DMA); -//! let dma_channel = dma.channel0; +//! let dma_channel = peripherals.DMA_CH0; //! //! // Configure the 4-bit input pins and clock pin //! let tx_pins = TxFourBits::new( diff --git a/esp-hal/src/peripheral.rs b/esp-hal/src/peripheral.rs index 622470d859b..4a817111a84 100644 --- a/esp-hal/src/peripheral.rs +++ b/esp-hal/src/peripheral.rs @@ -246,10 +246,15 @@ mod peripheral_macros { peripherals: [ $( $name:ident <= $from_pac:tt $(($($interrupt:ident),*))? - ), *$(,)? + ),* $(,)? ], pins: [ $( ( $pin:literal, $($pin_tokens:tt)* ) )* + ], + dma_channels: [ + $( + $channel_name:ident : $channel_ty:path + ),* $(,)? ] ) => { @@ -280,6 +285,11 @@ mod peripheral_macros { #[doc = concat!("GPIO", stringify!($pin))] pub []: $crate::gpio::GpioPin<$pin>, )* + + $( + #[doc = concat!(stringify!($channel_name), " DMA channel.")] + pub $channel_name: $crate::dma::$channel_ty, + )* } impl Peripherals { @@ -313,6 +323,10 @@ mod peripheral_macros { $( []: $crate::gpio::GpioPin::<$pin>::steal(), )* + + $( + $channel_name: $crate::dma::$channel_ty::steal(), + )* } } } diff --git a/esp-hal/src/soc/esp32/peripherals.rs b/esp-hal/src/soc/esp32/peripherals.rs index 2bfa72fc05e..cc58dd71561 100644 --- a/esp-hal/src/soc/esp32/peripherals.rs +++ b/esp-hal/src/soc/esp32/peripherals.rs @@ -30,7 +30,6 @@ crate::peripherals! { CPU_CTRL <= virtual, DAC1 <= virtual, DAC2 <= virtual, - DMA <= virtual, EFUSE <= EFUSE, FLASH_ENCRYPTION <= FLASH_ENCRYPTION, FRC_TIMER <= FRC_TIMER, @@ -112,5 +111,11 @@ crate::peripherals! { (37, [Input, Analog, RtcIoInput]) (38, [Input, Analog, RtcIoInput]) (39, [Input, Analog, RtcIoInput]) + ], + dma_channels: [ + DMA_SPI2: Spi2DmaChannel, + DMA_SPI3: Spi3DmaChannel, + DMA_I2S0: I2s0DmaChannel, + DMA_I2S1: I2s1DmaChannel, ] } diff --git a/esp-hal/src/soc/esp32c2/peripherals.rs b/esp-hal/src/soc/esp32c2/peripherals.rs index 6748f4e6ce5..03db06e0a0e 100644 --- a/esp-hal/src/soc/esp32c2/peripherals.rs +++ b/esp-hal/src/soc/esp32c2/peripherals.rs @@ -25,7 +25,6 @@ crate::peripherals! { APB_CTRL <= APB_CTRL, ASSIST_DEBUG <= ASSIST_DEBUG, BT <= virtual, - DMA <= DMA (DMA_CH0), ECC <= ECC, EFUSE <= EFUSE, EXTMEM <= EXTMEM, @@ -72,5 +71,8 @@ crate::peripherals! { (18, [Input, Output]) (19, [Input, Output]) (20, [Input, Output] (0 => U0RXD) ()) + ], + dma_channels: [ + DMA_CH0: DmaChannel0, ] } diff --git a/esp-hal/src/soc/esp32c3/peripherals.rs b/esp-hal/src/soc/esp32c3/peripherals.rs index f4a52d4fc08..00e6548a294 100644 --- a/esp-hal/src/soc/esp32c3/peripherals.rs +++ b/esp-hal/src/soc/esp32c3/peripherals.rs @@ -27,7 +27,6 @@ crate::peripherals! { APB_CTRL <= APB_CTRL, ASSIST_DEBUG <= ASSIST_DEBUG, BT <= virtual, - DMA <= DMA (DMA_CH0,DMA_CH1,DMA_CH2), DS <= DS, EFUSE <= EFUSE, EXTMEM <= EXTMEM, @@ -85,5 +84,10 @@ crate::peripherals! { (19, [Input, Output]) (20, [Input, Output] (0 => U0RXD) ()) (21, [Input, Output] () (0 => U0TXD)) + ], + dma_channels: [ + DMA_CH0: DmaChannel0, + DMA_CH1: DmaChannel1, + DMA_CH2: DmaChannel2, ] } diff --git a/esp-hal/src/soc/esp32c6/peripherals.rs b/esp-hal/src/soc/esp32c6/peripherals.rs index b521161faf9..666e7a252a6 100644 --- a/esp-hal/src/soc/esp32c6/peripherals.rs +++ b/esp-hal/src/soc/esp32c6/peripherals.rs @@ -26,7 +26,6 @@ crate::peripherals! { ASSIST_DEBUG <= ASSIST_DEBUG, ATOMIC <= ATOMIC, BT <= virtual, - DMA <= DMA (DMA_IN_CH0,DMA_IN_CH1,DMA_IN_CH2,DMA_OUT_CH0,DMA_OUT_CH1,DMA_OUT_CH2), DS <= DS, ECC <= ECC, EFUSE <= EFUSE, @@ -130,5 +129,10 @@ crate::peripherals! { (28, [Input, Output] (0 => SPIHD) (0 => SPIHD)) (29, [Input, Output] () (0 => SPICLK_MUX)) (30, [Input, Output] (0 => SPID) (0 => SPID)) + ], + dma_channels: [ + DMA_CH0: DmaChannel0, + DMA_CH1: DmaChannel1, + DMA_CH2: DmaChannel2, ] } diff --git a/esp-hal/src/soc/esp32h2/peripherals.rs b/esp-hal/src/soc/esp32h2/peripherals.rs index 9f2c0cdb7df..b5743079885 100644 --- a/esp-hal/src/soc/esp32h2/peripherals.rs +++ b/esp-hal/src/soc/esp32h2/peripherals.rs @@ -25,7 +25,6 @@ crate::peripherals! { AES <= AES, ASSIST_DEBUG <= ASSIST_DEBUG, BT <= virtual, - DMA <= DMA (DMA_IN_CH0,DMA_IN_CH1,DMA_IN_CH2,DMA_OUT_CH0,DMA_OUT_CH1,DMA_OUT_CH2), DS <= DS, ECC <= ECC, EFUSE <= EFUSE, @@ -117,5 +116,10 @@ crate::peripherals! { (25, [Input, Output] () (2 => FSPICS3)) (26, [Input, Output] () (2 => FSPICS4)) (27, [Input, Output] () (2 => FSPICS5)) + ], + dma_channels: [ + DMA_CH0: DmaChannel0, + DMA_CH1: DmaChannel1, + DMA_CH2: DmaChannel2, ] } diff --git a/esp-hal/src/soc/esp32s2/peripherals.rs b/esp-hal/src/soc/esp32s2/peripherals.rs index fc0cf5917fd..868dd4c1ff5 100644 --- a/esp-hal/src/soc/esp32s2/peripherals.rs +++ b/esp-hal/src/soc/esp32s2/peripherals.rs @@ -26,7 +26,6 @@ crate::peripherals! { AES <= AES, DAC1 <= virtual, DAC2 <= virtual, - DMA <= virtual, DEDICATED_GPIO <= DEDICATED_GPIO, DS <= DS, EFUSE <= EFUSE, @@ -115,5 +114,10 @@ crate::peripherals! { (44, [Input, Output]) (45, [Input, Output]) (46, [Input, Output]) + ], + dma_channels: [ + DMA_SPI2: Spi2DmaChannel, + DMA_SPI3: Spi3DmaChannel, + DMA_I2S0: I2s0DmaChannel, ] } diff --git a/esp-hal/src/soc/esp32s3/peripherals.rs b/esp-hal/src/soc/esp32s3/peripherals.rs index c6ab886c9bf..c27239702c8 100644 --- a/esp-hal/src/soc/esp32s3/peripherals.rs +++ b/esp-hal/src/soc/esp32s3/peripherals.rs @@ -28,7 +28,6 @@ crate::peripherals! { ASSIST_DEBUG <= ASSIST_DEBUG, BT <= virtual, CPU_CTRL <= virtual, - DMA <= DMA (DMA_IN_CH0,DMA_IN_CH1,DMA_IN_CH2,DMA_IN_CH3,DMA_IN_CH4,DMA_OUT_CH0,DMA_OUT_CH1,DMA_OUT_CH2,DMA_OUT_CH3,DMA_OUT_CH4), DS <= DS, EFUSE <= EFUSE, EXTMEM <= EXTMEM, @@ -126,5 +125,12 @@ crate::peripherals! { (46, [Input, Output]) (47, [Input, Output]) (48, [Input, Output]) + ], + dma_channels: [ + DMA_CH0: DmaChannel0, + DMA_CH1: DmaChannel1, + DMA_CH2: DmaChannel2, + DMA_CH3: DmaChannel3, + DMA_CH4: DmaChannel4, ] } diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index 5d7a4d31c43..62a97e4c4ba 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -18,10 +18,8 @@ //! # use esp_hal::dma_buffers; //! # use esp_hal::spi::SpiMode; //! # use esp_hal::spi::slave::Spi; -//! # use esp_hal::dma::Dma; -//! let dma = Dma::new(peripherals.DMA); -#![cfg_attr(pdma, doc = "let dma_channel = dma.spi2channel;")] -#![cfg_attr(gdma, doc = "let dma_channel = dma.channel0;")] +#![cfg_attr(pdma, doc = "let dma_channel = peripherals.DMA_SPI2;")] +#![cfg_attr(gdma, doc = "let dma_channel = peripherals.DMA_CH0;")] //! let sclk = peripherals.GPIO0; //! let miso = peripherals.GPIO1; //! let mosi = peripherals.GPIO2; diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index 40f0a69b31b..937bc497784 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -166,13 +166,18 @@ pub(crate) struct PeripheralGuard { } impl PeripheralGuard { - pub(crate) fn new(p: Peripheral) -> Self { + pub(crate) fn new_with(p: Peripheral, init: fn()) -> Self { if !KEEP_ENABLED.contains(&p) && PeripheralClockControl::enable(p) { PeripheralClockControl::reset(p); + init(); } Self { peripheral: p } } + + pub(crate) fn new(p: Peripheral) -> Self { + Self::new_with(p, || {}) + } } impl Drop for PeripheralGuard { @@ -187,14 +192,19 @@ impl Drop for PeripheralGuard { pub(crate) struct GenericPeripheralGuard {} impl GenericPeripheralGuard

{ - pub(crate) fn new() -> Self { + pub(crate) fn new_with(init: fn()) -> Self { let peripheral = unwrap!(Peripheral::try_from(P)); if !KEEP_ENABLED.contains(&peripheral) && PeripheralClockControl::enable(peripheral) { PeripheralClockControl::reset(peripheral); + init(); } Self {} } + + pub(crate) fn new() -> Self { + Self::new_with(|| {}) + } } impl Drop for GenericPeripheralGuard

{ diff --git a/examples/src/bin/dma_extmem2mem.rs b/examples/src/bin/dma_extmem2mem.rs index bf249d9b149..55c075aec92 100644 --- a/examples/src/bin/dma_extmem2mem.rs +++ b/examples/src/bin/dma_extmem2mem.rs @@ -9,12 +9,7 @@ use aligned::{Aligned, A64}; use esp_alloc as _; use esp_backtrace as _; -use esp_hal::{ - delay::Delay, - dma::{Dma, Mem2Mem}, - dma_descriptors_chunk_size, - prelude::*, -}; +use esp_hal::{delay::Delay, dma::Mem2Mem, dma_descriptors_chunk_size, prelude::*}; use log::{error, info}; extern crate alloc; @@ -67,11 +62,10 @@ fn main() -> ! { let mut intram_buffer = dma_buffer_aligned!(DATA_SIZE, A64); let (rx_descriptors, tx_descriptors) = dma_descriptors_chunk_size!(DATA_SIZE, CHUNK_SIZE); - let dma = Dma::new(peripherals.DMA); let dma_peripheral = peripherals.SPI2; let mut mem2mem = Mem2Mem::new_with_chunk_size( - dma.channel0, + peripherals.DMA_CH0, dma_peripheral, rx_descriptors, tx_descriptors, diff --git a/examples/src/bin/dma_mem2mem.rs b/examples/src/bin/dma_mem2mem.rs index 23dda706764..64304665d83 100644 --- a/examples/src/bin/dma_mem2mem.rs +++ b/examples/src/bin/dma_mem2mem.rs @@ -7,12 +7,7 @@ #![no_main] use esp_backtrace as _; -use esp_hal::{ - delay::Delay, - dma::{Dma, Mem2Mem}, - dma_buffers, - prelude::*, -}; +use esp_hal::{delay::Delay, dma::Mem2Mem, dma_buffers, prelude::*}; use log::{error, info}; const DATA_SIZE: usize = 1024 * 10; @@ -27,14 +22,21 @@ fn main() -> ! { let (mut rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(DATA_SIZE); - let dma = Dma::new(peripherals.DMA); - #[cfg(any(feature = "esp32c2", feature = "esp32c3", feature = "esp32s3"))] - let dma_peripheral = peripherals.SPI2; - #[cfg(not(any(feature = "esp32c2", feature = "esp32c3", feature = "esp32s3")))] - let dma_peripheral = peripherals.MEM2MEM1; + cfg_if::cfg_if! { + if #[cfg(any(feature = "esp32c2", feature = "esp32c3", feature = "esp32s3"))] { + let dma_peripheral = peripherals.SPI2; + } else { + let dma_peripheral = peripherals.MEM2MEM1; + } + } - let mut mem2mem = - Mem2Mem::new(dma.channel0, dma_peripheral, rx_descriptors, tx_descriptors).unwrap(); + let mut mem2mem = Mem2Mem::new( + peripherals.DMA_CH0, + dma_peripheral, + rx_descriptors, + tx_descriptors, + ) + .unwrap(); for i in 0..core::mem::size_of_val(tx_buffer) { tx_buffer[i] = (i % 256) as u8; diff --git a/examples/src/bin/embassy_spi.rs b/examples/src/bin/embassy_spi.rs index becc3e96134..1d7e8f9fd31 100644 --- a/examples/src/bin/embassy_spi.rs +++ b/examples/src/bin/embassy_spi.rs @@ -22,7 +22,7 @@ use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; use esp_backtrace as _; use esp_hal::{ - dma::*, + dma::{DmaRxBuf, DmaTxBuf}, dma_buffers, prelude::*, spi::{ @@ -45,13 +45,11 @@ async fn main(_spawner: Spawner) { let mosi = peripherals.GPIO4; let cs = peripherals.GPIO5; - let dma = Dma::new(peripherals.DMA); - cfg_if::cfg_if! { if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { - let dma_channel = dma.spi2channel; + let dma_channel = peripherals.DMA_SPI2; } else { - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; } } diff --git a/examples/src/bin/spi_loopback_dma_psram.rs b/examples/src/bin/spi_loopback_dma_psram.rs index 5aeb74b8621..72787eb408c 100644 --- a/examples/src/bin/spi_loopback_dma_psram.rs +++ b/examples/src/bin/spi_loopback_dma_psram.rs @@ -25,7 +25,7 @@ use esp_backtrace as _; use esp_hal::{ delay::Delay, - dma::{Dma, DmaBufBlkSize, DmaRxBuf, DmaTxBuf}, + dma::{DmaBufBlkSize, DmaRxBuf, DmaTxBuf}, peripheral::Peripheral, prelude::*, spi::{ @@ -67,9 +67,6 @@ fn main() -> ! { let miso = unsafe { mosi.clone_unchecked() }; let cs = peripherals.GPIO38; - let dma = Dma::new(peripherals.DMA); - let dma_channel = dma.channel0; - let (_, tx_descriptors) = esp_hal::dma_descriptors_chunk_size!(0, DMA_BUFFER_SIZE, DMA_CHUNK_SIZE); let tx_buffer = dma_alloc_buffer!(DMA_BUFFER_SIZE, DMA_ALIGNMENT as usize); @@ -103,7 +100,7 @@ fn main() -> ! { .with_miso(miso) .with_mosi(mosi) .with_cs(cs) - .with_dma(dma_channel); + .with_dma(peripherals.DMA_CH0); delay.delay_millis(100); // delay to let the above messages display diff --git a/examples/src/bin/spi_slave_dma.rs b/examples/src/bin/spi_slave_dma.rs index eaee969c415..5f92755e2eb 100644 --- a/examples/src/bin/spi_slave_dma.rs +++ b/examples/src/bin/spi_slave_dma.rs @@ -32,7 +32,6 @@ use esp_backtrace as _; use esp_hal::{ delay::Delay, - dma::Dma, dma_buffers, gpio::{Input, Level, Output, Pull}, prelude::*, @@ -54,12 +53,11 @@ fn main() -> ! { let slave_mosi = peripherals.GPIO2; let slave_cs = peripherals.GPIO3; - let dma = Dma::new(peripherals.DMA); cfg_if::cfg_if! { if #[cfg(feature = "esp32s2")] { - let dma_channel = dma.spi2channel; + let dma_channel = peripherals.DMA_SPI2; } else { - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; } } diff --git a/hil-test/tests/aes_dma.rs b/hil-test/tests/aes_dma.rs index e560e041dd3..be8eb3d804e 100644 --- a/hil-test/tests/aes_dma.rs +++ b/hil-test/tests/aes_dma.rs @@ -7,7 +7,6 @@ use esp_hal::{ aes::{dma::CipherMode, Aes, Mode}, - dma::Dma, dma_buffers, peripherals::Peripherals, }; @@ -27,8 +26,7 @@ mod tests { #[test] fn test_aes_128_dma_encryption(peripherals: Peripherals) { - let dma = Dma::new(peripherals.DMA); - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; let (mut output, rx_descriptors, input, tx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); @@ -66,8 +64,7 @@ mod tests { #[test] fn test_aes_128_dma_decryption(peripherals: Peripherals) { - let dma = Dma::new(peripherals.DMA); - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; let (mut output, rx_descriptors, input, tx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); @@ -104,8 +101,7 @@ mod tests { #[test] fn test_aes_256_dma_encryption(peripherals: Peripherals) { - let dma = Dma::new(peripherals.DMA); - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; let (mut output, rx_descriptors, input, tx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); @@ -143,8 +139,7 @@ mod tests { #[test] fn test_aes_256_dma_decryption(peripherals: Peripherals) { - let dma = Dma::new(peripherals.DMA); - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; let (mut output, rx_descriptors, input, tx_descriptors) = dma_buffers!(DMA_BUFFER_SIZE); diff --git a/hil-test/tests/dma_mem2mem.rs b/hil-test/tests/dma_mem2mem.rs index 20ac1cfe89b..09961d2517a 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::{AnyGdmaChannel, Dma, DmaChannelConvert, DmaError, Mem2Mem}, + dma::{AnyGdmaChannel, DmaChannelConvert, DmaError, Mem2Mem}, dma_buffers, dma_buffers_chunk_size, dma_descriptors, @@ -37,8 +37,7 @@ mod tests { fn init() -> Context { let peripherals = esp_hal::init(esp_hal::Config::default()); - let dma = Dma::new(peripherals.DMA); - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; cfg_if::cfg_if! { if #[cfg(any(esp32c2, esp32c6, esp32h2))] { diff --git a/hil-test/tests/embassy_interrupt_spi_dma.rs b/hil-test/tests/embassy_interrupt_spi_dma.rs index cc9121bff83..82ddbfd825f 100644 --- a/hil-test/tests/embassy_interrupt_spi_dma.rs +++ b/hil-test/tests/embassy_interrupt_spi_dma.rs @@ -9,7 +9,7 @@ use embassy_time::{Duration, Instant, Ticker}; use esp_hal::{ - dma::{Dma, DmaRxBuf, DmaTxBuf}, + dma::{DmaRxBuf, DmaTxBuf}, dma_buffers, interrupt::{software::SoftwareInterruptControl, Priority}, peripheral::Peripheral, @@ -83,7 +83,6 @@ mod test { #[timeout(3)] async fn dma_does_not_lock_up_when_used_in_different_executors() { let peripherals = esp_hal::init(esp_hal::Config::default()); - let dma = Dma::new(peripherals.DMA); cfg_if::cfg_if! { if #[cfg(systimer)] { @@ -104,12 +103,12 @@ mod test { } cfg_if::cfg_if! { - if #[cfg(pdma)] { - let dma_channel1 = dma.spi2channel; - let dma_channel2 = dma.spi3channel; + if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { + let dma_channel1 = peripherals.DMA_SPI2; + let dma_channel2 = peripherals.DMA_SPI3; } else { - let dma_channel1 = dma.channel0; - let dma_channel2 = dma.channel1; + let dma_channel1 = peripherals.DMA_CH0; + let dma_channel2 = peripherals.DMA_CH1; } } @@ -253,7 +252,6 @@ mod test { } let peripherals = esp_hal::init(esp_hal::Config::default()); - let dma = Dma::new(peripherals.DMA); cfg_if::cfg_if! { if #[cfg(systimer)] { @@ -275,9 +273,9 @@ mod test { cfg_if::cfg_if! { if #[cfg(pdma)] { - let dma_channel = dma.spi2channel; + let dma_channel = peripherals.DMA_SPI2; } else { - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; } } diff --git a/hil-test/tests/i2s.rs b/hil-test/tests/i2s.rs index e5191581085..77bb587e1c5 100644 --- a/hil-test/tests/i2s.rs +++ b/hil-test/tests/i2s.rs @@ -12,7 +12,6 @@ use esp_hal::{ delay::Delay, - dma::Dma, dma_buffers, gpio::{AnyPin, NoPin, Pin}, i2s::master::{DataFormat, I2s, I2sTx, Standard}, @@ -112,13 +111,11 @@ mod tests { fn init() -> Context { let peripherals = esp_hal::init(esp_hal::Config::default()); - let dma = Dma::new(peripherals.DMA); - cfg_if::cfg_if! { - if #[cfg(any(esp32, esp32s2))] { - let dma_channel = dma.i2s0channel; + if #[cfg(pdma)] { + let dma_channel = peripherals.DMA_I2S0; } else { - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; } } diff --git a/hil-test/tests/lcd_cam.rs b/hil-test/tests/lcd_cam.rs index c1002e7fbe0..c682ee25f73 100644 --- a/hil-test/tests/lcd_cam.rs +++ b/hil-test/tests/lcd_cam.rs @@ -6,7 +6,7 @@ #![no_main] use esp_hal::{ - dma::{Dma, DmaChannel, DmaRxBuf, DmaTxBuf}, + dma::{DmaChannel, DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::Level, lcd_cam::{ @@ -55,10 +55,9 @@ mod tests { fn test_camera_can_receive_from_rgb(ctx: Context) { let peripherals = ctx.peripherals; - let dma = Dma::new(peripherals.DMA); let lcd_cam = LcdCam::new(peripherals.LCD_CAM); - let (rx_channel, tx_channel) = dma.channel2.split(); + let (rx_channel, tx_channel) = peripherals.DMA_CH2.split(); let (vsync_in, vsync_out) = peripherals.GPIO6.split(); let (hsync_in, hsync_out) = peripherals.GPIO7.split(); diff --git a/hil-test/tests/lcd_cam_i8080.rs b/hil-test/tests/lcd_cam_i8080.rs index da5ad4df11f..0ce6e842cd6 100644 --- a/hil-test/tests/lcd_cam_i8080.rs +++ b/hil-test/tests/lcd_cam_i8080.rs @@ -6,7 +6,7 @@ #![no_main] use esp_hal::{ - dma::{Dma, DmaTxBuf}, + dma::{DmaChannel0, DmaTxBuf}, dma_buffers, gpio::{GpioPin, NoPin}, lcd_cam::{ @@ -38,7 +38,7 @@ struct Context<'d> { lcd_cam: LcdCam<'d, Blocking>, pcnt: Pcnt<'d>, pins: Pins, - dma: Dma<'d>, + dma: DmaChannel0, dma_buf: DmaTxBuf, } @@ -50,7 +50,6 @@ mod tests { #[init] fn init() -> Context<'static> { let peripherals = esp_hal::init(esp_hal::Config::default()); - let dma = Dma::new(peripherals.DMA); let lcd_cam = LcdCam::new(peripherals.LCD_CAM); let pcnt = Pcnt::new(peripherals.PCNT); @@ -59,7 +58,7 @@ mod tests { Context { lcd_cam, - dma, + dma: peripherals.DMA_CH0, pcnt, pins: Pins { GPIO8: peripherals.GPIO8, @@ -76,13 +75,7 @@ mod tests { fn test_i8080_8bit(ctx: Context<'static>) { let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin); - let i8080 = I8080::new( - ctx.lcd_cam.lcd, - ctx.dma.channel0, - pins, - 20.MHz(), - Config::default(), - ); + let i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, 20.MHz(), Config::default()); let xfer = i8080.send(Command::::None, 0, ctx.dma_buf).unwrap(); xfer.wait().0.unwrap(); @@ -139,15 +132,9 @@ mod tests { NoPin, ); - let mut i8080 = I8080::new( - ctx.lcd_cam.lcd, - ctx.dma.channel0, - pins, - 20.MHz(), - Config::default(), - ) - .with_cs(cs_signal) - .with_ctrl_pins(NoPin, NoPin); + let mut i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, 20.MHz(), Config::default()) + .with_cs(cs_signal) + .with_ctrl_pins(NoPin, NoPin); // This is to make the test values look more intuitive. i8080.set_bit_order(BitOrder::Inverted); @@ -238,7 +225,6 @@ mod tests { .channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); - let channel = ctx.dma.channel0; let pins = TxSixteenBits::new( NoPin, NoPin, @@ -258,7 +244,7 @@ mod tests { unit3_signal, ); - let mut i8080 = I8080::new(ctx.lcd_cam.lcd, channel, pins, 20.MHz(), Config::default()) + let mut i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, 20.MHz(), Config::default()) .with_cs(cs_signal) .with_ctrl_pins(NoPin, NoPin); diff --git a/hil-test/tests/lcd_cam_i8080_async.rs b/hil-test/tests/lcd_cam_i8080_async.rs index b2da394fb0c..f9c49f8f4f0 100644 --- a/hil-test/tests/lcd_cam_i8080_async.rs +++ b/hil-test/tests/lcd_cam_i8080_async.rs @@ -7,7 +7,7 @@ #![no_main] use esp_hal::{ - dma::{Dma, DmaTxBuf}, + dma::{DmaChannel0, DmaTxBuf}, dma_buffers, gpio::NoPin, lcd_cam::{ @@ -23,7 +23,7 @@ const DATA_SIZE: usize = 1024 * 10; struct Context<'d> { lcd_cam: LcdCam<'d, Async>, - dma: Dma<'d>, + dma: DmaChannel0, dma_buf: DmaTxBuf, } @@ -36,14 +36,13 @@ mod tests { async fn init() -> Context<'static> { let peripherals = esp_hal::init(esp_hal::Config::default()); - let dma = Dma::new(peripherals.DMA); let lcd_cam = LcdCam::new(peripherals.LCD_CAM).into_async(); let (_, _, tx_buffer, tx_descriptors) = dma_buffers!(0, DATA_SIZE); let dma_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); Context { lcd_cam, - dma, + dma: peripherals.DMA_CH0, dma_buf, } } @@ -52,13 +51,7 @@ mod tests { async fn test_i8080_8bit(ctx: Context<'static>) { let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin); - let i8080 = I8080::new( - ctx.lcd_cam.lcd, - ctx.dma.channel0, - pins, - 20.MHz(), - Config::default(), - ); + let i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, 20.MHz(), Config::default()); let mut transfer = i8080.send(Command::::None, 0, ctx.dma_buf).unwrap(); diff --git a/hil-test/tests/parl_io_tx.rs b/hil-test/tests/parl_io_tx.rs index 54fbe1f27ba..501d6a07775 100644 --- a/hil-test/tests/parl_io_tx.rs +++ b/hil-test/tests/parl_io_tx.rs @@ -7,7 +7,7 @@ #[cfg(esp32c6)] use esp_hal::parl_io::{TxPinConfigWithValidPin, TxSixteenBits}; use esp_hal::{ - dma::{Dma, DmaChannel0}, + dma::DmaChannel0, gpio::{ interconnect::{InputSignal, OutputSignal}, NoPin, @@ -57,8 +57,7 @@ mod tests { let (valid_loopback, valid) = valid.split(); let pcnt = Pcnt::new(peripherals.PCNT); let pcnt_unit = pcnt.unit0; - let dma = Dma::new(peripherals.DMA); - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; let parl_io = peripherals.PARL_IO; diff --git a/hil-test/tests/parl_io_tx_async.rs b/hil-test/tests/parl_io_tx_async.rs index ab7b202003b..8b9a6a8a04e 100644 --- a/hil-test/tests/parl_io_tx_async.rs +++ b/hil-test/tests/parl_io_tx_async.rs @@ -9,7 +9,7 @@ #[cfg(esp32c6)] use esp_hal::parl_io::{TxPinConfigWithValidPin, TxSixteenBits}; use esp_hal::{ - dma::{Dma, DmaChannel0}, + dma::DmaChannel0, gpio::{ interconnect::{InputSignal, OutputSignal}, NoPin, @@ -59,8 +59,7 @@ mod tests { let (valid_loopback, valid) = valid.split(); let pcnt = Pcnt::new(peripherals.PCNT); let pcnt_unit = pcnt.unit0; - let dma = Dma::new(peripherals.DMA); - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; let parl_io = peripherals.PARL_IO; diff --git a/hil-test/tests/qspi.rs b/hil-test/tests/qspi.rs index 8960f767dea..1c9f46fc371 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::{Dma, DmaRxBuf, DmaTxBuf}, + dma::{DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::{AnyPin, Input, Level, Output, Pull}, prelude::*, @@ -192,13 +192,11 @@ mod tests { let _ = Input::new(&mut pin_mirror, Pull::Down); let _ = Input::new(&mut unconnected_pin, Pull::Down); - let dma = Dma::new(peripherals.DMA); - cfg_if::cfg_if! { - if #[cfg(any(esp32, esp32s2))] { - let dma_channel = dma.spi2channel; + if #[cfg(pdma)] { + let dma_channel = peripherals.DMA_SPI2; } else { - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; } } diff --git a/hil-test/tests/spi_full_duplex.rs b/hil-test/tests/spi_full_duplex.rs index 35a9209acc0..756833d9cc4 100644 --- a/hil-test/tests/spi_full_duplex.rs +++ b/hil-test/tests/spi_full_duplex.rs @@ -12,7 +12,7 @@ use embedded_hal::spi::SpiBus; #[cfg(pcnt)] use embedded_hal_async::spi::SpiBus as SpiBusAsync; use esp_hal::{ - dma::{Dma, DmaDescriptor, DmaRxBuf, DmaTxBuf}, + dma::{DmaDescriptor, DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::{Level, NoPin}, peripheral::Peripheral, @@ -61,13 +61,11 @@ mod tests { let sclk = peripherals.GPIO0; let (_, mosi) = hil_test::common_test_pins!(peripherals); - let dma = Dma::new(peripherals.DMA); - cfg_if::cfg_if! { - if #[cfg(any(esp32, esp32s2))] { - let dma_channel = dma.spi2channel; + if #[cfg(pdma)] { + let dma_channel = peripherals.DMA_SPI2; } else { - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; } } diff --git a/hil-test/tests/spi_half_duplex_read.rs b/hil-test/tests/spi_half_duplex_read.rs index 12b77d1b065..c1c92da8be9 100644 --- a/hil-test/tests/spi_half_duplex_read.rs +++ b/hil-test/tests/spi_half_duplex_read.rs @@ -6,7 +6,7 @@ #![no_main] use esp_hal::{ - dma::{Dma, DmaRxBuf, DmaTxBuf}, + dma::{DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::{Level, Output}, prelude::*, @@ -38,13 +38,11 @@ mod tests { let miso_mirror = Output::new(miso_mirror, Level::High); - let dma = Dma::new(peripherals.DMA); - cfg_if::cfg_if! { - if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { - let dma_channel = dma.spi2channel; + if #[cfg(pdma)] { + let dma_channel = peripherals.DMA_SPI2; } else { - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; } } diff --git a/hil-test/tests/spi_half_duplex_write.rs b/hil-test/tests/spi_half_duplex_write.rs index f09a226ec53..fdd0cf43ba1 100644 --- a/hil-test/tests/spi_half_duplex_write.rs +++ b/hil-test/tests/spi_half_duplex_write.rs @@ -6,7 +6,7 @@ #![no_main] use esp_hal::{ - dma::{Dma, DmaRxBuf, DmaTxBuf}, + dma::{DmaRxBuf, DmaTxBuf}, dma_buffers, gpio::interconnect::InputSignal, pcnt::{channel::EdgeMode, unit::Unit, Pcnt}, @@ -39,13 +39,12 @@ mod tests { let (mosi, _) = hil_test::common_test_pins!(peripherals); let pcnt = Pcnt::new(peripherals.PCNT); - let dma = Dma::new(peripherals.DMA); cfg_if::cfg_if! { - if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { - let dma_channel = dma.spi2channel; + if #[cfg(pdma)] { + let dma_channel = peripherals.DMA_SPI2; } else { - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; } } diff --git a/hil-test/tests/spi_half_duplex_write_psram.rs b/hil-test/tests/spi_half_duplex_write_psram.rs index e0eead9bde9..cb19aafd039 100644 --- a/hil-test/tests/spi_half_duplex_write_psram.rs +++ b/hil-test/tests/spi_half_duplex_write_psram.rs @@ -7,7 +7,7 @@ use defmt::error; use esp_alloc as _; use esp_hal::{ - dma::{Dma, DmaBufBlkSize, DmaRxBuf, DmaTxBuf}, + dma::{DmaBufBlkSize, DmaRxBuf, DmaTxBuf}, dma_buffers, dma_descriptors_chunk_size, gpio::interconnect::InputSignal, @@ -57,9 +57,8 @@ mod tests { let (mosi, _) = hil_test::common_test_pins!(peripherals); let pcnt = Pcnt::new(peripherals.PCNT); - let dma = Dma::new(peripherals.DMA); - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; let (mosi_loopback, mosi) = mosi.split(); diff --git a/hil-test/tests/spi_slave.rs b/hil-test/tests/spi_slave.rs index 299a592a2b4..5a0472619bc 100644 --- a/hil-test/tests/spi_slave.rs +++ b/hil-test/tests/spi_slave.rs @@ -9,7 +9,6 @@ #![no_main] use esp_hal::{ - dma::Dma, dma_buffers, gpio::{Input, Level, Output, Pull}, peripheral::Peripheral, @@ -107,13 +106,11 @@ mod tests { let (sclk_pin, _) = hil_test::common_test_pins!(peripherals); let cs_pin = hil_test::unconnected_pin!(peripherals); - let dma = Dma::new(peripherals.DMA); - cfg_if::cfg_if! { - if #[cfg(any(esp32, esp32s2))] { - let dma_channel = dma.spi2channel; + if #[cfg(pdma)] { + let dma_channel = peripherals.DMA_SPI2; } else { - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; } } diff --git a/qa-test/src/bin/embassy_i2s_read.rs b/qa-test/src/bin/embassy_i2s_read.rs index d6efb56455f..ad12db40d2d 100644 --- a/qa-test/src/bin/embassy_i2s_read.rs +++ b/qa-test/src/bin/embassy_i2s_read.rs @@ -20,7 +20,6 @@ use embassy_executor::Spawner; use esp_backtrace as _; use esp_hal::{ - dma::Dma, dma_buffers, i2s::master::{DataFormat, I2s, Standard}, prelude::*, @@ -36,11 +35,13 @@ async fn main(_spawner: Spawner) { let timg0 = TimerGroup::new(peripherals.TIMG0); esp_hal_embassy::init(timg0.timer0); - let dma = Dma::new(peripherals.DMA); - #[cfg(any(feature = "esp32", feature = "esp32s2"))] - let dma_channel = dma.i2s0channel; - #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] - let dma_channel = dma.channel0; + cfg_if::cfg_if! { + if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { + let dma_channel = peripherals.DMA_I2S0; + } else { + let dma_channel = peripherals.DMA_CH0; + } + } let (rx_buffer, rx_descriptors, _, tx_descriptors) = dma_buffers!(4092 * 4, 0); diff --git a/qa-test/src/bin/embassy_i2s_sound.rs b/qa-test/src/bin/embassy_i2s_sound.rs index 8b1b920c209..9678d976496 100644 --- a/qa-test/src/bin/embassy_i2s_sound.rs +++ b/qa-test/src/bin/embassy_i2s_sound.rs @@ -34,7 +34,6 @@ use embassy_executor::Spawner; use esp_backtrace as _; use esp_hal::{ - dma::Dma, dma_buffers, i2s::master::{DataFormat, I2s, Standard}, prelude::*, @@ -58,11 +57,13 @@ async fn main(_spawner: Spawner) { let timg0 = TimerGroup::new(peripherals.TIMG0); esp_hal_embassy::init(timg0.timer0); - let dma = Dma::new(peripherals.DMA); - #[cfg(any(feature = "esp32", feature = "esp32s2"))] - let dma_channel = dma.i2s0channel; - #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] - let dma_channel = dma.channel0; + cfg_if::cfg_if! { + if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { + let dma_channel = peripherals.DMA_I2S0; + } else { + let dma_channel = peripherals.DMA_CH0; + } + } let (_, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(0, 32000); diff --git a/qa-test/src/bin/lcd_cam_ov2640.rs b/qa-test/src/bin/lcd_cam_ov2640.rs index 77e2b47276b..14f8b690383 100644 --- a/qa-test/src/bin/lcd_cam_ov2640.rs +++ b/qa-test/src/bin/lcd_cam_ov2640.rs @@ -28,7 +28,6 @@ use esp_backtrace as _; use esp_hal::{ delay::Delay, - dma::Dma, dma_rx_stream_buffer, i2c::{ self, @@ -47,8 +46,6 @@ use esp_println::{print, println}; fn main() -> ! { let peripherals = esp_hal::init(esp_hal::Config::default()); - let dma = Dma::new(peripherals.DMA); - let dma_rx_buf = dma_rx_stream_buffer!(20 * 1000, 1000); let cam_siod = peripherals.GPIO4; @@ -69,7 +66,7 @@ fn main() -> ! { ); let lcd_cam = LcdCam::new(peripherals.LCD_CAM); - let camera = Camera::new(lcd_cam.cam, dma.channel0, cam_data_pins, 20u32.MHz()) + let camera = Camera::new(lcd_cam.cam, peripherals.DMA_CH0, cam_data_pins, 20u32.MHz()) .with_master_clock(cam_xclk) .with_pixel_clock(cam_pclk) .with_ctrl_pins(cam_vsync, cam_href); diff --git a/qa-test/src/bin/lcd_dpi.rs b/qa-test/src/bin/lcd_dpi.rs index c70bf44368b..6785ff0b8d6 100644 --- a/qa-test/src/bin/lcd_dpi.rs +++ b/qa-test/src/bin/lcd_dpi.rs @@ -34,7 +34,6 @@ use core::iter::{empty, once}; use esp_backtrace as _; use esp_hal::{ delay::Delay, - dma::Dma, dma_loop_buffer, gpio::{Level, Output}, i2c, @@ -70,8 +69,7 @@ fn main() -> ! { .with_sda(peripherals.GPIO47) .with_scl(peripherals.GPIO48); - let dma = Dma::new(peripherals.DMA); - let tx_channel = dma.channel2; + let tx_channel = peripherals.DMA_CH2; let lcd_cam = LcdCam::new(peripherals.LCD_CAM); let mut expander = Tca9554::new(i2c); diff --git a/qa-test/src/bin/lcd_i8080.rs b/qa-test/src/bin/lcd_i8080.rs index e3288aeb553..88d8c96aab4 100644 --- a/qa-test/src/bin/lcd_i8080.rs +++ b/qa-test/src/bin/lcd_i8080.rs @@ -25,7 +25,7 @@ use esp_backtrace as _; use esp_hal::{ delay::Delay, - dma::{Dma, DmaTxBuf}, + dma::DmaTxBuf, dma_tx_buffer, gpio::{Input, Level, Output, Pull}, lcd_cam::{ @@ -47,8 +47,6 @@ fn main() -> ! { let lcd_wr = peripherals.GPIO47; // Write clock let lcd_te = peripherals.GPIO48; // Frame sync - let dma = Dma::new(peripherals.DMA); - let dma_tx_buf = dma_tx_buffer!(4000).unwrap(); let delay = Delay::new(); @@ -71,7 +69,7 @@ fn main() -> ! { let lcd_cam = LcdCam::new(peripherals.LCD_CAM); let i8080 = I8080::new( lcd_cam.lcd, - dma.channel0, + peripherals.DMA_CH0, tx_pins, 20.MHz(), Config::default(), diff --git a/qa-test/src/bin/qspi_flash.rs b/qa-test/src/bin/qspi_flash.rs index 46552163fa9..861a3f4eb67 100644 --- a/qa-test/src/bin/qspi_flash.rs +++ b/qa-test/src/bin/qspi_flash.rs @@ -30,7 +30,7 @@ use esp_backtrace as _; use esp_hal::{ delay::Delay, - dma::{Dma, DmaRxBuf, DmaTxBuf}, + dma::{DmaRxBuf, DmaTxBuf}, dma_buffers, prelude::*, spi::{ @@ -63,13 +63,11 @@ fn main() -> ! { } } - let dma = Dma::new(peripherals.DMA); - cfg_if::cfg_if! { if #[cfg(any(feature = "esp32", feature = "esp32s2"))] { - let dma_channel = dma.spi2channel; + let dma_channel = peripherals.DMA_SPI2; } else { - let dma_channel = dma.channel0; + let dma_channel = peripherals.DMA_CH0; } } From 5c3dbfb0ae44ab628cc7538a4dc6c3f1df819904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Sat, 23 Nov 2024 14:39:56 +0100 Subject: [PATCH 2/3] Initialize DMA in the critical section needed for clock management --- esp-hal/src/dma/gdma.rs | 4 +- esp-hal/src/dma/pdma.rs | 3 +- esp-hal/src/system.rs | 111 ++++++++++++++++++++++++---------------- 3 files changed, 73 insertions(+), 45 deletions(-) diff --git a/esp-hal/src/dma/gdma.rs b/esp-hal/src/dma/gdma.rs index 1b363d83504..bc4154e2b8a 100644 --- a/esp-hal/src/dma/gdma.rs +++ b/esp-hal/src/dma/gdma.rs @@ -14,6 +14,8 @@ //! //! PS: Note that the number of DMA channels is chip-specific. +use critical_section::CriticalSection; + use crate::{ dma::*, interrupt::Priority, @@ -775,7 +777,7 @@ crate::impl_dma_eligible! { } } -pub(super) fn init_dma() { +pub(super) fn init_dma(_cs: CriticalSection<'_>) { let dma = unsafe { crate::soc::peripherals::DMA::steal() }; dma.misc_conf().modify(|_, w| w.ahbm_rst_inter().set_bit()); dma.misc_conf() diff --git a/esp-hal/src/dma/pdma.rs b/esp-hal/src/dma/pdma.rs index e5953fcf2af..8049f2b8ebb 100644 --- a/esp-hal/src/dma/pdma.rs +++ b/esp-hal/src/dma/pdma.rs @@ -11,6 +11,7 @@ //! [SPI]: ../spi/index.html //! [I2S]: ../i2s/index.html +use critical_section::CriticalSection; use portable_atomic::{AtomicBool, Ordering}; use crate::{ @@ -875,7 +876,7 @@ crate::impl_dma_eligible!([I2s0DmaChannel] I2S0 => I2s0); #[cfg(i2s1)] crate::impl_dma_eligible!([I2s1DmaChannel] I2S1 => I2s1); -pub(super) fn init_dma() { +pub(super) fn init_dma(_cs: CriticalSection<'_>) { #[cfg(esp32)] { // (only) on ESP32 we need to configure DPORT for the SPI DMA channels diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index 937bc497784..c69da05fd90 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -5,10 +5,9 @@ //! This `system` module defines the available radio peripherals and provides an //! interface to control and configure radio clocks. -use core::sync::atomic::Ordering; +use core::cell::RefCell; -use critical_section::CriticalSection; -use portable_atomic::AtomicUsize; +use critical_section::{CriticalSection, Mutex}; use strum::{EnumCount, EnumIter, IntoEnumIterator}; use crate::peripherals::SYSTEM; @@ -145,19 +144,22 @@ impl Peripheral { } } -static PERIPHERAL_REF_COUNT: [AtomicUsize; Peripheral::COUNT] = - [const { AtomicUsize::new(0) }; Peripheral::COUNT]; +static PERIPHERAL_REF_COUNT: Mutex> = + Mutex::new(RefCell::new([0; Peripheral::COUNT])); /// Disable all peripherals. /// /// Peripherals listed in [KEEP_ENABLED] are NOT disabled. pub(crate) fn disable_peripherals() { - for p in Peripheral::iter() { - if KEEP_ENABLED.contains(&p) { - continue; + // Take the critical section up front to avoid taking it multiple times. + critical_section::with(|cs| { + for p in Peripheral::iter() { + if KEEP_ENABLED.contains(&p) { + continue; + } + PeripheralClockControl::enable_forced_with_cs(p, false, true, cs); } - PeripheralClockControl::enable_forced(p, false, true); - } + }) } #[derive(Debug)] @@ -192,18 +194,22 @@ impl Drop for PeripheralGuard { pub(crate) struct GenericPeripheralGuard {} impl GenericPeripheralGuard

{ - pub(crate) fn new_with(init: fn()) -> Self { + pub(crate) fn new_with(init: fn(CriticalSection<'_>)) -> Self { let peripheral = unwrap!(Peripheral::try_from(P)); - if !KEEP_ENABLED.contains(&peripheral) && PeripheralClockControl::enable(peripheral) { - PeripheralClockControl::reset(peripheral); - init(); - } + critical_section::with(|cs| { + if !KEEP_ENABLED.contains(&peripheral) + && PeripheralClockControl::enable_with_cs(peripheral, cs) + { + PeripheralClockControl::reset(peripheral); + init(cs); + } + }); Self {} } pub(crate) fn new() -> Self { - Self::new_with(|| {}) + Self::new_with(|_| {}) } } @@ -221,7 +227,7 @@ pub(crate) struct PeripheralClockControl; #[cfg(not(any(esp32c6, esp32h2)))] impl PeripheralClockControl { - fn enable_internal(peripheral: Peripheral, enable: bool, _cs: &CriticalSection<'_>) { + fn enable_internal(peripheral: Peripheral, enable: bool, _cs: CriticalSection<'_>) { debug!("Enable {:?} {}", peripheral, enable); let system = unsafe { &*SYSTEM::PTR }; @@ -605,7 +611,7 @@ impl PeripheralClockControl { #[cfg(any(esp32c6, esp32h2))] impl PeripheralClockControl { - fn enable_internal(peripheral: Peripheral, enable: bool, _cs: &CriticalSection<'_>) { + fn enable_internal(peripheral: Peripheral, enable: bool, _cs: CriticalSection<'_>) { debug!("Enable {:?} {}", peripheral, enable); let system = unsafe { &*SYSTEM::PTR }; @@ -981,6 +987,16 @@ impl PeripheralClockControl { Self::enable_forced(peripheral, true, false) } + /// Enables the given peripheral. + /// + /// This keeps track of enabling a peripheral - i.e. a peripheral + /// is only enabled with the first call attempt to enable it. + /// + /// Returns `true` if it actually enabled the peripheral. + pub(crate) fn enable_with_cs(peripheral: Peripheral, cs: CriticalSection<'_>) -> bool { + Self::enable_forced_with_cs(peripheral, true, false, cs) + } + /// Disables the given peripheral. /// /// This keeps track of disabling a peripheral - i.e. it only @@ -994,34 +1010,43 @@ impl PeripheralClockControl { } pub(crate) fn enable_forced(peripheral: Peripheral, enable: bool, force: bool) -> bool { - critical_section::with(|cs| { - if !force { - if enable { - let prev = - PERIPHERAL_REF_COUNT[peripheral as usize].fetch_add(1, Ordering::Relaxed); - if prev > 0 { - return false; - } - } else { - let prev = - PERIPHERAL_REF_COUNT[peripheral as usize].fetch_sub(1, Ordering::Relaxed); - assert!(prev != 0); - if prev > 1 { - return false; - } - }; - } else if !enable { - assert!(PERIPHERAL_REF_COUNT[peripheral as usize].swap(0, Ordering::Relaxed) == 0); - } + critical_section::with(|cs| Self::enable_forced_with_cs(peripheral, enable, force, cs)) + } - if !enable { - Self::reset(peripheral); - } + pub(crate) fn enable_forced_with_cs( + peripheral: Peripheral, + enable: bool, + force: bool, + cs: CriticalSection<'_>, + ) -> bool { + let mut ref_counts = PERIPHERAL_REF_COUNT.borrow_ref_mut(cs); + let ref_count = &mut ref_counts[peripheral as usize]; + if !force { + if enable { + let prev = *ref_count; + *ref_count += 1; + if prev > 0 { + return false; + } + } else { + let prev = *ref_count; + *ref_count -= 1; + if prev > 1 { + return false; + } + assert!(prev != 0); + }; + } else if !enable { + assert!(*ref_count == 0); + } + + if !enable { + Self::reset(peripheral); + } - Self::enable_internal(peripheral, enable, &cs); + Self::enable_internal(peripheral, enable, cs); - true - }) + true } } From 25169266dcb4cb52fc9c5453c5dff988f2db47e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 25 Nov 2024 09:18:41 +0100 Subject: [PATCH 3/3] Update esp-hal/MIGRATING-0.22.md Co-authored-by: Jesse Braham --- esp-hal/MIGRATING-0.22.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-hal/MIGRATING-0.22.md b/esp-hal/MIGRATING-0.22.md index dee0b5734a9..8ed0777b4b4 100644 --- a/esp-hal/MIGRATING-0.22.md +++ b/esp-hal/MIGRATING-0.22.md @@ -5,7 +5,7 @@ ### Accessing channel objects DMA channels are now available through the `Peripherals` struct, which is returned -by `esp_hal::init()`. The channels themselves have been renamed to match other peripheral signletons. +by `esp_hal::init()`. The channels themselves have been renamed to match other peripheral singletons. - ESP32-C2, C3, C6, H2 and S3: `channelX -> DMA_CHX` - ESP32 and S2: `spiXchannel -> DMA_SPIX`, `i2sXchannel -> DMA_I2SX`