Peripheralize DMA channels (#3372)

This commit is contained in:
Dániel Buga 2025-04-14 11:09:54 +02:00 committed by GitHub
parent a98a96821b
commit 11ba2509d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 178 additions and 211 deletions

View File

@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Migrate SPI slave driver to newer DMA API (#3326)
- Migrate DMA memcpy driver to newer DMA API (#3327)
- Moved numbered GPIO pin types from `esp_hal::gpio::GpioPin<N>` to `esp_hal::peripherals::GPION<'_>` (#3349)
- Moved DMA channel types from `esp_hal::dma::DmaChannelN`/`esp_hal::dma::XYDmaChannel` to `esp_hal::peripherals::DMA_XY` (#3372)
- `ParlIoFullDuplex`, `ParlIoTxOnly` and `ParlIoRxOnly` have been merged into `ParlIo` (#3366)
### Fixed

View File

@ -56,6 +56,24 @@ If a driver works with multiple peripheral instances, e.g. `SPI`:
+fn new(spi: impl Instance + Into<AnySpi<'d>>)
```
## DMA changes
### DMA channel types are now consistent with other peripheral singletons
For compatibility with third party libraries, as well as for consistency with other peripherals,
the DMA channel types (e.g. `DmaChannel0`/`Spi2DmaChannel`) have been replaced by
`esp_hal::peripherals::DMA_channel<'d>` types.
```diff
-use esp_hal::gpio::DmaChannel0;
+use esp_hal::peripherals::DMA_CH0;
```
```diff
-use esp_hal::gpio::Spi2DmaChannel;
+use esp_hal::peripherals::DMA_SPI2;
```
## GPIO changes
### GPIO pins are now consistent with other peripheral singletons

View File

@ -220,30 +220,30 @@ impl TxRegisterAccess for AnyGdmaTxChannel<'_> {
fn async_handler(&self) -> Option<InterruptHandler> {
match self.channel {
0 => DmaChannel0::handler_out(),
0 => DMA_CH0::handler_out(),
#[cfg(not(esp32c2))]
1 => DmaChannel1::handler_out(),
1 => DMA_CH1::handler_out(),
#[cfg(not(esp32c2))]
2 => DmaChannel2::handler_out(),
2 => DMA_CH2::handler_out(),
#[cfg(esp32s3)]
3 => DmaChannel3::handler_out(),
3 => DMA_CH3::handler_out(),
#[cfg(esp32s3)]
4 => DmaChannel4::handler_out(),
4 => DMA_CH4::handler_out(),
_ => unreachable!(),
}
}
fn peripheral_interrupt(&self) -> Option<Interrupt> {
match self.channel {
0 => DmaChannel0::isr_out(),
0 => DMA_CH0::isr_out(),
#[cfg(not(esp32c2))]
1 => DmaChannel1::isr_out(),
1 => DMA_CH1::isr_out(),
#[cfg(not(esp32c2))]
2 => DmaChannel2::isr_out(),
2 => DMA_CH2::isr_out(),
#[cfg(esp32s3)]
3 => DmaChannel3::isr_out(),
3 => DMA_CH3::isr_out(),
#[cfg(esp32s3)]
4 => DmaChannel4::isr_out(),
4 => DMA_CH4::isr_out(),
_ => unreachable!(),
}
}
@ -450,30 +450,30 @@ impl RxRegisterAccess for AnyGdmaRxChannel<'_> {
fn async_handler(&self) -> Option<InterruptHandler> {
match self.channel {
0 => DmaChannel0::handler_in(),
0 => DMA_CH0::handler_in(),
#[cfg(not(esp32c2))]
1 => DmaChannel1::handler_in(),
1 => DMA_CH1::handler_in(),
#[cfg(not(esp32c2))]
2 => DmaChannel2::handler_in(),
2 => DMA_CH2::handler_in(),
#[cfg(esp32s3)]
3 => DmaChannel3::handler_in(),
3 => DMA_CH3::handler_in(),
#[cfg(esp32s3)]
4 => DmaChannel4::handler_in(),
4 => DMA_CH4::handler_in(),
_ => unreachable!(),
}
}
fn peripheral_interrupt(&self) -> Option<Interrupt> {
match self.channel {
0 => DmaChannel0::isr_in(),
0 => DMA_CH0::isr_in(),
#[cfg(not(esp32c2))]
1 => DmaChannel1::isr_in(),
1 => DMA_CH1::isr_in(),
#[cfg(not(esp32c2))]
2 => DmaChannel2::isr_in(),
2 => DMA_CH2::isr_in(),
#[cfg(esp32s3)]
3 => DmaChannel3::isr_in(),
3 => DMA_CH3::isr_in(),
#[cfg(esp32s3)]
4 => DmaChannel4::isr_in(),
4 => DMA_CH4::isr_in(),
_ => unreachable!(),
}
}
@ -589,9 +589,8 @@ impl<CH: DmaChannel, Dm: DriverMode> Channel<Dm, CH> {
macro_rules! impl_channel {
($num:literal, $interrupt_in:ident $(, $interrupt_out:ident)? ) => {
paste::paste! {
$crate::create_peripheral!([<DmaChannel $num>] <= virtual);
impl [<DmaChannel $num>]<'_> {
use $crate::peripherals::[<DMA_CH $num>];
impl [<DMA_CH $num>]<'_> {
fn handler_in() -> Option<InterruptHandler> {
$crate::if_set! {
$({
@ -599,15 +598,15 @@ macro_rules! impl_channel {
#[handler(priority = Priority::max())]
fn interrupt_handler_in() {
$crate::ignore!($interrupt_out);
super::asynch::handle_in_interrupt::<[< DmaChannel $num >]<'static>>();
super::asynch::handle_in_interrupt::<[< DMA_CH $num >]<'static>>();
}
Some(interrupt_handler_in)
})?,
{
#[handler(priority = Priority::max())]
fn interrupt_handler() {
super::asynch::handle_in_interrupt::<[< DmaChannel $num >]<'static>>();
super::asynch::handle_out_interrupt::<[< DmaChannel $num >]<'static>>();
super::asynch::handle_in_interrupt::<[< DMA_CH $num >]<'static>>();
super::asynch::handle_out_interrupt::<[< DMA_CH $num >]<'static>>();
}
Some(interrupt_handler)
}
@ -624,7 +623,7 @@ macro_rules! impl_channel {
#[handler(priority = Priority::max())]
fn interrupt_handler_out() {
$crate::ignore!($interrupt_out);
super::asynch::handle_out_interrupt::<[< DmaChannel $num >]<'static>>();
super::asynch::handle_out_interrupt::<[< DMA_CH $num >]<'static>>();
}
Some(interrupt_handler_out)
})?,
@ -637,7 +636,7 @@ macro_rules! impl_channel {
}
}
impl<'d> DmaChannel for [<DmaChannel $num>]<'d> {
impl<'d> DmaChannel for [<DMA_CH $num>]<'d> {
type Rx = AnyGdmaRxChannel<'d>;
type Tx = AnyGdmaTxChannel<'d>;
@ -655,7 +654,7 @@ macro_rules! impl_channel {
}
}
impl<'d> DmaChannelConvert<AnyGdmaChannel<'d>> for [<DmaChannel $num>]<'d> {
impl<'d> DmaChannelConvert<AnyGdmaChannel<'d>> for [<DMA_CH $num>]<'d> {
fn degrade(self) -> AnyGdmaChannel<'d> {
AnyGdmaChannel {
channel: $num,
@ -664,7 +663,7 @@ macro_rules! impl_channel {
}
}
impl<'d> DmaChannelConvert<AnyGdmaRxChannel<'d>> for [<DmaChannel $num>]<'d> {
impl<'d> DmaChannelConvert<AnyGdmaRxChannel<'d>> for [<DMA_CH $num>]<'d> {
fn degrade(self) -> AnyGdmaRxChannel<'d> {
AnyGdmaRxChannel {
channel: $num,
@ -673,7 +672,7 @@ macro_rules! impl_channel {
}
}
impl<'d> DmaChannelConvert<AnyGdmaTxChannel<'d>> for [<DmaChannel $num>]<'d> {
impl<'d> DmaChannelConvert<AnyGdmaTxChannel<'d>> for [<DMA_CH $num>]<'d> {
fn degrade(self) -> AnyGdmaTxChannel<'d> {
AnyGdmaTxChannel {
channel: $num,
@ -682,7 +681,7 @@ macro_rules! impl_channel {
}
}
impl DmaChannelExt for [<DmaChannel $num>]<'_> {
impl DmaChannelExt for [<DMA_CH $num>]<'_> {
fn rx_interrupts() -> impl InterruptAccess<DmaRxInterrupt> {
AnyGdmaRxChannel {
channel: $num,

View File

@ -11,8 +11,6 @@ use crate::dma::{
DmaChannelConvert,
DmaEligible,
};
#[cfg(esp32s2)]
use crate::dma::{CopyDmaChannel, CopyDmaRxChannel, CopyDmaTxChannel};
use crate::{
dma::{
BurstConfig,
@ -33,6 +31,11 @@ use crate::{
Blocking,
DriverMode,
};
#[cfg(esp32s2)]
use crate::{
dma::{CopyDmaRxChannel, CopyDmaTxChannel},
peripherals::DMA_COPY,
};
/// DMA Memory to Memory pseudo-Peripheral
///
@ -88,7 +91,7 @@ impl<'d> Mem2Mem<'d, Blocking> {
/// Create a new Mem2Mem instance.
#[cfg(esp32s2)]
pub fn new(channel: CopyDmaChannel<'d>) -> Self {
pub fn new(channel: DMA_COPY<'d>) -> Self {
let channel = Channel::new(channel);
// The S2's COPY DMA channel doesn't care about this. Once support for other

View File

@ -949,6 +949,7 @@ impl From<u32> for Owner {
}
#[doc(hidden)]
#[instability::unstable]
pub trait DmaEligible {
/// The most specific DMA channel type usable by this peripheral.
type Dma: DmaChannel;
@ -1600,10 +1601,10 @@ pub type PeripheralRxChannel<T> = <PeripheralDmaChannel<T> as DmaChannel>::Rx;
/// Helper type to get the DMA Tx channel for a peripheral.
pub type PeripheralTxChannel<T> = <PeripheralDmaChannel<T> as DmaChannel>::Tx;
#[doc(hidden)]
#[instability::unstable]
pub trait DmaRxChannel: RxRegisterAccess + InterruptAccess<DmaRxInterrupt> {}
#[doc(hidden)]
#[instability::unstable]
pub trait DmaTxChannel: TxRegisterAccess + InterruptAccess<DmaTxInterrupt> {}
/// A description of a DMA Channel.
@ -1695,6 +1696,7 @@ impl<DEG: DmaChannel> DmaChannelConvert<DEG> for DEG {
/// # Ok(())
/// # }
/// ```
#[allow(private_bounds)]
pub trait DmaChannelFor<P: DmaEligible>:
DmaChannel + DmaChannelConvert<PeripheralDmaChannel<P>>
{
@ -1713,6 +1715,7 @@ where
///
/// You can use this in places where a peripheral driver would expect a
/// `DmaRxChannel` implementation.
#[allow(private_bounds)]
pub trait RxChannelFor<P: DmaEligible>: DmaChannelConvert<PeripheralRxChannel<P>> {}
impl<P, RX> RxChannelFor<P> for RX
where
@ -1728,6 +1731,7 @@ where
///
/// You can use this in places where a peripheral driver would expect a
/// `DmaTxChannel` implementation.
#[allow(private_bounds)]
pub trait TxChannelFor<PER: DmaEligible>: DmaChannelConvert<PeripheralTxChannel<PER>> {}
impl<P, TX> TxChannelFor<P> for TX
where
@ -2516,6 +2520,7 @@ pub(crate) mod dma_private {
fn peripheral_dma_stop(&mut self);
}
#[instability::unstable]
pub trait DmaSupportTx: DmaSupport {
type Channel: DmaTxChannel;
@ -2524,6 +2529,7 @@ pub(crate) mod dma_private {
fn chain(&mut self) -> &mut DescriptorChain;
}
#[instability::unstable]
pub trait DmaSupportRx: DmaSupport {
type Channel: DmaRxChannel;

View File

@ -4,7 +4,7 @@ use crate::{
asynch::AtomicWaker,
dma::*,
interrupt::{InterruptHandler, Priority},
peripherals::{Interrupt, COPY_DMA},
peripherals::{Interrupt, DMA_COPY},
};
pub(super) type CopyRegisterBlock = crate::pac::copy_dma::RegisterBlock;
@ -12,7 +12,7 @@ pub(super) type CopyRegisterBlock = crate::pac::copy_dma::RegisterBlock;
/// The RX half of a Copy DMA channel.
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CopyDmaRxChannel<'d>(pub(crate) CopyDmaChannel<'d>);
pub struct CopyDmaRxChannel<'d>(pub(crate) DMA_COPY<'d>);
impl CopyDmaRxChannel<'_> {
fn regs(&self) -> &CopyRegisterBlock {
@ -26,7 +26,7 @@ impl DmaRxChannel for CopyDmaRxChannel<'_> {}
/// The TX half of a Copy DMA channel.
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CopyDmaTxChannel<'d>(pub(crate) CopyDmaChannel<'d>);
pub struct CopyDmaTxChannel<'d>(pub(crate) DMA_COPY<'d>);
impl CopyDmaTxChannel<'_> {
fn regs(&self) -> &CopyRegisterBlock {
@ -359,29 +359,7 @@ impl InterruptAccess<DmaRxInterrupt> for CopyDmaRxChannel<'_> {
}
}
#[doc = "DMA channel suitable for COPY"]
#[non_exhaustive]
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CopyDmaChannel<'d> {
_lifetime: core::marker::PhantomData<&'d mut ()>,
}
impl crate::private::Sealed for CopyDmaChannel<'_> {}
impl CopyDmaChannel<'_> {
#[doc = r" Unsafely constructs a new DMA channel."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc = r" The caller must ensure that only a single instance is used."]
pub unsafe fn steal() -> Self {
Self {
_lifetime: core::marker::PhantomData,
}
}
}
impl<'d> DmaChannel for CopyDmaChannel<'d> {
impl<'d> DmaChannel for DMA_COPY<'d> {
type Rx = CopyDmaRxChannel<'d>;
type Tx = CopyDmaTxChannel<'d>;
unsafe fn split_internal(self, _: crate::private::Internal) -> (Self::Rx, Self::Tx) {
@ -391,7 +369,7 @@ impl<'d> DmaChannel for CopyDmaChannel<'d> {
)
}
}
impl DmaChannelExt for CopyDmaChannel<'_> {
impl DmaChannelExt for DMA_COPY<'_> {
fn rx_interrupts() -> impl InterruptAccess<DmaRxInterrupt> {
CopyDmaRxChannel(unsafe { Self::steal() })
}
@ -399,10 +377,10 @@ impl DmaChannelExt for CopyDmaChannel<'_> {
CopyDmaTxChannel(unsafe { Self::steal() })
}
}
impl PdmaChannel for CopyDmaChannel<'_> {
impl PdmaChannel for DMA_COPY<'_> {
type RegisterBlock = CopyRegisterBlock;
fn register_block(&self) -> &Self::RegisterBlock {
COPY_DMA::regs()
DMA_COPY::regs()
}
fn tx_waker(&self) -> &'static AtomicWaker {
static WAKER: AtomicWaker = AtomicWaker::new();
@ -421,8 +399,8 @@ impl PdmaChannel for CopyDmaChannel<'_> {
}
fn async_handler(&self) -> InterruptHandler {
pub(crate) extern "C" fn __esp_hal_internal_interrupt_handler() {
super::asynch::handle_in_interrupt::<CopyDmaChannel<'static>>();
super::asynch::handle_out_interrupt::<CopyDmaChannel<'static>>();
super::asynch::handle_in_interrupt::<DMA_COPY<'static>>();
super::asynch::handle_out_interrupt::<DMA_COPY<'static>>();
}
#[allow(non_upper_case_globals)]
pub(crate) static interrupt_handler: InterruptHandler =
@ -438,12 +416,12 @@ impl PdmaChannel for CopyDmaChannel<'_> {
&FLAG
}
}
impl<'d> DmaChannelConvert<CopyDmaRxChannel<'d>> for CopyDmaChannel<'d> {
impl<'d> DmaChannelConvert<CopyDmaRxChannel<'d>> for DMA_COPY<'d> {
fn degrade(self) -> CopyDmaRxChannel<'d> {
CopyDmaRxChannel(self)
}
}
impl<'d> DmaChannelConvert<CopyDmaTxChannel<'d>> for CopyDmaChannel<'d> {
impl<'d> DmaChannelConvert<CopyDmaTxChannel<'d>> for DMA_COPY<'d> {
fn degrade(self) -> CopyDmaTxChannel<'d> {
CopyDmaTxChannel(self)
}

View File

@ -4,7 +4,7 @@ use crate::{
asynch::AtomicWaker,
dma::*,
interrupt::Priority,
peripherals::{Interrupt, CRYPTO_DMA},
peripherals::{Interrupt, DMA_CRYPTO},
};
pub(super) type CryptoRegisterBlock = crate::pac::crypto_dma::RegisterBlock;
@ -12,7 +12,7 @@ pub(super) type CryptoRegisterBlock = crate::pac::crypto_dma::RegisterBlock;
/// The RX half of a Crypto DMA channel.
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CryptoDmaRxChannel<'d>(pub(crate) CryptoDmaChannel<'d>);
pub struct CryptoDmaRxChannel<'d>(pub(crate) DMA_CRYPTO<'d>);
impl CryptoDmaRxChannel<'_> {
fn regs(&self) -> &CryptoRegisterBlock {
@ -26,7 +26,7 @@ impl DmaRxChannel for CryptoDmaRxChannel<'_> {}
/// The TX half of a Crypto DMA channel.
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CryptoDmaTxChannel<'d>(pub(crate) CryptoDmaChannel<'d>);
pub struct CryptoDmaTxChannel<'d>(pub(crate) DMA_CRYPTO<'d>);
impl CryptoDmaTxChannel<'_> {
fn regs(&self) -> &CryptoRegisterBlock {
@ -415,29 +415,7 @@ impl InterruptAccess<DmaRxInterrupt> for CryptoDmaRxChannel<'_> {
}
}
#[doc = "DMA channel suitable for CRYPTO"]
#[non_exhaustive]
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CryptoDmaChannel<'d> {
_lifetime: core::marker::PhantomData<&'d mut ()>,
}
impl crate::private::Sealed for CryptoDmaChannel<'_> {}
impl CryptoDmaChannel<'_> {
#[doc = r" Unsafely constructs a new DMA channel."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc = r" The caller must ensure that only a single instance is used."]
pub unsafe fn steal() -> Self {
Self {
_lifetime: core::marker::PhantomData,
}
}
}
impl<'d> DmaChannel for CryptoDmaChannel<'d> {
impl<'d> DmaChannel for DMA_CRYPTO<'d> {
type Rx = CryptoDmaRxChannel<'d>;
type Tx = CryptoDmaTxChannel<'d>;
unsafe fn split_internal(self, _: crate::private::Internal) -> (Self::Rx, Self::Tx) {
@ -447,7 +425,7 @@ impl<'d> DmaChannel for CryptoDmaChannel<'d> {
)
}
}
impl DmaChannelExt for CryptoDmaChannel<'_> {
impl DmaChannelExt for DMA_CRYPTO<'_> {
fn rx_interrupts() -> impl InterruptAccess<DmaRxInterrupt> {
CryptoDmaRxChannel(unsafe { Self::steal() })
}
@ -455,10 +433,10 @@ impl DmaChannelExt for CryptoDmaChannel<'_> {
CryptoDmaTxChannel(unsafe { Self::steal() })
}
}
impl PdmaChannel for CryptoDmaChannel<'_> {
impl PdmaChannel for DMA_CRYPTO<'_> {
type RegisterBlock = CryptoRegisterBlock;
fn register_block(&self) -> &Self::RegisterBlock {
CRYPTO_DMA::regs()
DMA_CRYPTO::regs()
}
fn tx_waker(&self) -> &'static AtomicWaker {
static WAKER: AtomicWaker = AtomicWaker::new();
@ -477,8 +455,8 @@ impl PdmaChannel for CryptoDmaChannel<'_> {
}
fn async_handler(&self) -> InterruptHandler {
pub(crate) extern "C" fn __esp_hal_internal_interrupt_handler() {
super::asynch::handle_in_interrupt::<CryptoDmaChannel<'static>>();
super::asynch::handle_out_interrupt::<CryptoDmaChannel<'static>>();
super::asynch::handle_in_interrupt::<DMA_CRYPTO<'static>>();
super::asynch::handle_out_interrupt::<DMA_CRYPTO<'static>>();
}
#[allow(non_upper_case_globals)]
pub(crate) static interrupt_handler: crate::interrupt::InterruptHandler =
@ -497,12 +475,12 @@ impl PdmaChannel for CryptoDmaChannel<'_> {
&FLAG
}
}
impl<'d> DmaChannelConvert<CryptoDmaRxChannel<'d>> for CryptoDmaChannel<'d> {
impl<'d> DmaChannelConvert<CryptoDmaRxChannel<'d>> for DMA_CRYPTO<'d> {
fn degrade(self) -> CryptoDmaRxChannel<'d> {
CryptoDmaRxChannel(self)
}
}
impl<'d> DmaChannelConvert<CryptoDmaTxChannel<'d>> for CryptoDmaChannel<'d> {
impl<'d> DmaChannelConvert<CryptoDmaTxChannel<'d>> for DMA_CRYPTO<'d> {
fn degrade(self) -> CryptoDmaTxChannel<'d> {
CryptoDmaTxChannel(self)
}

View File

@ -385,9 +385,9 @@ impl InterruptAccess<DmaRxInterrupt> for AnyI2sDmaRxChannel<'_> {
crate::any_peripheral! {
/// An I2S-compatible type-erased DMA channel.
pub peripheral AnyI2sDmaChannel<'d> {
I2s0(I2s0DmaChannel<'d>),
I2s0(super::DMA_I2S0<'d>),
#[cfg(i2s1)]
I2s1(I2s1DmaChannel<'d>),
I2s1(super::DMA_I2S1<'d>),
}
}

View File

@ -48,9 +48,8 @@ pub trait PdmaChannel: crate::private::Sealed {
macro_rules! impl_pdma_channel {
($peri:ident, $register_block:ident, $instance:ident, $int:ident, [$($compatible:ident),*]) => {
paste::paste! {
$crate::create_peripheral!([<$instance DmaChannel>] <= virtual);
impl<'d> DmaChannel for [<$instance DmaChannel>]<'d> {
use $crate::peripherals::[< $instance >];
impl<'d> DmaChannel for $instance<'d> {
type Rx = [<$peri DmaRxChannel>]<'d>;
type Tx = [<$peri DmaTxChannel>]<'d>;
@ -62,7 +61,7 @@ macro_rules! impl_pdma_channel {
}
}
impl DmaChannelExt for [<$instance DmaChannel>]<'_> {
impl DmaChannelExt for $instance<'_> {
fn rx_interrupts() -> impl InterruptAccess<DmaRxInterrupt> {
[<$peri DmaRxChannel>](unsafe { Self::steal() }.into())
}
@ -71,11 +70,11 @@ macro_rules! impl_pdma_channel {
}
}
impl PdmaChannel for [<$instance DmaChannel>]<'_> {
impl PdmaChannel for $instance<'_> {
type RegisterBlock = $register_block;
fn register_block(&self) -> &Self::RegisterBlock {
crate::peripherals::[< $instance:upper >]::regs()
$crate::peripherals::[< $instance >]::regs()
}
fn tx_waker(&self) -> &'static AtomicWaker {
static WAKER: AtomicWaker = AtomicWaker::new();
@ -97,8 +96,8 @@ macro_rules! impl_pdma_channel {
fn async_handler(&self) -> InterruptHandler {
#[handler(priority = Priority::max())]
pub(crate) fn interrupt_handler() {
super::asynch::handle_in_interrupt::<[< $instance DmaChannel >]<'static>>();
super::asynch::handle_out_interrupt::<[< $instance DmaChannel >]<'static>>();
super::asynch::handle_in_interrupt::<$instance<'static>>();
super::asynch::handle_out_interrupt::<$instance<'static>>();
}
interrupt_handler
@ -113,19 +112,19 @@ macro_rules! impl_pdma_channel {
}
}
impl<'d> DmaChannelConvert<[<$peri DmaChannel>]<'d>> for [<$instance DmaChannel>]<'d> {
impl<'d> DmaChannelConvert<[<$peri DmaChannel>]<'d>> for $instance<'d> {
fn degrade(self) -> [<$peri DmaChannel>]<'d> {
self.into()
}
}
impl<'d> DmaChannelConvert<[<$peri DmaRxChannel>]<'d>> for [<$instance DmaChannel>]<'d> {
impl<'d> DmaChannelConvert<[<$peri DmaRxChannel>]<'d>> for $instance<'d> {
fn degrade(self) -> [<$peri DmaRxChannel>]<'d> {
[<$peri DmaRxChannel>](self.into())
}
}
impl<'d> DmaChannelConvert<[<$peri DmaTxChannel>]<'d>> for [<$instance DmaChannel>]<'d> {
impl<'d> DmaChannelConvert<[<$peri DmaTxChannel>]<'d>> for $instance<'d> {
fn degrade(self) -> [<$peri DmaTxChannel>]<'d> {
[<$peri DmaTxChannel>](self.into())
}
@ -134,25 +133,27 @@ macro_rules! impl_pdma_channel {
};
}
impl_pdma_channel!(AnySpi, SpiRegisterBlock, Spi2, SPI2_DMA, [Spi2]);
impl_pdma_channel!(AnySpi, SpiRegisterBlock, Spi3, SPI3_DMA, [Spi3]);
impl_pdma_channel!(AnySpi, SpiRegisterBlock, DMA_SPI2, SPI2_DMA, [Spi2]);
impl_pdma_channel!(AnySpi, SpiRegisterBlock, DMA_SPI3, SPI3_DMA, [Spi3]);
impl_pdma_channel!(AnyI2s, I2sRegisterBlock, I2s0, I2S0, [I2s0]);
impl_pdma_channel!(AnyI2s, I2sRegisterBlock, DMA_I2S0, I2S0, [I2s0]);
#[cfg(i2s1)]
impl_pdma_channel!(AnyI2s, I2sRegisterBlock, I2s1, I2S1, [I2s1]);
impl_pdma_channel!(AnyI2s, I2sRegisterBlock, DMA_I2S1, I2S1, [I2s1]);
// Specific peripherals use specific channels. Note that this may be overly
// restrictive (ESP32 allows configuring 2 SPI DMA channels between 3 different
// peripherals), but for the current set of restrictions this is sufficient.
crate::dma::impl_dma_eligible!([Spi2DmaChannel] SPI2 => Spi2);
crate::dma::impl_dma_eligible!([Spi3DmaChannel] SPI3 => Spi3);
crate::dma::impl_dma_eligible!([I2s0DmaChannel] I2S0 => I2s0);
crate::dma::impl_dma_eligible!([DMA_SPI2] SPI2 => Spi2);
crate::dma::impl_dma_eligible!([DMA_SPI3] SPI3 => Spi3);
crate::dma::impl_dma_eligible!([DMA_I2S0] I2S0 => I2s0);
#[cfg(i2s1)]
crate::dma::impl_dma_eligible!([I2s1DmaChannel] I2S1 => I2s1);
crate::dma::impl_dma_eligible!([DMA_I2S1] I2S1 => I2s1);
#[cfg(esp32s2)]
crate::dma::impl_dma_eligible!([CryptoDmaChannel] AES => Aes);
use crate::peripherals::DMA_CRYPTO;
#[cfg(esp32s2)]
crate::dma::impl_dma_eligible!([CryptoDmaChannel] SHA => Sha);
crate::dma::impl_dma_eligible!([DMA_CRYPTO] AES => Aes);
#[cfg(esp32s2)]
crate::dma::impl_dma_eligible!([DMA_CRYPTO] SHA => Sha);
pub(super) fn init_dma(_cs: CriticalSection<'_>) {
#[cfg(esp32)]
@ -176,9 +177,9 @@ pub(super) fn init_dma(_cs: CriticalSection<'_>) {
// the DMA channel is in use but we don't have a good mechanism for that
// yet. For now, we shall just turn in on forever once any DMA channel is used.
use crate::peripherals::COPY_DMA;
use crate::peripherals::DMA_COPY;
COPY_DMA::regs().conf().modify(|_, w| w.clk_en().set_bit());
DMA_COPY::regs().conf().modify(|_, w| w.clk_en().set_bit());
}
}
@ -188,6 +189,7 @@ where
Dm: DriverMode,
{
/// Asserts that the channel is compatible with the given peripheral.
#[instability::unstable]
pub fn runtime_ensure_compatible(&self, peripheral: &impl DmaEligible) {
assert!(
self.tx

View File

@ -386,8 +386,8 @@ impl InterruptAccess<DmaRxInterrupt> for AnySpiDmaRxChannel<'_> {
crate::any_peripheral! {
/// An SPI-compatible type-erased DMA channel.
pub peripheral AnySpiDmaChannel<'d> {
Spi2(Spi2DmaChannel<'d>),
Spi3(Spi3DmaChannel<'d>),
Spi2(super::DMA_SPI2<'d>),
Spi3(super::DMA_SPI3<'d>),
}
}

View File

@ -559,6 +559,7 @@ where
}
}
#[instability::unstable]
impl<'d, Dm> DmaSupportRx for I2sRx<'d, Dm>
where
Dm: DriverMode,
@ -789,6 +790,7 @@ mod private {
}
}
#[allow(private_bounds)]
pub trait RegBlock: DmaEligible {
fn regs(&self) -> &RegisterBlock;
fn peripheral(&self) -> crate::system::Peripheral;

View File

@ -488,6 +488,7 @@ fn calculate_clock(sample_rate: Rate, data_bits: u8) -> I2sClockDividers {
}
}
#[doc(hidden)]
#[allow(private_bounds)]
pub trait PrivateInstance: DmaEligible {
fn regs(&self) -> &RegisterBlock;
fn peripheral(&self) -> crate::system::Peripheral;

View File

@ -26,11 +26,6 @@ macro_rules! peripherals {
],
pins: [
$( ( $pin:literal, $($pin_tokens:tt)* ) )*
],
dma_channels: [
$(
$channel_name:ident : $channel_ty:path
),* $(,)?
]
) => {
paste::paste! {
@ -73,11 +68,6 @@ macro_rules! peripherals {
#[doc = concat!("GPIO", stringify!($pin))]
pub [<GPIO $pin>]: [<GPIO $pin>]<'static>,
)*
$(
#[doc = concat!(stringify!($channel_name), " DMA channel.")]
pub $channel_name: $crate::dma::$channel_ty<'static>,
)*
}
impl Peripherals {
@ -114,10 +104,6 @@ macro_rules! peripherals {
$(
[<GPIO $pin>]: [<GPIO $pin>]::steal(),
)*
$(
$channel_name: $crate::dma::$channel_ty::steal(),
)*
}
}
}

View File

@ -76,6 +76,11 @@ crate::peripherals! {
UHCI0 <= UHCI0,
UHCI1 <= UHCI1,
WIFI <= WIFI,
DMA_SPI2 <= SPI2,
DMA_SPI3 <= SPI3,
DMA_I2S0 <= I2S0,
DMA_I2S1 <= I2S1,
],
pins: [
(0, [Input, Output, Analog, RtcIo, Touch] (5 => EMAC_TX_CLK) (1 => CLK_OUT1))
@ -114,11 +119,5 @@ 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,
]
}

View File

@ -61,6 +61,8 @@ crate::peripherals! {
MEM2MEM5 <= virtual,
MEM2MEM6 <= virtual,
MEM2MEM8 <= virtual,
DMA_CH0 <= virtual,
],
pins: [
(0, [Input, Output, Analog, RtcIo])
@ -77,8 +79,5 @@ crate::peripherals! {
(18, [Input, Output])
(19, [Input, Output])
(20, [Input, Output] (0 => U0RXD) ())
],
dma_channels: [
DMA_CH0: DmaChannel0,
]
}

View File

@ -69,6 +69,10 @@ crate::peripherals! {
USB_DEVICE <= USB_DEVICE,
WIFI <= virtual,
XTS_AES <= XTS_AES,
DMA_CH0 <= virtual,
DMA_CH1 <= virtual,
DMA_CH2 <= virtual,
],
pins: [
(0, [Input, Output, Analog, RtcIo])
@ -93,10 +97,5 @@ 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,
]
}

View File

@ -105,6 +105,10 @@ crate::peripherals! {
MEM2MEM13 <= virtual,
MEM2MEM14 <= virtual,
MEM2MEM15 <= virtual,
DMA_CH0 <= virtual,
DMA_CH1 <= virtual,
DMA_CH2 <= virtual,
],
pins: [
(0, [Input, Output, Analog, RtcIo])
@ -138,10 +142,5 @@ 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,
]
}

View File

@ -93,6 +93,10 @@ crate::peripherals! {
MEM2MEM13 <= virtual,
MEM2MEM14 <= virtual,
MEM2MEM15 <= virtual,
DMA_CH0 <= virtual,
DMA_CH1 <= virtual,
DMA_CH2 <= virtual,
],
pins: [
(0, [Input, Output, Analog] (2 => FSPIQ) (2 => FSPIQ))
@ -123,10 +127,5 @@ 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,
]
}

View File

@ -33,8 +33,6 @@ crate::peripherals! {
APB_SARADC <= APB_SARADC,
DAC1 <= virtual,
DAC2 <= virtual,
COPY_DMA <= COPY_DMA,
CRYPTO_DMA <= CRYPTO_DMA,
DEDICATED_GPIO <= DEDICATED_GPIO,
DS <= DS,
EFUSE <= EFUSE,
@ -77,6 +75,12 @@ crate::peripherals! {
NRX <= NRX,
FE <= FE,
FE2 <= FE2,
DMA_SPI2 <= SPI2,
DMA_SPI3 <= SPI3,
DMA_I2S0 <= I2S0,
DMA_CRYPTO <= CRYPTO_DMA,
DMA_COPY <= COPY_DMA,
],
pins: [
(0, [Input, Output, Analog, RtcIo])
@ -123,12 +127,5 @@ crate::peripherals! {
(44, [Input, Output])
(45, [Input, Output])
(46, [Input, Output])
],
dma_channels: [
DMA_SPI2: Spi2DmaChannel,
DMA_SPI3: Spi3DmaChannel,
DMA_I2S0: I2s0DmaChannel,
DMA_CRYPTO: CryptoDmaChannel,
DMA_COPY: CopyDmaChannel,
]
}

View File

@ -82,6 +82,12 @@ crate::peripherals! {
WCL <= WCL,
WIFI <= virtual,
XTS_AES <= XTS_AES,
DMA_CH0 <= virtual,
DMA_CH1 <= virtual,
DMA_CH2 <= virtual,
DMA_CH3 <= virtual,
DMA_CH4 <= virtual,
],
pins: [
(0, [Input, Output, Analog, RtcIo])
@ -129,12 +135,5 @@ 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,
]
}

View File

@ -2674,6 +2674,7 @@ mod ehal1 {
/// SPI peripheral instance.
#[doc(hidden)]
#[allow(private_bounds)]
pub trait PeripheralInstance: private::Sealed + DmaEligible {
/// Returns the peripheral data describing this SPI instance.
fn info(&self) -> &'static Info;

View File

@ -579,6 +579,7 @@ pub trait Instance: crate::private::Sealed + super::IntoAnySpi {
/// A marker for DMA-capable SPI peripheral instances.
#[doc(hidden)]
#[allow(private_bounds)]
pub trait InstanceDma: Instance + DmaEligible {}
impl InstanceDma for crate::peripherals::SPI2<'_> {}

View File

@ -206,9 +206,9 @@ mod test {
cfg_if::cfg_if! {
if #[cfg(pdma)] {
type DmaChannel<'a> = esp_hal::dma::Spi2DmaChannel<'a>;
type DmaChannel<'a> = esp_hal::peripherals::DMA_SPI2<'a>;
} else {
type DmaChannel<'a> = esp_hal::dma::DmaChannel0<'a>;
type DmaChannel<'a> = esp_hal::peripherals::DMA_CH0<'a>;
}
}

View File

@ -23,9 +23,9 @@ use hil_test as _;
cfg_if::cfg_if! {
if #[cfg(any(esp32, esp32s2))] {
type DmaChannel0<'d> = esp_hal::dma::I2s0DmaChannel<'d>;
type DmaChannel0<'d> = esp_hal::peripherals::DMA_I2S0<'d>;
} else {
type DmaChannel0<'d> = esp_hal::dma::DmaChannel0<'d>;
type DmaChannel0<'d> = esp_hal::peripherals::DMA_CH0<'d>;
}
}

View File

@ -9,20 +9,18 @@
use esp_hal::{
gpio::NoPin,
i2s::parallel::{I2sParallel, TxSixteenBits},
peripherals::I2S0,
peripherals::{DMA_I2S0, I2S0},
time::Rate,
};
use hil_test as _;
type DmaChannel0<'a> = esp_hal::dma::I2s0DmaChannel<'a>;
#[cfg(test)]
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
mod tests {
use super::*;
struct Context {
dma_channel: DmaChannel0<'static>,
dma_channel: DMA_I2S0<'static>,
i2s: I2S0<'static>,
}

View File

@ -7,7 +7,7 @@
#![no_main]
use esp_hal::{
dma::{DmaChannel0, DmaTxBuf},
dma::DmaTxBuf,
dma_buffers,
gpio::NoPin,
lcd_cam::{
@ -19,6 +19,7 @@ use esp_hal::{
channel::{CtrlMode, EdgeMode},
Pcnt,
},
peripherals::DMA_CH0,
time::Rate,
Blocking,
};
@ -39,7 +40,7 @@ struct Context<'d> {
lcd_cam: LcdCam<'d, Blocking>,
pcnt: Pcnt<'d>,
pins: Pins,
dma: DmaChannel0<'d>,
dma: DMA_CH0<'d>,
dma_buf: DmaTxBuf,
}

View File

@ -7,13 +7,14 @@
#![no_main]
use esp_hal::{
dma::{DmaChannel0, DmaTxBuf},
dma::DmaTxBuf,
dma_buffers,
gpio::NoPin,
lcd_cam::{
lcd::i8080::{Command, Config, TxEightBits, I8080},
LcdCam,
},
peripherals::DMA_CH0,
time::Rate,
Async,
};
@ -23,7 +24,7 @@ const DATA_SIZE: usize = 1024 * 10;
struct Context<'d> {
lcd_cam: LcdCam<'d, Async>,
dma: DmaChannel0<'d>,
dma: DMA_CH0<'d>,
dma_buf: DmaTxBuf,
}

View File

@ -9,7 +9,7 @@
#[cfg(not(esp32h2))]
use esp_hal::parl_io::{RxSixteenBits, TxSixteenBits};
use esp_hal::{
dma::{DmaChannel0, DmaRxBuf, DmaTxBuf},
dma::{DmaRxBuf, DmaTxBuf},
dma_buffers,
gpio::{AnyPin, Pin},
parl_io::{
@ -32,14 +32,14 @@ use esp_hal::{
TxPinConfigWithValidPin,
TxTwoBits,
},
peripherals::PARL_IO,
peripherals::{DMA_CH0, PARL_IO},
time::Rate,
};
use hil_test as _;
struct Context {
parl_io: PARL_IO<'static>,
dma_channel: DmaChannel0<'static>,
dma_channel: DMA_CH0<'static>,
clock_pin: AnyPin<'static>,
valid_pin: AnyPin<'static>,
data_pins: [AnyPin<'static>; 8],

View File

@ -9,7 +9,7 @@
#[cfg(esp32c6)]
use esp_hal::parl_io::{TxPinConfigWithValidPin, TxSixteenBits};
use esp_hal::{
dma::{DmaChannel0, DmaTxBuf},
dma::DmaTxBuf,
dma_tx_buffer,
gpio::{
interconnect::{InputSignal, OutputSignal},
@ -29,14 +29,14 @@ use esp_hal::{
unit::Unit,
Pcnt,
},
peripherals::PARL_IO,
peripherals::{DMA_CH0, PARL_IO},
time::Rate,
};
use hil_test as _;
struct Context {
parl_io: PARL_IO<'static>,
dma_channel: DmaChannel0<'static>,
dma_channel: DMA_CH0<'static>,
clock: OutputSignal<'static>,
valid: OutputSignal<'static>,
clock_loopback: InputSignal<'static>,

View File

@ -9,7 +9,7 @@
#[cfg(esp32c6)]
use esp_hal::parl_io::{TxPinConfigWithValidPin, TxSixteenBits};
use esp_hal::{
dma::{DmaChannel0, DmaTxBuf},
dma::DmaTxBuf,
dma_tx_buffer,
gpio::{
interconnect::{InputSignal, OutputSignal},
@ -29,14 +29,14 @@ use esp_hal::{
unit::Unit,
Pcnt,
},
peripherals::PARL_IO,
peripherals::{DMA_CH0, PARL_IO},
time::Rate,
};
use hil_test as _;
struct Context {
parl_io: PARL_IO<'static>,
dma_channel: DmaChannel0<'static>,
dma_channel: DMA_CH0<'static>,
clock: OutputSignal<'static>,
valid: OutputSignal<'static>,
clock_loopback: InputSignal<'static>,

View File

@ -24,9 +24,9 @@ use hil_test as _;
cfg_if::cfg_if! {
if #[cfg(pdma)] {
type DmaChannel0<'d> = esp_hal::dma::Spi2DmaChannel<'d>;
type DmaChannel0<'d> = esp_hal::peripherals::DMA_SPI2<'d>;
} else {
type DmaChannel0<'d> = esp_hal::dma::DmaChannel0<'d>;
type DmaChannel0<'d> = esp_hal::peripherals::DMA_CH0<'d>;
}
}

View File

@ -36,9 +36,9 @@ cfg_if::cfg_if! {
#[cfg(feature = "unstable")]
cfg_if::cfg_if! {
if #[cfg(any(esp32, esp32s2))] {
type DmaChannel<'d> = esp_hal::dma::Spi2DmaChannel<'d>;
type DmaChannel<'d> = esp_hal::peripherals::DMA_SPI2<'d>;
} else {
type DmaChannel<'d> = esp_hal::dma::DmaChannel0<'d>;
type DmaChannel<'d> = esp_hal::peripherals::DMA_CH0<'d>;
}
}

View File

@ -20,9 +20,9 @@ use hil_test as _;
cfg_if::cfg_if! {
if #[cfg(any(esp32, esp32s2))] {
type DmaChannel<'d> = esp_hal::dma::Spi2DmaChannel<'d>;
type DmaChannel<'d> = esp_hal::peripherals::DMA_SPI2<'d>;
} else {
type DmaChannel<'d> = esp_hal::dma::DmaChannel0<'d>;
type DmaChannel<'d> = esp_hal::peripherals::DMA_CH0<'d>;
}
}