Split DMA RegisterAccess trait into RX/TX (#2249)

* Reduce macro usage in PDMA

* Split DMA RegisterAccess trait into RX/TX

* Move set_isr to Ext trait

---------

Co-authored-by: Dominic Fischer <git@dominicfischer.me>
This commit is contained in:
Dominic Fischer 2024-09-30 14:32:18 +01:00 committed by GitHub
parent 487de0ff22
commit f1bedbe3dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 1192 additions and 1070 deletions

View File

@ -21,11 +21,17 @@ use crate::{
}; };
#[non_exhaustive] #[non_exhaustive]
pub struct Channel<const N: u8> {} #[doc(hidden)]
pub struct ChannelTxImpl<const N: u8> {}
impl<const N: u8> crate::private::Sealed for Channel<N> {} use embassy_sync::waitqueue::AtomicWaker;
impl<const N: u8> Channel<N> { static TX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [const { AtomicWaker::new() }; CHANNEL_COUNT];
static RX_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [const { AtomicWaker::new() }; CHANNEL_COUNT];
impl<const N: u8> crate::private::Sealed for ChannelTxImpl<N> {}
impl<const N: u8> ChannelTxImpl<N> {
#[inline(always)] #[inline(always)]
fn ch() -> &'static crate::peripherals::dma::ch::CH { fn ch() -> &'static crate::peripherals::dma::ch::CH {
let dma = unsafe { &*crate::peripherals::DMA::PTR }; let dma = unsafe { &*crate::peripherals::DMA::PTR };
@ -34,74 +40,77 @@ impl<const N: u8> Channel<N> {
#[cfg(any(esp32c2, esp32c3))] #[cfg(any(esp32c2, esp32c3))]
#[inline(always)] #[inline(always)]
fn in_int() -> &'static crate::peripherals::dma::int_ch::INT_CH { fn int() -> &'static crate::peripherals::dma::int_ch::INT_CH {
let dma = unsafe { &*crate::peripherals::DMA::PTR }; let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.int_ch(N as usize) dma.int_ch(N as usize)
} }
#[inline(always)] #[inline(always)]
#[cfg(any(esp32c6, esp32h2))] #[cfg(any(esp32c6, esp32h2))]
fn in_int() -> &'static crate::peripherals::dma::in_int_ch::IN_INT_CH { fn int() -> &'static crate::peripherals::dma::out_int_ch::OUT_INT_CH {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.in_int_ch(N as usize)
}
#[cfg(esp32s3)]
#[inline(always)]
fn in_int() -> &'static crate::peripherals::dma::ch::in_int::IN_INT {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.ch(N as usize).in_int()
}
#[cfg(any(esp32c2, esp32c3))]
#[inline(always)]
fn out_int() -> &'static crate::peripherals::dma::int_ch::INT_CH {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.int_ch(N as usize)
}
#[inline(always)]
#[cfg(any(esp32c6, esp32h2))]
fn out_int() -> &'static crate::peripherals::dma::out_int_ch::OUT_INT_CH {
let dma = unsafe { &*crate::peripherals::DMA::PTR }; let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.out_int_ch(N as usize) dma.out_int_ch(N as usize)
} }
#[cfg(esp32s3)] #[cfg(esp32s3)]
#[inline(always)] #[inline(always)]
fn out_int() -> &'static crate::peripherals::dma::ch::out_int::OUT_INT { fn int() -> &'static crate::peripherals::dma::ch::out_int::OUT_INT {
let dma = unsafe { &*crate::peripherals::DMA::PTR }; let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.ch(N as usize).out_int() dma.ch(N as usize).out_int()
} }
} }
impl<const N: u8> RegisterAccess for Channel<N> { impl<const N: u8> RegisterAccess for ChannelTxImpl<N> {
#[cfg(gdma)] fn reset(&self) {
fn set_mem2mem_mode(value: bool) { let conf0 = Self::ch().out_conf0();
Self::ch() conf0.modify(|_, w| w.out_rst().set_bit());
.in_conf0() conf0.modify(|_, w| w.out_rst().clear_bit());
.modify(|_, w| w.mem_trans_en().bit(value));
} }
#[cfg(esp32s3)] fn set_burst_mode(&self, burst_mode: bool) {
fn set_out_ext_mem_block_size(size: DmaExtMemBKSize) {
Self::ch()
.out_conf1()
.modify(|_, w| unsafe { w.out_ext_mem_bk_size().bits(size as u8) });
}
fn set_out_burstmode(burst_mode: bool) {
Self::ch().out_conf0().modify(|_, w| { Self::ch().out_conf0().modify(|_, w| {
w.out_data_burst_en().bit(burst_mode); w.out_data_burst_en().bit(burst_mode);
w.outdscr_burst_en().bit(burst_mode) w.outdscr_burst_en().bit(burst_mode)
}); });
} }
fn set_out_priority(priority: DmaPriority) { fn set_priority(&self, priority: DmaPriority) {
Self::ch() Self::ch()
.out_pri() .out_pri()
.write(|w| unsafe { w.tx_pri().bits(priority as u8) }); .write(|w| unsafe { w.tx_pri().bits(priority as u8) });
} }
fn clear_out_interrupts() { fn set_peripheral(&self, peripheral: u8) {
Self::ch()
.out_peri_sel()
.modify(|_, w| unsafe { w.peri_out_sel().bits(peripheral) });
}
fn set_link_addr(&self, address: u32) {
Self::ch()
.out_link()
.modify(|_, w| unsafe { w.outlink_addr().bits(address) });
}
fn start(&self) {
Self::ch()
.out_link()
.modify(|_, w| w.outlink_start().set_bit());
}
fn stop(&self) {
Self::ch()
.out_link()
.modify(|_, w| w.outlink_stop().set_bit());
}
fn restart(&self) {
Self::ch()
.out_link()
.modify(|_, w| w.outlink_restart().set_bit());
}
fn clear_interrupts(&self) {
#[cfg(not(esp32s3))] #[cfg(not(esp32s3))]
Self::out_int().clr().write(|w| { Self::int().clr().write(|w| {
w.out_eof().clear_bit_by_one(); w.out_eof().clear_bit_by_one();
w.out_dscr_err().clear_bit_by_one(); w.out_dscr_err().clear_bit_by_one();
w.out_done().clear_bit_by_one(); w.out_done().clear_bit_by_one();
@ -111,7 +120,7 @@ impl<const N: u8> RegisterAccess for Channel<N> {
}); });
#[cfg(esp32s3)] #[cfg(esp32s3)]
Self::out_int().clr().write(|w| { Self::int().clr().write(|w| {
w.out_eof().clear_bit_by_one(); w.out_eof().clear_bit_by_one();
w.out_dscr_err().clear_bit_by_one(); w.out_dscr_err().clear_bit_by_one();
w.out_done().clear_bit_by_one(); w.out_done().clear_bit_by_one();
@ -123,122 +132,27 @@ impl<const N: u8> RegisterAccess for Channel<N> {
}); });
} }
fn reset_out() { #[cfg(esp32s3)]
let conf0 = Self::ch().out_conf0(); fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
conf0.modify(|_, w| w.out_rst().set_bit());
conf0.modify(|_, w| w.out_rst().clear_bit());
}
fn set_out_descriptors(address: u32) {
Self::ch() Self::ch()
.out_link() .out_conf1()
.modify(|_, w| unsafe { w.outlink_addr().bits(address) }); .modify(|_, w| unsafe { w.out_ext_mem_bk_size().bits(size as u8) });
} }
}
fn set_out_peripheral(peripheral: u8) { impl<const N: u8> TxRegisterAccess for ChannelTxImpl<N> {
Self::ch() fn last_dscr_address(&self) -> usize {
.out_peri_sel()
.modify(|_, w| unsafe { w.peri_out_sel().bits(peripheral) });
}
fn start_out() {
Self::ch()
.out_link()
.modify(|_, w| w.outlink_start().set_bit());
}
fn stop_out() {
Self::ch()
.out_link()
.modify(|_, w| w.outlink_stop().set_bit());
}
fn last_out_dscr_address() -> usize {
Self::ch() Self::ch()
.out_eof_des_addr() .out_eof_des_addr()
.read() .read()
.out_eof_des_addr() .out_eof_des_addr()
.bits() as _ .bits() as _
} }
}
#[cfg(esp32s3)] impl<const N: u8> InterruptAccess<DmaTxInterrupt> for ChannelTxImpl<N> {
fn set_in_ext_mem_block_size(size: DmaExtMemBKSize) { fn listen(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
Self::ch() Self::int().ena().modify(|_, w| {
.in_conf1()
.modify(|_, w| unsafe { w.in_ext_mem_bk_size().bits(size as u8) });
}
fn set_in_burstmode(burst_mode: bool) {
Self::ch().in_conf0().modify(|_, w| {
w.in_data_burst_en().bit(burst_mode);
w.indscr_burst_en().bit(burst_mode)
});
}
fn set_in_priority(priority: DmaPriority) {
Self::ch()
.in_pri()
.write(|w| unsafe { w.rx_pri().bits(priority as u8) });
}
fn clear_in_interrupts() {
#[cfg(not(esp32s3))]
Self::in_int().clr().write(|w| {
w.in_suc_eof().clear_bit_by_one();
w.in_err_eof().clear_bit_by_one();
w.in_dscr_err().clear_bit_by_one();
w.in_dscr_empty().clear_bit_by_one();
w.in_done().clear_bit_by_one();
w.infifo_ovf().clear_bit_by_one();
w.infifo_udf().clear_bit_by_one()
});
#[cfg(esp32s3)]
Self::in_int().clr().write(|w| {
w.in_suc_eof().clear_bit_by_one();
w.in_err_eof().clear_bit_by_one();
w.in_dscr_err().clear_bit_by_one();
w.in_dscr_empty().clear_bit_by_one();
w.in_done().clear_bit_by_one();
w.infifo_ovf_l1().clear_bit_by_one();
w.infifo_ovf_l3().clear_bit_by_one();
w.infifo_udf_l1().clear_bit_by_one();
w.infifo_udf_l3().clear_bit_by_one()
});
}
fn reset_in() {
let conf0 = Self::ch().in_conf0();
conf0.modify(|_, w| w.in_rst().set_bit());
conf0.modify(|_, w| w.in_rst().clear_bit());
}
fn set_in_descriptors(address: u32) {
Self::ch()
.in_link()
.modify(|_, w| unsafe { w.inlink_addr().bits(address) });
}
fn set_in_peripheral(peripheral: u8) {
Self::ch()
.in_peri_sel()
.modify(|_, w| unsafe { w.peri_in_sel().bits(peripheral) });
}
fn start_in() {
Self::ch()
.in_link()
.modify(|_, w| w.inlink_start().set_bit());
}
fn stop_in() {
Self::ch()
.in_link()
.modify(|_, w| w.inlink_stop().set_bit());
}
fn listen_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
Self::out_int().ena().modify(|_, w| {
for interrupt in interrupts.into() { for interrupt in interrupts.into() {
match interrupt { match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().set_bit(), DmaTxInterrupt::TotalEof => w.out_total_eof().set_bit(),
@ -251,8 +165,8 @@ impl<const N: u8> RegisterAccess for Channel<N> {
}) })
} }
fn unlisten_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) { fn unlisten(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
Self::out_int().ena().modify(|_, w| { Self::int().ena().modify(|_, w| {
for interrupt in interrupts.into() { for interrupt in interrupts.into() {
match interrupt { match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit(), DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit(),
@ -265,10 +179,10 @@ impl<const N: u8> RegisterAccess for Channel<N> {
}) })
} }
fn is_listening_out() -> EnumSet<DmaTxInterrupt> { fn is_listening(&self) -> EnumSet<DmaTxInterrupt> {
let mut result = EnumSet::new(); let mut result = EnumSet::new();
let int_ena = Self::out_int().ena().read(); let int_ena = Self::int().ena().read();
if int_ena.out_total_eof().bit_is_set() { if int_ena.out_total_eof().bit_is_set() {
result |= DmaTxInterrupt::TotalEof; result |= DmaTxInterrupt::TotalEof;
} }
@ -285,10 +199,24 @@ impl<const N: u8> RegisterAccess for Channel<N> {
result result
} }
fn pending_out_interrupts() -> EnumSet<DmaTxInterrupt> { fn clear(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
Self::int().clr().write(|w| {
for interrupt in interrupts.into() {
match interrupt {
DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit_by_one(),
DmaTxInterrupt::DescriptorError => w.out_dscr_err().clear_bit_by_one(),
DmaTxInterrupt::Eof => w.out_eof().clear_bit_by_one(),
DmaTxInterrupt::Done => w.out_done().clear_bit_by_one(),
};
}
w
})
}
fn pending_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
let mut result = EnumSet::new(); let mut result = EnumSet::new();
let int_raw = Self::out_int().raw().read(); let int_raw = Self::int().raw().read();
if int_raw.out_total_eof().bit_is_set() { if int_raw.out_total_eof().bit_is_set() {
result |= DmaTxInterrupt::TotalEof; result |= DmaTxInterrupt::TotalEof;
} }
@ -305,22 +233,141 @@ impl<const N: u8> RegisterAccess for Channel<N> {
result result
} }
fn clear_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>) { fn waker(&self) -> &'static AtomicWaker {
Self::out_int().clr().write(|w| { &TX_WAKERS[N as usize]
for interrupt in interrupts.into() { }
match interrupt { }
DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit_by_one(),
DmaTxInterrupt::DescriptorError => w.out_dscr_err().clear_bit_by_one(), #[non_exhaustive]
DmaTxInterrupt::Eof => w.out_eof().clear_bit_by_one(), #[doc(hidden)]
DmaTxInterrupt::Done => w.out_done().clear_bit_by_one(), pub struct ChannelRxImpl<const N: u8> {}
};
} impl<const N: u8> crate::private::Sealed for ChannelRxImpl<N> {}
w
}) impl<const N: u8> ChannelRxImpl<N> {
#[inline(always)]
fn ch() -> &'static crate::peripherals::dma::ch::CH {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.ch(N as usize)
} }
fn listen_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) { #[cfg(any(esp32c2, esp32c3))]
Self::in_int().ena().modify(|_, w| { #[inline(always)]
fn int() -> &'static crate::peripherals::dma::int_ch::INT_CH {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.int_ch(N as usize)
}
#[inline(always)]
#[cfg(any(esp32c6, esp32h2))]
fn int() -> &'static crate::peripherals::dma::in_int_ch::IN_INT_CH {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.in_int_ch(N as usize)
}
#[cfg(esp32s3)]
#[inline(always)]
fn int() -> &'static crate::peripherals::dma::ch::in_int::IN_INT {
let dma = unsafe { &*crate::peripherals::DMA::PTR };
dma.ch(N as usize).in_int()
}
}
impl<const N: u8> RegisterAccess for ChannelRxImpl<N> {
fn reset(&self) {
let conf0 = Self::ch().in_conf0();
conf0.modify(|_, w| w.in_rst().set_bit());
conf0.modify(|_, w| w.in_rst().clear_bit());
}
fn set_burst_mode(&self, burst_mode: bool) {
Self::ch().in_conf0().modify(|_, w| {
w.in_data_burst_en().bit(burst_mode);
w.indscr_burst_en().bit(burst_mode)
});
}
fn set_priority(&self, priority: DmaPriority) {
Self::ch()
.in_pri()
.write(|w| unsafe { w.rx_pri().bits(priority as u8) });
}
fn set_peripheral(&self, peripheral: u8) {
Self::ch()
.in_peri_sel()
.modify(|_, w| unsafe { w.peri_in_sel().bits(peripheral) });
}
fn set_link_addr(&self, address: u32) {
Self::ch()
.in_link()
.modify(|_, w| unsafe { w.inlink_addr().bits(address) });
}
fn start(&self) {
Self::ch()
.in_link()
.modify(|_, w| w.inlink_start().set_bit());
}
fn stop(&self) {
Self::ch()
.in_link()
.modify(|_, w| w.inlink_stop().set_bit());
}
fn restart(&self) {
Self::ch()
.in_link()
.modify(|_, w| w.inlink_restart().set_bit());
}
fn clear_interrupts(&self) {
#[cfg(not(esp32s3))]
Self::int().clr().write(|w| {
w.in_suc_eof().clear_bit_by_one();
w.in_err_eof().clear_bit_by_one();
w.in_dscr_err().clear_bit_by_one();
w.in_dscr_empty().clear_bit_by_one();
w.in_done().clear_bit_by_one();
w.infifo_ovf().clear_bit_by_one();
w.infifo_udf().clear_bit_by_one()
});
#[cfg(esp32s3)]
Self::int().clr().write(|w| {
w.in_suc_eof().clear_bit_by_one();
w.in_err_eof().clear_bit_by_one();
w.in_dscr_err().clear_bit_by_one();
w.in_dscr_empty().clear_bit_by_one();
w.in_done().clear_bit_by_one();
w.infifo_ovf_l1().clear_bit_by_one();
w.infifo_ovf_l3().clear_bit_by_one();
w.infifo_udf_l1().clear_bit_by_one();
w.infifo_udf_l3().clear_bit_by_one()
});
}
#[cfg(esp32s3)]
fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
Self::ch()
.in_conf1()
.modify(|_, w| unsafe { w.in_ext_mem_bk_size().bits(size as u8) });
}
}
impl<const N: u8> RxRegisterAccess for ChannelRxImpl<N> {
fn set_mem2mem_mode(&self, value: bool) {
Self::ch()
.in_conf0()
.modify(|_, w| w.mem_trans_en().bit(value));
}
}
impl<const N: u8> InterruptAccess<DmaRxInterrupt> for ChannelRxImpl<N> {
fn listen(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
Self::int().ena().modify(|_, w| {
for interrupt in interrupts.into() { for interrupt in interrupts.into() {
match interrupt { match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().set_bit(), DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().set_bit(),
@ -331,11 +378,11 @@ impl<const N: u8> RegisterAccess for Channel<N> {
}; };
} }
w w
}) });
} }
fn unlisten_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) { fn unlisten(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
Self::in_int().ena().modify(|_, w| { Self::int().ena().modify(|_, w| {
for interrupt in interrupts.into() { for interrupt in interrupts.into() {
match interrupt { match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit(), DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit(),
@ -349,10 +396,10 @@ impl<const N: u8> RegisterAccess for Channel<N> {
}) })
} }
fn is_listening_in() -> EnumSet<DmaRxInterrupt> { fn is_listening(&self) -> EnumSet<DmaRxInterrupt> {
let mut result = EnumSet::new(); let mut result = EnumSet::new();
let int_ena = Self::in_int().ena().read(); let int_ena = Self::int().ena().read();
if int_ena.in_dscr_err().bit_is_set() { if int_ena.in_dscr_err().bit_is_set() {
result |= DmaRxInterrupt::DescriptorError; result |= DmaRxInterrupt::DescriptorError;
} }
@ -372,10 +419,25 @@ impl<const N: u8> RegisterAccess for Channel<N> {
result result
} }
fn pending_in_interrupts() -> EnumSet<DmaRxInterrupt> { fn clear(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
Self::int().clr().write(|w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit_by_one(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit_by_one(),
DmaRxInterrupt::DescriptorError => w.in_dscr_err().clear_bit_by_one(),
DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().clear_bit_by_one(),
DmaRxInterrupt::Done => w.in_done().clear_bit_by_one(),
};
}
w
})
}
fn pending_interrupts(&self) -> EnumSet<DmaRxInterrupt> {
let mut result = EnumSet::new(); let mut result = EnumSet::new();
let int_raw = Self::in_int().raw().read(); let int_raw = Self::int().raw().read();
if int_raw.in_dscr_err().bit_is_set() { if int_raw.in_dscr_err().bit_is_set() {
result |= DmaRxInterrupt::DescriptorError; result |= DmaRxInterrupt::DescriptorError;
} }
@ -395,47 +457,7 @@ impl<const N: u8> RegisterAccess for Channel<N> {
result result
} }
fn clear_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>) { fn waker(&self) -> &'static AtomicWaker {
Self::in_int().clr().write(|w| {
for interrupt in interrupts.into() {
match interrupt {
DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit_by_one(),
DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit_by_one(),
DmaRxInterrupt::DescriptorError => w.in_dscr_err().clear_bit_by_one(),
DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().clear_bit_by_one(),
DmaRxInterrupt::Done => w.in_done().clear_bit_by_one(),
};
}
w
})
}
}
#[non_exhaustive]
#[doc(hidden)]
pub struct ChannelTxImpl<const N: u8> {}
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];
impl<const N: u8> crate::private::Sealed for ChannelTxImpl<N> {}
impl<const N: u8> TxChannel<Channel<N>> for ChannelTxImpl<N> {
fn waker() -> &'static AtomicWaker {
&TX_WAKERS[N as usize]
}
}
#[non_exhaustive]
#[doc(hidden)]
pub struct ChannelRxImpl<const N: u8> {}
impl<const N: u8> crate::private::Sealed for ChannelRxImpl<N> {}
impl<const N: u8> RxChannel<Channel<N>> for ChannelRxImpl<N> {
fn waker() -> &'static AtomicWaker {
&RX_WAKERS[N as usize] &RX_WAKERS[N as usize]
} }
} }
@ -477,10 +499,19 @@ macro_rules! impl_channel {
impl crate::private::Sealed for [<DmaChannel $num>] {} impl crate::private::Sealed for [<DmaChannel $num>] {}
impl DmaChannel for [<DmaChannel $num>] { impl DmaChannel for [<DmaChannel $num>] {
type Channel = Channel<$num>;
type Rx = ChannelRxImpl<$num>; type Rx = ChannelRxImpl<$num>;
type Tx = ChannelTxImpl<$num>; type Tx = ChannelTxImpl<$num>;
type P = SuitablePeripheral<$num>; type P = SuitablePeripheral<$num>;
}
impl DmaChannelExt for [<DmaChannel $num>] {
fn get_rx_interrupts() -> impl InterruptAccess<DmaRxInterrupt> {
ChannelRxImpl::<$num> {}
}
fn get_tx_interrupts() -> impl InterruptAccess<DmaTxInterrupt> {
ChannelTxImpl::<$num> {}
}
fn set_isr(handler: $crate::interrupt::InterruptHandler) { fn set_isr(handler: $crate::interrupt::InterruptHandler) {
let mut dma = unsafe { crate::peripherals::DMA::steal() }; let mut dma = unsafe { crate::peripherals::DMA::steal() };
@ -497,11 +528,17 @@ macro_rules! impl_channel {
burst_mode: bool, burst_mode: bool,
priority: DmaPriority, priority: DmaPriority,
) -> crate::dma::Channel<'a, [<DmaChannel $num>], M> { ) -> crate::dma::Channel<'a, [<DmaChannel $num>], M> {
let mut tx_impl = ChannelTxImpl {}; let tx_impl = ChannelTxImpl {};
tx_impl.init(burst_mode, priority); tx_impl.set_burst_mode(burst_mode);
tx_impl.set_priority(priority);
let mut rx_impl = ChannelRxImpl {}; let rx_impl = ChannelRxImpl {};
rx_impl.init(burst_mode, priority); 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.
#[cfg(gdma)]
rx_impl.set_mem2mem_mode(false);
crate::dma::Channel { crate::dma::Channel {
tx: ChannelTx::new(tx_impl, burst_mode), tx: ChannelTx::new(tx_impl, burst_mode),

View File

@ -1497,17 +1497,20 @@ impl RxCircularState {
/// A description of a DMA Channel. /// A description of a DMA Channel.
pub trait DmaChannel: crate::private::Sealed { pub trait DmaChannel: crate::private::Sealed {
#[doc(hidden)]
type Channel: RegisterAccess;
/// A description of the RX half of a DMA Channel. /// A description of the RX half of a DMA Channel.
type Rx: RxChannel<Self::Channel>; type Rx: RxRegisterAccess + InterruptAccess<DmaRxInterrupt>;
/// A description of the TX half of a DMA Channel. /// A description of the TX half of a DMA Channel.
type Tx: TxChannel<Self::Channel>; type Tx: TxRegisterAccess + InterruptAccess<DmaTxInterrupt>;
/// A suitable peripheral for this DMA channel. /// A suitable peripheral for this DMA channel.
type P: PeripheralMarker; type P: PeripheralMarker;
}
#[doc(hidden)]
pub trait DmaChannelExt: DmaChannel {
fn get_rx_interrupts() -> impl InterruptAccess<DmaRxInterrupt>;
fn get_tx_interrupts() -> impl InterruptAccess<DmaTxInterrupt>;
#[doc(hidden)] #[doc(hidden)]
fn set_isr(handler: InterruptHandler); fn set_isr(handler: InterruptHandler);
@ -1516,8 +1519,6 @@ pub trait DmaChannel: crate::private::Sealed {
/// The functions here are not meant to be used outside the HAL /// The functions here are not meant to be used outside the HAL
#[doc(hidden)] #[doc(hidden)]
pub trait Rx: crate::private::Sealed { pub trait Rx: crate::private::Sealed {
fn init(&mut self, burst_mode: bool, priority: DmaPriority);
unsafe fn prepare_transfer_without_start( unsafe fn prepare_transfer_without_start(
&mut self, &mut self,
peri: DmaPeripheral, peri: DmaPeripheral,
@ -1569,53 +1570,7 @@ pub trait Rx: crate::private::Sealed {
fn clear_interrupts(&self); fn clear_interrupts(&self);
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker; fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker;
}
#[doc(hidden)]
pub trait RxChannel<R>: crate::private::Sealed
where
R: RegisterAccess,
{
fn init(&mut self, burst_mode: bool, priority: DmaPriority) {
R::set_in_burstmode(burst_mode);
R::set_in_priority(priority);
// clear the mem2mem mode to avoid failed DMA if this
// channel was previously used for a mem2mem transfer.
#[cfg(gdma)]
R::set_mem2mem_mode(false);
}
unsafe fn prepare_transfer_without_start(
&mut self,
first_desc: *mut DmaDescriptor,
peri: DmaPeripheral,
) -> Result<(), DmaError> {
compiler_fence(core::sync::atomic::Ordering::SeqCst);
R::clear_in_interrupts();
R::reset_in();
R::set_in_descriptors(first_desc as u32);
R::set_in_peripheral(peri as u8);
Ok(())
}
fn start_transfer(&mut self) -> Result<(), DmaError> {
R::start_in();
if R::pending_in_interrupts().contains(DmaRxInterrupt::DescriptorError) {
Err(DmaError::DescriptorError)
} else {
Ok(())
}
}
fn stop_transfer(&mut self) {
R::stop_in();
}
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker;
} }
// DMA receive channel // DMA receive channel
@ -1649,10 +1604,6 @@ impl<'a, CH> Rx for ChannelRx<'a, CH>
where where
CH: DmaChannel, CH: DmaChannel,
{ {
fn init(&mut self, burst_mode: bool, priority: DmaPriority) {
self.rx_impl.init(burst_mode, priority);
}
unsafe fn prepare_transfer_without_start( unsafe fn prepare_transfer_without_start(
&mut self, &mut self,
peri: DmaPeripheral, peri: DmaPeripheral,
@ -1685,8 +1636,14 @@ where
} }
} }
self.rx_impl compiler_fence(core::sync::atomic::Ordering::SeqCst);
.prepare_transfer_without_start(chain.first() as _, peri)
self.rx_impl.clear_interrupts();
self.rx_impl.reset();
self.rx_impl.set_link_addr(chain.first() as u32);
self.rx_impl.set_peripheral(peri as u8);
Ok(())
} }
unsafe fn prepare_transfer<BUF: DmaRxBuffer>( unsafe fn prepare_transfer<BUF: DmaRxBuffer>(
@ -1701,46 +1658,61 @@ where
return Err(DmaError::InvalidAlignment); return Err(DmaError::InvalidAlignment);
} }
self.rx_impl compiler_fence(core::sync::atomic::Ordering::SeqCst);
.prepare_transfer_without_start(preparation.start, peri)
self.rx_impl.clear_interrupts();
self.rx_impl.reset();
self.rx_impl.set_link_addr(preparation.start as u32);
self.rx_impl.set_peripheral(peri as u8);
Ok(())
} }
fn start_transfer(&mut self) -> Result<(), DmaError> { fn start_transfer(&mut self) -> Result<(), DmaError> {
self.rx_impl.start_transfer() self.rx_impl.start();
if self
.pending_in_interrupts()
.contains(DmaRxInterrupt::DescriptorError)
{
Err(DmaError::DescriptorError)
} else {
Ok(())
}
} }
fn stop_transfer(&mut self) { fn stop_transfer(&mut self) {
self.rx_impl.stop_transfer() self.rx_impl.stop()
} }
#[cfg(esp32s3)] #[cfg(esp32s3)]
fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) { fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
CH::Channel::set_in_ext_mem_block_size(size); self.rx_impl.set_ext_mem_block_size(size);
} }
#[cfg(gdma)] #[cfg(gdma)]
fn set_mem2mem_mode(&mut self, value: bool) { fn set_mem2mem_mode(&mut self, value: bool) {
CH::Channel::set_mem2mem_mode(value); self.rx_impl.set_mem2mem_mode(value);
} }
fn listen_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) { fn listen_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
CH::Channel::listen_in(interrupts); self.rx_impl.listen(interrupts);
} }
fn unlisten_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) { fn unlisten_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
CH::Channel::unlisten_in(interrupts); self.rx_impl.unlisten(interrupts);
} }
fn is_listening_in(&self) -> EnumSet<DmaRxInterrupt> { fn is_listening_in(&self) -> EnumSet<DmaRxInterrupt> {
CH::Channel::is_listening_in() self.rx_impl.is_listening()
} }
fn clear_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) { fn clear_in(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
CH::Channel::clear_in(interrupts); self.rx_impl.clear(interrupts);
} }
fn pending_in_interrupts(&self) -> EnumSet<DmaRxInterrupt> { fn pending_in_interrupts(&self) -> EnumSet<DmaRxInterrupt> {
CH::Channel::pending_in_interrupts() self.rx_impl.pending_interrupts()
} }
fn is_done(&self) -> bool { fn is_done(&self) -> bool {
@ -1749,19 +1721,17 @@ where
} }
fn clear_interrupts(&self) { fn clear_interrupts(&self) {
CH::Channel::clear_in_interrupts(); self.rx_impl.clear_interrupts();
} }
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker { fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker {
CH::Rx::waker() self.rx_impl.waker()
} }
} }
/// The functions here are not meant to be used outside the HAL /// The functions here are not meant to be used outside the HAL
#[doc(hidden)] #[doc(hidden)]
pub trait Tx: crate::private::Sealed { pub trait Tx: crate::private::Sealed {
fn init(&mut self, burst_mode: bool, priority: DmaPriority);
unsafe fn prepare_transfer_without_start( unsafe fn prepare_transfer_without_start(
&mut self, &mut self,
peri: DmaPeripheral, peri: DmaPeripheral,
@ -1803,69 +1773,11 @@ pub trait Tx: crate::private::Sealed {
fn clear_interrupts(&self); fn clear_interrupts(&self);
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker; fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker;
fn last_out_dscr_address(&self) -> usize; fn last_out_dscr_address(&self) -> usize;
} }
#[doc(hidden)]
pub trait TxChannel<R>: crate::private::Sealed
where
R: RegisterAccess,
{
fn init(&mut self, burst_mode: bool, priority: DmaPriority) {
R::set_out_burstmode(burst_mode);
R::set_out_priority(priority);
}
unsafe fn prepare_transfer_without_start(
&mut self,
first_desc: *mut DmaDescriptor,
peri: DmaPeripheral,
) -> Result<(), DmaError> {
compiler_fence(core::sync::atomic::Ordering::SeqCst);
R::clear_out_interrupts();
R::reset_out();
R::set_out_descriptors(first_desc as u32);
R::set_out_peripheral(peri as u8);
Ok(())
}
fn start_transfer(&mut self) -> Result<(), DmaError> {
R::start_out();
if R::pending_out_interrupts().contains(DmaTxInterrupt::DescriptorError) {
Err(DmaError::DescriptorError)
} else {
Ok(())
}
}
fn stop_transfer(&mut self) {
R::stop_out();
}
fn listen_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
R::listen_out(interrupts)
}
fn unlisten_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
R::unlisten_out(interrupts)
}
fn is_listening_out(&self) -> EnumSet<DmaTxInterrupt> {
R::is_listening_out()
}
fn clear_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
R::clear_out(interrupts)
}
fn pending_out_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
R::pending_out_interrupts()
}
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker;
}
/// DMA transmit channel /// DMA transmit channel
#[doc(hidden)] #[doc(hidden)]
pub struct ChannelTx<'a, CH> pub struct ChannelTx<'a, CH>
@ -1897,10 +1809,6 @@ impl<'a, CH> Tx for ChannelTx<'a, CH>
where where
CH: DmaChannel, CH: DmaChannel,
{ {
fn init(&mut self, burst_mode: bool, priority: DmaPriority) {
self.tx_impl.init(burst_mode, priority);
}
unsafe fn prepare_transfer_without_start( unsafe fn prepare_transfer_without_start(
&mut self, &mut self,
peri: DmaPeripheral, peri: DmaPeripheral,
@ -1922,8 +1830,15 @@ where
crate::soc::cache_writeback_addr(des.buffer as u32, des.size() as u32); crate::soc::cache_writeback_addr(des.buffer as u32, des.size() as u32);
} }
} }
self.tx_impl
.prepare_transfer_without_start(chain.first() as _, peri) compiler_fence(core::sync::atomic::Ordering::SeqCst);
self.tx_impl.clear_interrupts();
self.tx_impl.reset();
self.tx_impl.set_link_addr(chain.first() as u32);
self.tx_impl.set_peripheral(peri as u8);
Ok(())
} }
unsafe fn prepare_transfer<BUF: DmaTxBuffer>( unsafe fn prepare_transfer<BUF: DmaTxBuffer>(
@ -1945,95 +1860,127 @@ where
} }
); );
// TODO: Get burst mode from DmaBuf. // TODO: Get burst mode from DmaBuf.
self.tx_impl
.prepare_transfer_without_start(preparation.start, peri) compiler_fence(core::sync::atomic::Ordering::SeqCst);
self.tx_impl.clear_interrupts();
self.tx_impl.reset();
self.tx_impl.set_link_addr(preparation.start as u32);
self.tx_impl.set_peripheral(peri as u8);
Ok(())
} }
fn start_transfer(&mut self) -> Result<(), DmaError> { fn start_transfer(&mut self) -> Result<(), DmaError> {
self.tx_impl.start_transfer() self.tx_impl.start();
if self
.pending_out_interrupts()
.contains(DmaTxInterrupt::DescriptorError)
{
Err(DmaError::DescriptorError)
} else {
Ok(())
}
} }
fn stop_transfer(&mut self) { fn stop_transfer(&mut self) {
self.tx_impl.stop_transfer() self.tx_impl.stop()
} }
#[cfg(esp32s3)] #[cfg(esp32s3)]
fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) { fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
CH::Channel::set_out_ext_mem_block_size(size); self.tx_impl.set_ext_mem_block_size(size);
} }
fn listen_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) { fn listen_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
CH::Channel::listen_out(interrupts); self.tx_impl.listen(interrupts);
} }
fn unlisten_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) { fn unlisten_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
CH::Channel::unlisten_out(interrupts); self.tx_impl.unlisten(interrupts);
} }
fn is_listening_out(&self) -> EnumSet<DmaTxInterrupt> { fn is_listening_out(&self) -> EnumSet<DmaTxInterrupt> {
CH::Channel::is_listening_out() self.tx_impl.is_listening()
} }
fn clear_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) { fn clear_out(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
CH::Channel::clear_out(interrupts); self.tx_impl.clear(interrupts);
} }
fn pending_out_interrupts(&self) -> EnumSet<DmaTxInterrupt> { fn pending_out_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
CH::Channel::pending_out_interrupts() self.tx_impl.pending_interrupts()
} }
fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker { fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker {
CH::Tx::waker() self.tx_impl.waker()
} }
fn clear_interrupts(&self) { fn clear_interrupts(&self) {
CH::Channel::clear_out_interrupts(); self.tx_impl.clear_interrupts();
} }
fn last_out_dscr_address(&self) -> usize { fn last_out_dscr_address(&self) -> usize {
CH::Channel::last_out_dscr_address() self.tx_impl.last_dscr_address()
} }
} }
#[doc(hidden)] #[doc(hidden)]
pub trait RegisterAccess: crate::private::Sealed { pub trait RegisterAccess: crate::private::Sealed {
/// Reset the state machine of the channel and FIFO pointer.
fn reset(&self);
/// Enable/Disable INCR burst transfer for channel reading
/// descriptor and accessing data in internal RAM.
fn set_burst_mode(&self, burst_mode: bool);
/// The priority of the channel. The larger the value, the higher the
/// priority.
fn set_priority(&self, priority: DmaPriority);
/// Select a peripheral for the channel.
fn set_peripheral(&self, peripheral: u8);
/// Set the address of the first descriptor.
fn set_link_addr(&self, address: u32);
/// Enable the channel for data transfer.
fn start(&self);
/// Stop the channel from transferring data.
fn stop(&self);
/// Mount a new descriptor.
fn restart(&self);
/// Clear all interrupt bits
fn clear_interrupts(&self);
#[cfg(esp32s3)]
fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize);
}
#[doc(hidden)]
pub trait RxRegisterAccess: RegisterAccess {
#[cfg(gdma)] #[cfg(gdma)]
fn set_mem2mem_mode(value: bool); fn set_mem2mem_mode(&self, value: bool);
#[cfg(esp32s3)] }
fn set_out_ext_mem_block_size(size: DmaExtMemBKSize);
fn set_out_burstmode(burst_mode: bool);
fn set_out_priority(priority: DmaPriority);
fn clear_out_interrupts();
fn reset_out();
fn set_out_descriptors(address: u32);
fn set_out_peripheral(peripheral: u8);
fn start_out();
fn stop_out();
fn listen_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>); #[doc(hidden)]
fn unlisten_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>); pub trait TxRegisterAccess: RegisterAccess {
fn is_listening_out() -> EnumSet<DmaTxInterrupt>; /// Outlink descriptor address when EOF occurs of Tx channel.
fn clear_out(interrupts: impl Into<EnumSet<DmaTxInterrupt>>); fn last_dscr_address(&self) -> usize;
fn pending_out_interrupts() -> EnumSet<DmaTxInterrupt>; }
fn listen_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>); #[doc(hidden)]
fn unlisten_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>); pub trait InterruptAccess<T: EnumSetType>: crate::private::Sealed {
fn is_listening_in() -> EnumSet<DmaRxInterrupt>; fn listen(&self, interrupts: impl Into<EnumSet<T>>);
fn clear_in(interrupts: impl Into<EnumSet<DmaRxInterrupt>>); fn unlisten(&self, interrupts: impl Into<EnumSet<T>>);
fn pending_in_interrupts() -> EnumSet<DmaRxInterrupt>; fn is_listening(&self) -> EnumSet<T>;
fn clear(&self, interrupts: impl Into<EnumSet<T>>);
fn last_out_dscr_address() -> usize; fn pending_interrupts(&self) -> EnumSet<T>;
fn waker(&self) -> &'static embassy_sync::waitqueue::AtomicWaker;
#[cfg(esp32s3)]
fn set_in_ext_mem_block_size(size: DmaExtMemBKSize);
fn set_in_burstmode(burst_mode: bool);
fn set_in_priority(priority: DmaPriority);
fn clear_in_interrupts();
fn reset_in();
fn set_in_descriptors(address: u32);
fn set_in_peripheral(peripheral: u8);
fn start_in();
fn stop_in();
} }
/// DMA Channel /// DMA Channel
@ -2057,7 +2004,10 @@ where
/// with [crate::interrupt::Priority::max()] /// with [crate::interrupt::Priority::max()]
/// ///
/// Interrupts are not enabled at the peripheral level here. /// Interrupts are not enabled at the peripheral level here.
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) { pub fn set_interrupt_handler(&mut self, handler: InterruptHandler)
where
C: DmaChannelExt,
{
C::set_isr(handler); C::set_isr(handler);
} }
@ -3001,7 +2951,7 @@ pub(crate) mod asynch {
self: core::pin::Pin<&mut Self>, self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>, cx: &mut core::task::Context<'_>,
) -> Poll<Self::Output> { ) -> Poll<Self::Output> {
TX::waker().register(cx.waker()); self.tx.waker().register(cx.waker());
if self.tx.is_done() { if self.tx.is_done() {
self.tx.clear_interrupts(); self.tx.clear_interrupts();
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
@ -3057,7 +3007,7 @@ pub(crate) mod asynch {
self: core::pin::Pin<&mut Self>, self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>, cx: &mut core::task::Context<'_>,
) -> Poll<Self::Output> { ) -> Poll<Self::Output> {
RX::waker().register(cx.waker()); self.rx.waker().register(cx.waker());
if self.rx.is_done() { if self.rx.is_done() {
self.rx.clear_interrupts(); self.rx.clear_interrupts();
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
@ -3123,7 +3073,7 @@ pub(crate) mod asynch {
self: core::pin::Pin<&mut Self>, self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>, cx: &mut core::task::Context<'_>,
) -> Poll<Self::Output> { ) -> Poll<Self::Output> {
TX::waker().register(cx.waker()); self.tx.waker().register(cx.waker());
if self if self
.tx .tx
.pending_out_interrupts() .pending_out_interrupts()
@ -3187,7 +3137,7 @@ pub(crate) mod asynch {
self: core::pin::Pin<&mut Self>, self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>, cx: &mut core::task::Context<'_>,
) -> Poll<Self::Output> { ) -> Poll<Self::Output> {
RX::waker().register(cx.waker()); self.rx.waker().register(cx.waker());
if self if self
.rx .rx
.pending_in_interrupts() .pending_in_interrupts()
@ -3229,49 +3179,58 @@ pub(crate) mod asynch {
} }
} }
fn handle_interrupt<CH: DmaChannel>() { fn handle_interrupt<CH: DmaChannelExt>() {
if CH::Channel::pending_in_interrupts().is_disjoint( let rx = CH::get_rx_interrupts();
let tx = CH::get_tx_interrupts();
if rx.pending_interrupts().is_disjoint(
DmaRxInterrupt::DescriptorError DmaRxInterrupt::DescriptorError
| DmaRxInterrupt::DescriptorEmpty | DmaRxInterrupt::DescriptorEmpty
| DmaRxInterrupt::ErrorEof, | DmaRxInterrupt::ErrorEof,
) { ) {
CH::Channel::unlisten_in( rx.unlisten(
DmaRxInterrupt::DescriptorError DmaRxInterrupt::DescriptorError
| DmaRxInterrupt::DescriptorEmpty | DmaRxInterrupt::DescriptorEmpty
| DmaRxInterrupt::ErrorEof | DmaRxInterrupt::ErrorEof
| DmaRxInterrupt::SuccessfulEof | DmaRxInterrupt::SuccessfulEof
| DmaRxInterrupt::Done, | DmaRxInterrupt::Done,
); );
CH::Rx::waker().wake() rx.waker().wake()
} }
if CH::Channel::pending_out_interrupts().contains(DmaTxInterrupt::DescriptorError) { if tx
CH::Channel::unlisten_out( .pending_interrupts()
.contains(DmaTxInterrupt::DescriptorError)
{
tx.unlisten(
DmaTxInterrupt::DescriptorError | DmaTxInterrupt::TotalEof | DmaTxInterrupt::Done, DmaTxInterrupt::DescriptorError | DmaTxInterrupt::TotalEof | DmaTxInterrupt::Done,
); );
CH::Tx::waker().wake() tx.waker().wake()
} }
if CH::Channel::pending_in_interrupts().contains(DmaRxInterrupt::SuccessfulEof) { if rx
CH::Channel::unlisten_in(DmaRxInterrupt::SuccessfulEof); .pending_interrupts()
CH::Rx::waker().wake() .contains(DmaRxInterrupt::SuccessfulEof)
}
if CH::Channel::pending_in_interrupts().contains(DmaRxInterrupt::Done) {
CH::Channel::unlisten_in(DmaRxInterrupt::Done);
CH::Rx::waker().wake()
}
if CH::Channel::pending_out_interrupts().contains(DmaTxInterrupt::TotalEof)
&& CH::Channel::is_listening_out().contains(DmaTxInterrupt::TotalEof)
{ {
CH::Channel::unlisten_out(DmaTxInterrupt::TotalEof); rx.unlisten(DmaRxInterrupt::SuccessfulEof);
CH::Tx::waker().wake() rx.waker().wake()
} }
if CH::Channel::pending_out_interrupts().contains(DmaTxInterrupt::Done) { if rx.pending_interrupts().contains(DmaRxInterrupt::Done) {
CH::Channel::unlisten_out(DmaTxInterrupt::Done); rx.unlisten(DmaRxInterrupt::Done);
CH::Tx::waker().wake() rx.waker().wake()
}
if tx.pending_interrupts().contains(DmaTxInterrupt::TotalEof)
&& tx.is_listening().contains(DmaTxInterrupt::TotalEof)
{
tx.unlisten(DmaTxInterrupt::TotalEof);
tx.waker().wake()
}
if tx.pending_interrupts().contains(DmaTxInterrupt::Done) {
tx.unlisten(DmaTxInterrupt::Done);
tx.waker().wake()
} }
} }

File diff suppressed because it is too large Load Diff