Skip to content

Commit

Permalink
Split DMA IN/OUT handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani committed Nov 12, 2024
1 parent 5e877f3 commit ae27f2f
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 8 deletions.
44 changes: 44 additions & 0 deletions esp-hal/src/dma/gdma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ use embassy_sync::waitqueue::AtomicWaker;
static TX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [const { AtomicWaker::new() }; CHANNEL_COUNT];
static RX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [const { AtomicWaker::new() }; CHANNEL_COUNT];

cfg_if::cfg_if! {
if #[cfg(any(esp32c2, esp32c3))] {
use portable_atomic::AtomicBool;
static TX_IS_ASYNC: [AtomicBool; CHANNEL_COUNT] = [const { AtomicBool::new(false) }; CHANNEL_COUNT];
static RX_IS_ASYNC: [AtomicBool; CHANNEL_COUNT] = [const { AtomicBool::new(false) }; CHANNEL_COUNT];
}
}

impl<C: GdmaChannel> crate::private::Sealed for ChannelTxImpl<C> {}

impl<C: GdmaChannel> ChannelTxImpl<C> {
Expand Down Expand Up @@ -314,6 +322,24 @@ impl<C: GdmaChannel> InterruptAccess<DmaTxInterrupt> for ChannelTxImpl<C> {
fn waker(&self) -> &'static AtomicWaker {
&TX_WAKERS[self.0.number() as usize]
}

fn is_async(&self) -> bool {
cfg_if::cfg_if! {
if #[cfg(any(esp32c2, esp32c3))] {
TX_IS_ASYNC[self.0.number() as usize].load(Ordering::Relaxed)
} else {
true
}
}
}

fn set_async(&self, _is_async: bool) {
cfg_if::cfg_if! {
if #[cfg(any(esp32c2, esp32c3))] {
TX_IS_ASYNC[self.0.number() as usize].store(_is_async, Ordering::Relaxed);
}
}
}
}

#[non_exhaustive]
Expand Down Expand Up @@ -513,6 +539,24 @@ impl<C: GdmaChannel> InterruptAccess<DmaRxInterrupt> for ChannelRxImpl<C> {
fn waker(&self) -> &'static AtomicWaker {
&RX_WAKERS[self.0.number() as usize]
}

fn is_async(&self) -> bool {
cfg_if::cfg_if! {
if #[cfg(any(esp32c2, esp32c3))] {
RX_IS_ASYNC[self.0.number() as usize].load(Ordering::Relaxed)
} else {
true
}
}
}

fn set_async(&self, _is_async: bool) {
cfg_if::cfg_if! {
if #[cfg(any(esp32c2, esp32c3))] {
RX_IS_ASYNC[self.0.number() as usize].store(_is_async, Ordering::Relaxed);
}
}
}
}

/// A Channel can be created from this
Expand Down
7 changes: 7 additions & 0 deletions esp-hal/src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1691,6 +1691,7 @@ where
if let Some(handler) = self.rx_impl.async_handler() {
self.set_interrupt_handler(handler);
}
self.rx_impl.set_async(true);
ChannelRx {
burst_mode: false,
rx_impl: self.rx_impl,
Expand Down Expand Up @@ -1724,6 +1725,7 @@ where
if let Some(interrupt) = self.rx_impl.peripheral_interrupt() {
crate::interrupt::disable(Cpu::current(), interrupt);
}
self.rx_impl.set_async(false);
ChannelRx {
burst_mode: false,
rx_impl: self.rx_impl,
Expand Down Expand Up @@ -1972,6 +1974,7 @@ where
if let Some(handler) = self.tx_impl.async_handler() {
self.set_interrupt_handler(handler);
}
self.tx_impl.set_async(true);
ChannelTx {
burst_mode: false,
tx_impl: self.tx_impl,
Expand Down Expand Up @@ -2005,6 +2008,7 @@ where
if let Some(interrupt) = self.tx_impl.peripheral_interrupt() {
crate::interrupt::disable(Cpu::current(), interrupt);
}
self.tx_impl.set_async(false);
ChannelTx {
burst_mode: false,
tx_impl: self.tx_impl,
Expand Down Expand Up @@ -2259,6 +2263,9 @@ pub trait InterruptAccess<T: EnumSetType>: crate::private::Sealed {
fn clear(&self, interrupts: impl Into<EnumSet<T>>);
fn pending_interrupts(&self) -> EnumSet<T>;
fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker;

fn is_async(&self) -> bool;
fn set_async(&self, is_async: bool);
}

/// DMA Channel
Expand Down
71 changes: 63 additions & 8 deletions esp-hal/src/dma/pdma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//! [I2S]: ../i2s/index.html
use embassy_sync::waitqueue::AtomicWaker;
use portable_atomic::{AtomicBool, Ordering};

use crate::{
dma::*,
Expand All @@ -35,6 +36,8 @@ pub trait PdmaChannel: crate::private::Sealed {

fn peripheral_interrupt(&self) -> Interrupt;
fn async_handler(&self) -> InterruptHandler;
fn rx_async_flag(&self) -> &'static AtomicBool;
fn tx_async_flag(&self) -> &'static AtomicBool;
}

#[doc(hidden)]
Expand Down Expand Up @@ -198,6 +201,14 @@ impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> InterruptAccess<DmaTxInte
fn waker(&self) -> &'static AtomicWaker {
self.0.tx_waker()
}

fn is_async(&self) -> bool {
self.0.tx_async_flag().load(Ordering::Relaxed)
}

fn set_async(&self, _is_async: bool) {
self.0.tx_async_flag().store(_is_async, Ordering::Relaxed);
}
}

impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> RegisterAccess for SpiDmaRxChannelImpl<C> {
Expand Down Expand Up @@ -348,6 +359,14 @@ impl<C: PdmaChannel<RegisterBlock = SpiRegisterBlock>> InterruptAccess<DmaRxInte
fn waker(&self) -> &'static AtomicWaker {
self.0.rx_waker()
}

fn is_async(&self) -> bool {
self.0.rx_async_flag().load(Ordering::Relaxed)
}

fn set_async(&self, _is_async: bool) {
self.0.rx_async_flag().store(_is_async, Ordering::Relaxed);
}
}

#[doc(hidden)]
Expand Down Expand Up @@ -382,12 +401,12 @@ macro_rules! ImplSpiChannel {
fn register_block(&self) -> &SpiRegisterBlock {
unsafe { &*crate::peripherals::[<SPI $num>]::PTR }
}
fn tx_waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker {
static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
fn tx_waker(&self) -> &'static AtomicWaker {
static WAKER: AtomicWaker = AtomicWaker::new();
&WAKER
}
fn rx_waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker {
static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
fn rx_waker(&self) -> &'static AtomicWaker {
static WAKER: AtomicWaker = AtomicWaker::new();
&WAKER
}

Expand All @@ -402,6 +421,14 @@ macro_rules! ImplSpiChannel {
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>] {
Expand Down Expand Up @@ -614,6 +641,14 @@ impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> InterruptAccess<DmaTxInte
fn waker(&self) -> &'static AtomicWaker {
self.0.tx_waker()
}

fn is_async(&self) -> bool {
self.0.tx_async_flag().load(Ordering::Relaxed)
}

fn set_async(&self, _is_async: bool) {
self.0.tx_async_flag().store(_is_async, Ordering::Relaxed);
}
}

impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> RegisterAccess for I2sDmaRxChannelImpl<C> {
Expand Down Expand Up @@ -770,6 +805,14 @@ impl<C: PdmaChannel<RegisterBlock = I2sRegisterBlock>> InterruptAccess<DmaRxInte
fn waker(&self) -> &'static AtomicWaker {
self.0.rx_waker()
}

fn is_async(&self) -> bool {
self.0.rx_async_flag().load(Ordering::Relaxed)
}

fn set_async(&self, _is_async: bool) {
self.0.rx_async_flag().store(_is_async, Ordering::Relaxed);
}
}

macro_rules! ImplI2sChannel {
Expand Down Expand Up @@ -800,12 +843,12 @@ macro_rules! ImplI2sChannel {
fn register_block(&self) -> &I2sRegisterBlock {
unsafe { &*crate::peripherals::[< I2S $num >]::PTR }
}
fn tx_waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker {
static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
fn tx_waker(&self) -> &'static AtomicWaker {
static WAKER: AtomicWaker = AtomicWaker::new();
&WAKER
}
fn rx_waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker {
static WAKER: embassy_sync::waitqueue::AtomicWaker = embassy_sync::waitqueue::AtomicWaker::new();
fn rx_waker(&self) -> &'static AtomicWaker {
static WAKER: AtomicWaker = AtomicWaker::new();
&WAKER
}
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
Expand All @@ -819,6 +862,14 @@ macro_rules! ImplI2sChannel {
fn async_handler(&self) -> InterruptHandler {
super::asynch::interrupt::[< interrupt_handler_i2s $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<AnyI2sDmaChannel> for [<I2s $num DmaChannel>] {
Expand Down Expand Up @@ -968,6 +1019,8 @@ impl PdmaChannel for AnySpiDmaChannelInner {
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool;
fn peripheral_interrupt(&self) -> Interrupt;
fn async_handler(&self) -> InterruptHandler;
fn rx_async_flag(&self) -> &'static AtomicBool;
fn tx_async_flag(&self) -> &'static AtomicBool;
}
}
}
Expand Down Expand Up @@ -1008,6 +1061,8 @@ impl PdmaChannel for AnyI2sDmaChannelInner {
fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool;
fn peripheral_interrupt(&self) -> Interrupt;
fn async_handler(&self) -> InterruptHandler;
fn rx_async_flag(&self) -> &'static AtomicBool;
fn tx_async_flag(&self) -> &'static AtomicBool;
}
}
}

0 comments on commit ae27f2f

Please sign in to comment.