Skip to content

Commit

Permalink
Deduplicate PDMA channel impl macro
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani committed Nov 13, 2024
1 parent 53d7125 commit 6b27763
Showing 1 changed file with 33 additions and 141 deletions.
174 changes: 33 additions & 141 deletions esp-hal/src/dma/pdma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,114 +376,6 @@ impl InterruptAccess<DmaRxInterrupt> for AnySpiDmaRxChannel {
}
}

#[doc(hidden)]
pub struct SpiDmaChannel<C>(PhantomData<C>);

impl<C> crate::private::Sealed for SpiDmaChannel<C> {}

macro_rules! ImplSpiChannel {
($num: literal) => {
paste::paste! {
#[doc = concat!("DMA channel suitable for SPI", $num)]
#[non_exhaustive]
pub struct [<Spi $num DmaChannel>] {}

impl $crate::private::Sealed for [<Spi $num DmaChannel>] {}

impl Peripheral for [<Spi $num DmaChannel>] {
type P = Self;

unsafe fn clone_unchecked(&self) -> Self::P {
Self::steal()
}
}

impl [<Spi $num DmaChannel>] {
/// Unsafely constructs a new DMA channel.
///
/// # Safety
///
/// The caller must ensure that only a single instance is used.
pub unsafe fn steal() -> Self {
Self {}
}
}

impl DmaChannel for [<Spi $num DmaChannel>] {
type Rx = AnySpiDmaRxChannel;
type Tx = AnySpiDmaTxChannel;

unsafe fn split_internal(self, _: $crate::private::Internal) -> (Self::Rx, Self::Tx) {
(AnySpiDmaRxChannel(Self {}.into()), AnySpiDmaTxChannel(Self {}.into()))
}
}

impl DmaChannelExt for [<Spi $num DmaChannel>] {
fn get_rx_interrupts() -> impl InterruptAccess<DmaRxInterrupt> {
AnySpiDmaRxChannel(Self {}.into())
}
fn get_tx_interrupts() -> impl InterruptAccess<DmaTxInterrupt> {
AnySpiDmaTxChannel(Self {}.into())
}
}

impl PdmaChannel for [<Spi $num DmaChannel>] {
type RegisterBlock = SpiRegisterBlock;

fn register_block(&self) -> &SpiRegisterBlock {
unsafe { &*$crate::peripherals::[<SPI $num>]::PTR }
}
fn tx_waker(&self) -> &'static AtomicWaker {
static WAKER: AtomicWaker = AtomicWaker::new();
&WAKER
}
fn rx_waker(&self) -> &'static AtomicWaker {
static WAKER: AtomicWaker = AtomicWaker::new();
&WAKER
}

fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
peripheral == DmaPeripheral::[<Spi $num>]
}

fn peripheral_interrupt(&self) -> Interrupt {
Interrupt::[< SPI $num _DMA >]
}

fn async_handler(&self) -> InterruptHandler {
super::asynch::interrupt::[< interrupt_handler_spi $num _dma >]
}
fn rx_async_flag(&self) -> &'static AtomicBool {
static FLAG: AtomicBool = AtomicBool::new(false);
&FLAG
}
fn tx_async_flag(&self) -> &'static AtomicBool {
static FLAG: AtomicBool = AtomicBool::new(false);
&FLAG
}
}

impl DmaChannelConvert<AnySpiDmaChannel> for [<Spi $num DmaChannel>] {
fn degrade(self) -> AnySpiDmaChannel {
self.into()
}
}

impl DmaChannelConvert<AnySpiDmaRxChannel> for [<Spi $num DmaChannel>] {
fn degrade(self) -> AnySpiDmaRxChannel {
AnySpiDmaRxChannel(Self {}.into())
}
}

impl DmaChannelConvert<AnySpiDmaTxChannel> for [<Spi $num DmaChannel>] {
fn degrade(self) -> AnySpiDmaTxChannel {
AnySpiDmaTxChannel(Self {}.into())
}
}
}
};
}

/// The RX half of an arbitrary I2S DMA channel.
pub struct AnyI2sDmaRxChannel(AnyI2sDmaChannel);

Expand Down Expand Up @@ -840,23 +732,23 @@ impl InterruptAccess<DmaRxInterrupt> for AnyI2sDmaRxChannel {
}
}

macro_rules! ImplI2sChannel {
($num: literal) => {
macro_rules! ImplPdmaChannel {
($peri:ident, $num:literal) => {
paste::paste! {
#[doc = concat!("DMA channel suitable for I2S", $num)]
pub struct [<I2s $num DmaChannel>] {}
#[doc = concat!("DMA channel suitable for ", stringify!([< $peri:upper >]), $num)]
pub struct [<$peri $num DmaChannel>] {}

impl $crate::private::Sealed for [<I2s $num DmaChannel>] {}
impl $crate::private::Sealed for [<$peri $num DmaChannel>] {}

impl Peripheral for [<I2s $num DmaChannel>] {
impl Peripheral for [<$peri $num DmaChannel>] {
type P = Self;

unsafe fn clone_unchecked(&self) -> Self::P {
Self::steal()
}
}

impl [<I2s $num DmaChannel>] {
impl [<$peri $num DmaChannel>] {
/// Unsafely constructs a new DMA channel.
///
/// # Safety
Expand All @@ -867,29 +759,29 @@ macro_rules! ImplI2sChannel {
}
}

impl DmaChannel for [<I2s $num DmaChannel>] {
type Rx = AnyI2sDmaRxChannel;
type Tx = AnyI2sDmaTxChannel;
impl DmaChannel for [<$peri $num DmaChannel>] {
type Rx = [<Any $peri DmaRxChannel>];
type Tx = [<Any $peri DmaTxChannel>];

unsafe fn split_internal(self, _: $crate::private::Internal) -> (Self::Rx, Self::Tx) {
(AnyI2sDmaRxChannel(Self {}.into()), AnyI2sDmaTxChannel(Self {}.into()))
([<Any $peri DmaRxChannel>](Self {}.into()), [<Any $peri DmaTxChannel>](Self {}.into()))
}
}

impl DmaChannelExt for [<I2s $num DmaChannel>] {
impl DmaChannelExt for [<$peri $num DmaChannel>] {
fn get_rx_interrupts() -> impl InterruptAccess<DmaRxInterrupt> {
AnyI2sDmaRxChannel(Self {}.into())
[<Any $peri DmaRxChannel>](Self {}.into())
}
fn get_tx_interrupts() -> impl InterruptAccess<DmaTxInterrupt> {
AnyI2sDmaTxChannel(Self {}.into())
[<Any $peri DmaTxChannel>](Self {}.into())
}
}

impl PdmaChannel for [<I2s $num DmaChannel>] {
type RegisterBlock = I2sRegisterBlock;
impl PdmaChannel for [<$peri $num DmaChannel>] {
type RegisterBlock = [<$peri RegisterBlock>];

fn register_block(&self) -> &I2sRegisterBlock {
unsafe { &*crate::peripherals::[< I2S $num >]::PTR }
fn register_block(&self) -> &Self::RegisterBlock {
unsafe { &*crate::peripherals::[< $peri:upper $num >]::PTR }
}
fn tx_waker(&self) -> &'static AtomicWaker {
static WAKER: AtomicWaker = AtomicWaker::new();
Expand All @@ -900,15 +792,15 @@ macro_rules! ImplI2sChannel {
&WAKER
}
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
peripheral == DmaPeripheral::[<I2s $num>]
peripheral == DmaPeripheral::[<$peri $num>]
}

fn peripheral_interrupt(&self) -> Interrupt {
Interrupt::[< I2S $num >]
Interrupt::[< $peri:upper $num >]
}

fn async_handler(&self) -> InterruptHandler {
super::asynch::interrupt::[< interrupt_handler_i2s $num _dma >]
super::asynch::interrupt::[< interrupt_handler_ $peri:lower $num _dma >]
}
fn rx_async_flag(&self) -> &'static AtomicBool {
static FLAG: AtomicBool = AtomicBool::new(false);
Expand All @@ -920,33 +812,33 @@ macro_rules! ImplI2sChannel {
}
}

impl DmaChannelConvert<AnyI2sDmaChannel> for [<I2s $num DmaChannel>] {
fn degrade(self) -> AnyI2sDmaChannel {
impl DmaChannelConvert<[<Any $peri DmaChannel>]> for [<$peri $num DmaChannel>] {
fn degrade(self) -> [<Any $peri DmaChannel>] {
self.into()
}
}

impl DmaChannelConvert<AnyI2sDmaRxChannel> for [<I2s $num DmaChannel>] {
fn degrade(self) -> AnyI2sDmaRxChannel {
AnyI2sDmaRxChannel(Self {}.into())
impl DmaChannelConvert<[<Any $peri DmaRxChannel>]> for [<$peri $num DmaChannel>] {
fn degrade(self) -> [<Any $peri DmaRxChannel>] {
[<Any $peri DmaRxChannel>](Self {}.into())
}
}

impl DmaChannelConvert<AnyI2sDmaTxChannel> for [<I2s $num DmaChannel>] {
fn degrade(self) -> AnyI2sDmaTxChannel {
AnyI2sDmaTxChannel(Self {}.into())
impl DmaChannelConvert<[<Any $peri DmaTxChannel>]> for [<$peri $num DmaChannel>] {
fn degrade(self) -> [<Any $peri DmaTxChannel>] {
[<Any $peri DmaTxChannel>](Self {}.into())
}
}
}
};
}

ImplSpiChannel!(2);
ImplSpiChannel!(3);
ImplPdmaChannel!(Spi, 2);
ImplPdmaChannel!(Spi, 3);

ImplI2sChannel!(0);
ImplPdmaChannel!(I2s, 0);
#[cfg(i2s1)]
ImplI2sChannel!(1);
ImplPdmaChannel!(I2s, 1);

// Specific peripherals use specific channels. Note that this may be overly
// restrictive (ESP32 allows configuring 2 SPI DMA channels between 3 different
Expand Down

0 comments on commit 6b27763

Please sign in to comment.