Skip to content

Commit

Permalink
Remove ChannelCreator types
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani committed Oct 25, 2024
1 parent 6bf03f6 commit a179100
Show file tree
Hide file tree
Showing 43 changed files with 758 additions and 557 deletions.
1 change: 1 addition & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[alias]
xtask = "run --package xtask --"
xfmt = "xtask fmt-packages"
6 changes: 3 additions & 3 deletions esp-hal/src/aes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ pub mod dma {
WriteBuffer,
},
peripherals::AES,
Blocking,
};

const ALIGN_SIZE: usize = core::mem::size_of::<u32>();
Expand All @@ -275,7 +276,7 @@ pub mod dma {
/// The underlying [`Aes`](super::Aes) driver
pub aes: super::Aes<'d>,

channel: Channel<'d, <AES as DmaEligible>::Dma, crate::Blocking>,
channel: Channel<'d, <AES as DmaEligible>::Dma, Blocking>,
rx_chain: DescriptorChain,
tx_chain: DescriptorChain,
}
Expand All @@ -284,12 +285,11 @@ pub mod dma {
/// Enable DMA for the current instance of the AES driver
pub fn with_dma<C>(
self,
channel: Channel<'d, C, crate::Blocking>,
channel: Channel<'d, C, Blocking>,
rx_descriptors: &'static mut [DmaDescriptor],
tx_descriptors: &'static mut [DmaDescriptor],
) -> AesDma<'d>
where
Self: Sized,
C: DmaChannelConvert<<AES as DmaEligible>::Dma>,
{
AesDma {
Expand Down
149 changes: 81 additions & 68 deletions esp-hal/src/dma/gdma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
use crate::{
dma::*,
peripheral::PeripheralRef,
peripherals::Interrupt,
system::{Peripheral, PeripheralClockControl},
Blocking,
};

#[doc(hidden)]
Expand All @@ -33,6 +35,36 @@ impl crate::private::Sealed for AnyGdmaChannel {}
impl DmaChannel for AnyGdmaChannel {
type Rx = ChannelRxImpl<Self>;
type Tx = ChannelTxImpl<Self>;

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

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

#[non_exhaustive]
Expand Down Expand Up @@ -442,9 +474,27 @@ macro_rules! impl_channel {

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

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

fn isrs() -> &'static [Interrupt] {
&[$(Interrupt::$interrupt),*]
}
}

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 All @@ -464,64 +514,25 @@ macro_rules! impl_channel {
fn get_tx_interrupts() -> impl InterruptAccess<DmaTxInterrupt> {
ChannelTxImpl(SpecificGdmaChannel::<$num> {})
}

fn set_isr(handler: $crate::interrupt::InterruptHandler) {
let mut dma = unsafe { crate::peripherals::DMA::steal() };
$(
dma.[< bind_ $interrupt:lower _interrupt >](handler.handler());
$crate::interrupt::enable($crate::peripherals::Interrupt::$interrupt, handler.priority()).unwrap();
)*
}
}

impl ChannelCreator<$num> {
fn do_configure<'a, M: crate::Mode>(
self,
burst_mode: bool,
priority: DmaPriority,
) -> crate::dma::Channel<'a, [<DmaChannel $num>], M> {
impl [<DmaChannel $num>] {
/// Unsafely constructs a new DMA channel.
///
/// # Safety
///
/// The caller must ensure that only a single instance is used.
pub unsafe fn steal<'a>() -> Channel<'a, Self, Blocking> {
let tx_impl = ChannelTxImpl(SpecificGdmaChannel::<$num> {});
tx_impl.set_burst_mode(burst_mode);
tx_impl.set_priority(priority);

let rx_impl = ChannelRxImpl(SpecificGdmaChannel::<$num> {});
rx_impl.set_burst_mode(burst_mode);
rx_impl.set_priority(priority);
// clear the mem2mem mode to avoid failed DMA if this
// channel was previously used for a mem2mem transfer.
rx_impl.set_mem2mem_mode(false);

crate::dma::Channel {
tx: ChannelTx::new(tx_impl, burst_mode),
rx: ChannelRx::new(rx_impl, burst_mode),
phantom: PhantomData,
}
}

/// Configure the channel for use with blocking APIs
///
/// Descriptors should be sized as `(CHUNK_SIZE + 4091) / 4092`. I.e., to
/// transfer buffers of size `1..=4092`, you need 1 descriptor.
pub fn configure<'a>(
self,
burst_mode: bool,
priority: DmaPriority,
) -> crate::dma::Channel<'a, [<DmaChannel $num>], crate::Blocking> {
self.do_configure(burst_mode, priority)
}

/// Configure the channel for use with async APIs
///
/// Descriptors should be sized as `(CHUNK_SIZE + 4091) / 4092`. I.e., to
/// transfer buffers of size `1..=4092`, you need 1 descriptor.
pub fn configure_for_async<'a>(
self,
burst_mode: bool,
priority: DmaPriority,
) -> crate::dma::Channel<'a, [<DmaChannel $num>], $crate::Async> {
let this = self.do_configure(burst_mode, priority);
let mut this = Channel {
tx: ChannelTx::new(tx_impl),
rx: ChannelRx::new(rx_impl),
phantom: PhantomData,
};

[<DmaChannel $num>]::set_isr($async_handler);
this.configure(false, DmaPriority::Priority0);

this
}
Expand Down Expand Up @@ -617,19 +628,19 @@ crate::impl_dma_eligible! {
pub struct Dma<'d> {
_inner: PeripheralRef<'d, crate::peripherals::DMA>,
/// Channel 0
pub channel0: ChannelCreator<0>,
pub channel0: Channel<'d, DmaChannel0, Blocking>,
/// Channel 1
#[cfg(not(esp32c2))]
pub channel1: ChannelCreator<1>,
pub channel1: Channel<'d, DmaChannel1, Blocking>,
/// Channel 2
#[cfg(not(esp32c2))]
pub channel2: ChannelCreator<2>,
pub channel2: Channel<'d, DmaChannel2, Blocking>,
/// Channel 3
#[cfg(esp32s3)]
pub channel3: ChannelCreator<3>,
pub channel3: Channel<'d, DmaChannel3, Blocking>,
/// Channel 4
#[cfg(esp32s3)]
pub channel4: ChannelCreator<4>,
pub channel4: Channel<'d, DmaChannel4, Blocking>,
}

impl<'d> Dma<'d> {
Expand All @@ -645,17 +656,19 @@ impl<'d> Dma<'d> {
.modify(|_, w| w.ahbm_rst_inter().clear_bit());
dma.misc_conf().modify(|_, w| w.clk_en().set_bit());

Dma {
_inner: dma,
channel0: ChannelCreator {},
#[cfg(not(esp32c2))]
channel1: ChannelCreator {},
#[cfg(not(esp32c2))]
channel2: ChannelCreator {},
#[cfg(esp32s3)]
channel3: ChannelCreator {},
#[cfg(esp32s3)]
channel4: ChannelCreator {},
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(),
}
}
}
}
42 changes: 31 additions & 11 deletions esp-hal/src/dma/m2m.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use crate::{
Tx,
WriteBuffer,
},
Async,
Blocking,
Mode,
};

Expand All @@ -36,19 +38,18 @@ where
peripheral: DmaPeripheral,
}

impl<'d, M> Mem2Mem<'d, M>
where
M: Mode,
{
impl<'d> Mem2Mem<'d, Blocking> {
/// Create a new Mem2Mem instance.
pub fn new<CH>(
channel: Channel<'d, CH, M>,
pub fn new<CH, DM>(
channel: Channel<'d, CH, DM>,
peripheral: impl DmaEligible,
rx_descriptors: &'static mut [DmaDescriptor],
tx_descriptors: &'static mut [DmaDescriptor],
) -> Result<Self, DmaError>
where
CH: DmaChannelConvert<AnyGdmaChannel>,
DM: Mode,
Channel<'d, CH, Blocking>: From<Channel<'d, CH, DM>>,
{
unsafe {
Self::new_unsafe(
Expand All @@ -62,15 +63,17 @@ where
}

/// Create a new Mem2Mem instance with specific chunk size.
pub fn new_with_chunk_size<CH>(
channel: Channel<'d, CH, M>,
pub fn new_with_chunk_size<CH, DM>(
channel: Channel<'d, CH, DM>,
peripheral: impl DmaEligible,
rx_descriptors: &'static mut [DmaDescriptor],
tx_descriptors: &'static mut [DmaDescriptor],
chunk_size: usize,
) -> Result<Self, DmaError>
where
CH: DmaChannelConvert<AnyGdmaChannel>,
DM: Mode,
Channel<'d, CH, Blocking>: From<Channel<'d, CH, DM>>,
{
unsafe {
Self::new_unsafe(
Expand All @@ -89,15 +92,17 @@ where
///
/// You must ensure that your not using DMA for the same peripheral and
/// that your the only one using the DmaPeripheral.
pub unsafe fn new_unsafe<CH>(
channel: Channel<'d, CH, M>,
pub unsafe fn new_unsafe<CH, DM>(
channel: Channel<'d, CH, DM>,
peripheral: DmaPeripheral,
rx_descriptors: &'static mut [DmaDescriptor],
tx_descriptors: &'static mut [DmaDescriptor],
chunk_size: usize,
) -> Result<Self, DmaError>
where
CH: DmaChannelConvert<AnyGdmaChannel>,
DM: Mode,
Channel<'d, CH, Blocking>: From<Channel<'d, CH, DM>>,
{
if !(1..=4092).contains(&chunk_size) {
return Err(DmaError::InvalidChunkSize);
Expand All @@ -106,13 +111,28 @@ where
return Err(DmaError::OutOfDescriptors);
}
Ok(Mem2Mem {
channel: channel.degrade(),
channel: Channel::<_, Blocking>::from(channel).degrade(),
peripheral,
rx_chain: DescriptorChain::new_with_chunk_size(rx_descriptors, chunk_size),
tx_chain: DescriptorChain::new_with_chunk_size(tx_descriptors, chunk_size),
})
}

/// Convert Mem2Mem to an async Mem2Mem.
pub fn into_async(self) -> Mem2Mem<'d, Async> {
Mem2Mem {
channel: self.channel.into_async(),
rx_chain: self.rx_chain,
tx_chain: self.tx_chain,
peripheral: self.peripheral,
}
}
}

impl<'d, M> Mem2Mem<'d, M>
where
M: Mode,
{
/// Start a memory to memory transfer.
pub fn start_transfer<'t, TXBUF, RXBUF>(
&mut self,
Expand Down
Loading

0 comments on commit a179100

Please sign in to comment.