Skip to content

Commit

Permalink
Add mode to DMA channel drivers
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani committed Nov 12, 2024
1 parent 6cb5d96 commit c84c29e
Show file tree
Hide file tree
Showing 14 changed files with 359 additions and 248 deletions.
1 change: 1 addition & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The DMA channel types have been removed from peripherals (#2261)
- `I2C` driver renamed to `I2c` (#2320)
- The GPIO pins are now accessible via `Peripherals` and are no longer part of the `Io` struct (#2508)
- `dma::{ChannelRx, ChannelTx}` now have a `Mode` type parameter (#2519)

### Fixed

Expand Down
4 changes: 2 additions & 2 deletions esp-hal/src/aes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ pub mod dma {
}

impl<'d> DmaSupportTx for AesDma<'d> {
type TX = ChannelTx<'d, <AES as DmaEligible>::Dma>;
type TX = ChannelTx<'d, <AES as DmaEligible>::Dma, Blocking>;

fn tx(&mut self) -> &mut Self::TX {
&mut self.channel.tx
Expand All @@ -336,7 +336,7 @@ pub mod dma {
}

impl<'d> DmaSupportRx for AesDma<'d> {
type RX = ChannelRx<'d, <AES as DmaEligible>::Dma>;
type RX = ChannelRx<'d, <AES as DmaEligible>::Dma, Blocking>;

fn rx(&mut self) -> &mut Self::RX {
&mut self.channel.rx
Expand Down
143 changes: 95 additions & 48 deletions esp-hal/src/dma/gdma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,48 +25,78 @@ use crate::{
#[doc(hidden)]
pub trait GdmaChannel {
fn number(&self) -> u8;
}

/// An arbitrary GDMA channel
#[non_exhaustive]
pub struct AnyGdmaChannel(u8);
fn async_handler_out(&self) -> Option<InterruptHandler> {
match self.number() {
0 => DmaChannel0::handler_out(),
#[cfg(not(esp32c2))]
1 => DmaChannel1::handler_out(),
#[cfg(not(esp32c2))]
2 => DmaChannel2::handler_out(),
#[cfg(esp32s3)]
3 => DmaChannel3::handler_out(),
#[cfg(esp32s3)]
4 => DmaChannel4::handler_out(),
_ => unreachable!(),
}
}

impl crate::private::Sealed for AnyGdmaChannel {}
impl DmaChannel for AnyGdmaChannel {
type Rx = ChannelRxImpl<Self>;
type Tx = ChannelTxImpl<Self>;
fn peripheral_interrupt_out(&self) -> Option<Interrupt> {
match self.number() {
0 => DmaChannel0::isr_out(),
#[cfg(not(esp32c2))]
1 => DmaChannel1::isr_out(),
#[cfg(not(esp32c2))]
2 => DmaChannel2::isr_out(),
#[cfg(esp32s3)]
3 => DmaChannel3::isr_out(),
#[cfg(esp32s3)]
4 => DmaChannel4::isr_out(),
_ => unreachable!(),
}
}

fn async_handler<M: Mode>(ch: &Channel<'_, Self, M>) -> InterruptHandler {
match ch.tx.tx_impl.0.number() {
0 => DmaChannel0::handler(),
fn async_handler_in(&self) -> Option<InterruptHandler> {
match self.number() {
0 => DmaChannel0::handler_in(),
#[cfg(not(esp32c2))]
1 => DmaChannel1::handler(),
1 => DmaChannel1::handler_in(),
#[cfg(not(esp32c2))]
2 => DmaChannel2::handler(),
2 => DmaChannel2::handler_in(),
#[cfg(esp32s3)]
3 => DmaChannel3::handler(),
3 => DmaChannel3::handler_in(),
#[cfg(esp32s3)]
4 => DmaChannel4::handler(),
4 => DmaChannel4::handler_in(),
_ => unreachable!(),
}
}

fn interrupts<M: Mode>(ch: &Channel<'_, Self, M>) -> &'static [Interrupt] {
match ch.tx.tx_impl.0.number() {
0 => DmaChannel0::isrs(),
fn peripheral_interrupt_in(&self) -> Option<Interrupt> {
match self.number() {
0 => DmaChannel0::isr_in(),
#[cfg(not(esp32c2))]
1 => DmaChannel1::isrs(),
1 => DmaChannel1::isr_in(),
#[cfg(not(esp32c2))]
2 => DmaChannel2::isrs(),
2 => DmaChannel2::isr_in(),
#[cfg(esp32s3)]
3 => DmaChannel3::isrs(),
3 => DmaChannel3::isr_in(),
#[cfg(esp32s3)]
4 => DmaChannel4::isrs(),
4 => DmaChannel4::isr_in(),
_ => unreachable!(),
}
}
}

/// An arbitrary GDMA channel
#[non_exhaustive]
pub struct AnyGdmaChannel(u8);

impl crate::private::Sealed for AnyGdmaChannel {}
impl DmaChannel for AnyGdmaChannel {
type Rx = ChannelRxImpl<Self>;
type Tx = ChannelTxImpl<Self>;
}

#[non_exhaustive]
#[doc(hidden)]
pub struct SpecificGdmaChannel<const N: u8> {}
Expand Down Expand Up @@ -202,6 +232,14 @@ impl<C: GdmaChannel> TxRegisterAccess for ChannelTxImpl<C> {
.out_eof_des_addr()
.bits() as _
}

fn async_handler(&self) -> Option<InterruptHandler> {
self.0.async_handler_out()
}

fn peripheral_interrupt(&self) -> Option<Interrupt> {
self.0.peripheral_interrupt_out()
}
}

impl<C: GdmaChannel> InterruptAccess<DmaTxInterrupt> for ChannelTxImpl<C> {
Expand Down Expand Up @@ -385,6 +423,14 @@ impl<C: GdmaChannel> RxRegisterAccess for ChannelRxImpl<C> {
.in_conf0()
.modify(|_, w| w.mem_trans_en().bit(value));
}

fn async_handler(&self) -> Option<InterruptHandler> {
self.0.async_handler_in()
}

fn peripheral_interrupt(&self) -> Option<Interrupt> {
self.0.peripheral_interrupt_in()
}
}

impl<C: GdmaChannel> InterruptAccess<DmaRxInterrupt> for ChannelRxImpl<C> {
Expand Down Expand Up @@ -481,7 +527,7 @@ impl<CH: DmaChannel, M: Mode> Channel<'_, CH, M> {
}

macro_rules! impl_channel {
($num: literal, $async_handler: path, $($interrupt: ident),* ) => {
($num:literal, $interrupt_in:ident, $async_handler:path $(, $interrupt_out:ident , $async_handler_out:path)? ) => {
paste::paste! {
/// A description of a specific GDMA channel
#[non_exhaustive]
Expand All @@ -490,26 +536,26 @@ macro_rules! impl_channel {
impl crate::private::Sealed for [<DmaChannel $num>] {}

impl [<DmaChannel $num>] {
fn handler() -> InterruptHandler {
$async_handler
fn handler_in() -> Option<InterruptHandler> {
Some($async_handler)
}

fn isr_in() -> Option<Interrupt> {
Some(Interrupt::$interrupt_in)
}

fn handler_out() -> Option<InterruptHandler> {
$crate::if_set! { $(Some($async_handler_out))?, None }
}

fn isrs() -> &'static [Interrupt] {
&[$(Interrupt::$interrupt),*]
fn isr_out() -> Option<Interrupt> {
$crate::if_set! { $(Some(Interrupt::$interrupt_out))?, None }
}
}

impl DmaChannel for [<DmaChannel $num>] {
type Rx = ChannelRxImpl<SpecificGdmaChannel<$num>>;
type Tx = ChannelTxImpl<SpecificGdmaChannel<$num>>;

fn async_handler<M: Mode>(_ch: &Channel<'_, Self, M>) -> InterruptHandler {
Self::handler()
}

fn interrupts<M: Mode>(_ch: &Channel<'_, Self, M>,) -> &'static [Interrupt] {
Self::isrs()
}
}

impl DmaChannelConvert<AnyGdmaChannel> for [<DmaChannel $num>] {
Expand Down Expand Up @@ -541,7 +587,6 @@ macro_rules! impl_channel {
let mut this = Channel {
tx: ChannelTx::new(ChannelTxImpl(SpecificGdmaChannel::<$num> {})),
rx: ChannelRx::new(ChannelRxImpl(SpecificGdmaChannel::<$num> {})),
phantom: PhantomData,
};

this.configure(burst_mode, priority);
Expand All @@ -553,27 +598,29 @@ macro_rules! impl_channel {
};
}

use super::asynch::interrupt as asynch_handler;

cfg_if::cfg_if! {
if #[cfg(esp32c2)] {
const CHANNEL_COUNT: usize = 1;
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_CH0);
impl_channel!(0, DMA_CH0, asynch_handler::interrupt_handler_ch0);
} else if #[cfg(esp32c3)] {
const CHANNEL_COUNT: usize = 3;
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_CH0);
impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_CH1);
impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_CH2);
impl_channel!(0, DMA_CH0, asynch_handler::interrupt_handler_ch0);
impl_channel!(1, DMA_CH1, asynch_handler::interrupt_handler_ch1);
impl_channel!(2, DMA_CH2, asynch_handler::interrupt_handler_ch2);
} else if #[cfg(any(esp32c6, esp32h2))] {
const CHANNEL_COUNT: usize = 3;
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_IN_CH0, DMA_OUT_CH0);
impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_IN_CH1, DMA_OUT_CH1);
impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_IN_CH2, DMA_OUT_CH2);
impl_channel!(0, DMA_IN_CH0, asynch_handler::interrupt_handler_ch0, DMA_OUT_CH0, asynch_handler::interrupt_handler_ch0);
impl_channel!(1, DMA_IN_CH1, asynch_handler::interrupt_handler_ch1, DMA_OUT_CH1, asynch_handler::interrupt_handler_ch1);
impl_channel!(2, DMA_IN_CH2, asynch_handler::interrupt_handler_ch2, DMA_OUT_CH2, asynch_handler::interrupt_handler_ch2);
} else if #[cfg(esp32s3)] {
const CHANNEL_COUNT: usize = 5;
impl_channel!(0, super::asynch::interrupt::interrupt_handler_ch0, DMA_IN_CH0, DMA_OUT_CH0);
impl_channel!(1, super::asynch::interrupt::interrupt_handler_ch1, DMA_IN_CH1, DMA_OUT_CH1);
impl_channel!(2, super::asynch::interrupt::interrupt_handler_ch2, DMA_IN_CH2, DMA_OUT_CH2);
impl_channel!(3, super::asynch::interrupt::interrupt_handler_ch3, DMA_IN_CH3, DMA_OUT_CH3);
impl_channel!(4, super::asynch::interrupt::interrupt_handler_ch4, DMA_IN_CH4, DMA_OUT_CH4);
impl_channel!(0, DMA_IN_CH0, asynch_handler::interrupt_handler_ch0, DMA_OUT_CH0, asynch_handler::interrupt_handler_ch0);
impl_channel!(1, DMA_IN_CH1, asynch_handler::interrupt_handler_ch1, DMA_OUT_CH1, asynch_handler::interrupt_handler_ch1);
impl_channel!(2, DMA_IN_CH2, asynch_handler::interrupt_handler_ch2, DMA_OUT_CH2, asynch_handler::interrupt_handler_ch2);
impl_channel!(3, DMA_IN_CH3, asynch_handler::interrupt_handler_ch3, DMA_OUT_CH3, asynch_handler::interrupt_handler_ch3);
impl_channel!(4, DMA_IN_CH4, asynch_handler::interrupt_handler_ch4, DMA_OUT_CH4, asynch_handler::interrupt_handler_ch4);
}
}

Expand Down
6 changes: 3 additions & 3 deletions esp-hal/src/dma/m2m.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,11 @@ where
}
}

impl<'d, MODE> DmaSupportRx for Mem2Mem<'d, MODE>
impl<'d, M> DmaSupportRx for Mem2Mem<'d, M>
where
MODE: Mode,
M: Mode,
{
type RX = ChannelRx<'d, AnyGdmaChannel>;
type RX = ChannelRx<'d, AnyGdmaChannel, M>;

fn rx(&mut self) -> &mut Self::RX {
&mut self.channel.rx
Expand Down
Loading

0 comments on commit c84c29e

Please sign in to comment.