Skip to content

Commit

Permalink
Move DMA channels into Peripherals
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani committed Nov 23, 2024
1 parent 09511c7 commit ecfd132
Show file tree
Hide file tree
Showing 52 changed files with 295 additions and 347 deletions.
4 changes: 3 additions & 1 deletion esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,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)
Expand All @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `dma::{Channel, ChannelRx, ChannelTx}::set_priority` for GDMA devices (#2403)
- `SystemTimer`s `Alarm`s are now type erased (#2576)
- `TimerGroup` `Timer`s are now type erased (#2581)
- DMA channels are now available via the `Peripherals` struct, and have been renamed accordingly. (#2545)

### Fixed

Expand All @@ -40,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The DMA channel objects no longer have `tx` and `rx` fields. (#2526)
- `SysTimerAlarms` has been removed, alarms are now part of the `SystemTimer` struct (#2576)
- `FrozenUnit`, `AnyUnit`, `SpecificUnit`, `SpecificComparator`, `AnyComparator` have been removed from `systimer` (#2576)
- The `Dma` structure has been removed. (#2545)

## [0.22.0] - 2024-11-20

Expand Down
14 changes: 14 additions & 0 deletions esp-hal/MIGRATING-0.22.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
56 changes: 6 additions & 50 deletions esp-hal/src/dma/gdma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use crate::{
macros::handler,
peripheral::{Peripheral, PeripheralRef},
peripherals::Interrupt,
system::{self, PeripheralClockControl},
};

/// An arbitrary GDMA channel
Expand Down Expand Up @@ -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<P = crate::peripherals::DMA> + '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());
}
45 changes: 35 additions & 10 deletions esp-hal/src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -70,6 +68,7 @@ use crate::{
peripheral::{Peripheral, PeripheralRef},
peripherals::Interrupt,
soc::is_slice_in_dram,
system,
Async,
Blocking,
Cpu,
Expand Down Expand Up @@ -1665,7 +1664,7 @@ impl<DEG: DmaChannel> DmaChannelConvert<DEG> 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
Expand All @@ -1679,7 +1678,6 @@ impl<DEG: DmaChannel> DmaChannelConvert<DEG> 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>,
Expand All @@ -1691,10 +1689,8 @@ impl<DEG: DmaChannel> DmaChannelConvert<DEG> 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,
Expand Down Expand Up @@ -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)]
Expand All @@ -1812,6 +1823,7 @@ where
{
pub(crate) rx_impl: PeripheralRef<'a, CH>,
pub(crate) _phantom: PhantomData<M>,
pub(crate) _guard: PeripheralGuard,
}

impl<'a, CH> ChannelRx<'a, Blocking, CH>
Expand All @@ -1821,6 +1833,9 @@ where
/// Creates a new RX channel half.
pub fn new(rx_impl: impl Peripheral<P = CH> + '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.
Expand All @@ -1836,6 +1851,7 @@ where
Self {
rx_impl,
_phantom: PhantomData,
_guard,
}
}

Expand All @@ -1848,6 +1864,7 @@ where
ChannelRx {
rx_impl: self.rx_impl,
_phantom: PhantomData,
_guard: self._guard,
}
}

Expand Down Expand Up @@ -1878,6 +1895,7 @@ where
ChannelRx {
rx_impl: self.rx_impl,
_phantom: PhantomData,
_guard: self._guard,
}
}
}
Expand Down Expand Up @@ -2095,6 +2113,7 @@ where
{
pub(crate) tx_impl: PeripheralRef<'a, CH>,
pub(crate) _phantom: PhantomData<M>,
pub(crate) _guard: PeripheralGuard,
}

impl<'a, CH> ChannelTx<'a, Blocking, CH>
Expand All @@ -2104,6 +2123,9 @@ where
/// Creates a new TX channel half.
pub fn new(tx_impl: impl Peripheral<P = CH> + '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);
Expand All @@ -2113,6 +2135,7 @@ where
Self {
tx_impl,
_phantom: PhantomData,
_guard,
}
}

Expand All @@ -2125,6 +2148,7 @@ where
ChannelTx {
tx_impl: self.tx_impl,
_phantom: PhantomData,
_guard: self._guard,
}
}

Expand Down Expand Up @@ -2155,6 +2179,7 @@ where
ChannelTx {
tx_impl: self.tx_impl,
_phantom: PhantomData,
_guard: self._guard,
}
}
}
Expand Down
59 changes: 12 additions & 47 deletions esp-hal/src/dma/pdma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use crate::{
macros::handler,
peripheral::{Peripheral, PeripheralRef},
peripherals::Interrupt,
system::{self, PeripheralClockControl},
};

type SpiRegisterBlock = crate::peripherals::spi2::RegisterBlock;
Expand Down Expand Up @@ -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<P = crate::peripherals::DMA> + '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) });
}
}

Expand Down
9 changes: 5 additions & 4 deletions esp-hal/src/i2s/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
//!
Expand Down
6 changes: 1 addition & 5 deletions esp-hal/src/lcd_cam/cam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
//!
Expand All @@ -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(),
//! )
Expand Down
Loading

0 comments on commit ecfd132

Please sign in to comment.