diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index 674255dd..94c15811 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs @@ -6,7 +6,6 @@ use core::task::Waker; use embassy_sync::waitqueue::AtomicWaker; use super::{TransferOptions, Word, WordSize}; -use crate::_generated::BDMA_CHANNEL_COUNT; use crate::dma::Request; use crate::interrupt::{Interrupt, InterruptExt}; use crate::pac; @@ -22,21 +21,6 @@ impl From for vals::Size { } } -struct State { - ch_wakers: [AtomicWaker; BDMA_CHANNEL_COUNT], -} - -impl State { - const fn new() -> Self { - const AW: AtomicWaker = AtomicWaker::new(); - Self { - ch_wakers: [AW; BDMA_CHANNEL_COUNT], - } - } -} - -static STATE: State = State::new(); - /// safety: must be called only once pub(crate) unsafe fn init() { foreach_interrupt! { @@ -52,6 +36,13 @@ foreach_dma_channel! { // BDMA1 in H7 doesn't use DMAMUX, which breaks }; ($channel_peri:ident, $dma_peri:ident, bdma, $channel_num:expr, $index:expr, $dmamux:tt) => { + impl crate::peripherals::$channel_peri { + fn waker() -> &'static AtomicWaker { + static WAKER: AtomicWaker = AtomicWaker::new(); + &WAKER + } + } + impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { unsafe fn start_write(&mut self, _request: Request, buf: *const[W], reg_addr: *mut W, options: TransferOptions) { @@ -153,12 +144,12 @@ foreach_dma_channel! { } fn set_waker(&mut self, waker: &Waker) { - unsafe { low_level_api::set_waker($index, waker) } + Self::waker().register(waker); } fn on_irq() { unsafe { - low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index); + low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, Self::waker()); } } } @@ -248,11 +239,6 @@ mod low_level_api { ch.ndtr().read().ndt() as u16 } - /// Sets the waker for the specified DMA channel - pub unsafe fn set_waker(state_number: usize, waker: &Waker) { - STATE.ch_wakers[state_number].register(waker); - } - pub unsafe fn reset_status(dma: pac::bdma::Dma, channel_number: u8) { dma.ifcr().write(|w| { w.set_tcif(channel_number as _, true); @@ -261,9 +247,8 @@ mod low_level_api { } /// Safety: Must be called with a matching set of parameters for a valid dma channel - pub unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: u8, index: u8) { + pub unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: u8, waker: &'static AtomicWaker) { let channel_num = channel_num as usize; - let index = index as usize; let isr = dma.isr().read(); let cr = dma.ch(channel_num).cr(); @@ -273,7 +258,7 @@ mod low_level_api { } if isr.tcif(channel_num) && cr.read().tcie() { cr.write(|_| ()); // Disable channel interrupts with the default value. - STATE.ch_wakers[index].wake(); + waker.wake(); } } } diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index a45b8780..825c4a5d 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs @@ -4,7 +4,6 @@ use core::task::Waker; use embassy_sync::waitqueue::AtomicWaker; use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize}; -use crate::_generated::DMA_CHANNEL_COUNT; use crate::interrupt::{Interrupt, InterruptExt}; use crate::pac::dma::{regs, vals}; use crate::{interrupt, pac}; @@ -39,33 +38,6 @@ impl From for vals::Pfctrl { } } -struct ChannelState { - waker: AtomicWaker, -} - -impl ChannelState { - const fn new() -> Self { - Self { - waker: AtomicWaker::new(), - } - } -} - -struct State { - channels: [ChannelState; DMA_CHANNEL_COUNT], -} - -impl State { - const fn new() -> Self { - const CH: ChannelState = ChannelState::new(); - Self { - channels: [CH; DMA_CHANNEL_COUNT], - } - } -} - -static STATE: State = State::new(); - /// safety: must be called only once pub(crate) unsafe fn init() { foreach_interrupt! { @@ -78,6 +50,13 @@ pub(crate) unsafe fn init() { foreach_dma_channel! { ($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $index:expr, $dmamux:tt) => { + impl crate::peripherals::$channel_peri { + fn waker() -> &'static AtomicWaker { + static WAKER: AtomicWaker = AtomicWaker::new(); + &WAKER + } + } + impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { unsafe fn start_write(&mut self, request: Request, buf: *const [W], reg_addr: *mut W, options: TransferOptions) { let (ptr, len) = super::slice_ptr_parts(buf); @@ -192,12 +171,12 @@ foreach_dma_channel! { } fn set_waker(&mut self, waker: &Waker) { - unsafe {low_level_api::set_waker($index, waker )} + Self::waker().register(waker); } fn on_irq() { unsafe { - low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index); + low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, Self::waker()); } } } @@ -381,11 +360,6 @@ mod low_level_api { ch.ndtr().read().ndt() } - /// Sets the waker for the specified DMA channel - pub unsafe fn set_waker(state_number: usize, waker: &Waker) { - STATE.channels[state_number].waker.register(waker); - } - pub unsafe fn reset_status(dma: pac::dma::Dma, channel_number: u8) { let isrn = channel_number as usize / 4; let isrbit = channel_number as usize % 4; @@ -397,9 +371,8 @@ mod low_level_api { } /// Safety: Must be called with a matching set of parameters for a valid dma channel - pub unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: u8, state_index: u8) { + pub unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: u8, waker: &'static AtomicWaker) { let channel_num = channel_num as usize; - let state_index = state_index as usize; let cr = dma.st(channel_num).cr(); let isr = dma.isr(channel_num / 4).read(); @@ -415,7 +388,7 @@ mod low_level_api { // for double buffered mode, clear TCIF flag but do not stop the transfer dma.ifcr(channel_num / 4).write(|w| w.set_tcif(channel_num % 4, true)); } - STATE.channels[state_index].waker.wake(); + waker.wake(); } } } diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index bde8c3ef..1103d0d3 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs @@ -4,7 +4,6 @@ use core::task::Waker; use embassy_sync::waitqueue::AtomicWaker; use super::{Request, TransferOptions, Word, WordSize}; -use crate::_generated::GPDMA_CHANNEL_COUNT; use crate::interrupt::{Interrupt, InterruptExt}; use crate::pac::gpdma::{vals, Gpdma}; use crate::{interrupt, pac}; @@ -19,33 +18,6 @@ impl From for vals::ChTr1Dw { } } -struct ChannelState { - waker: AtomicWaker, -} - -impl ChannelState { - const fn new() -> Self { - Self { - waker: AtomicWaker::new(), - } - } -} - -struct State { - channels: [ChannelState; GPDMA_CHANNEL_COUNT], -} - -impl State { - const fn new() -> Self { - const CH: ChannelState = ChannelState::new(); - Self { - channels: [CH; GPDMA_CHANNEL_COUNT], - } - } -} - -static STATE: State = State::new(); - /// safety: must be called only once pub(crate) unsafe fn init() { foreach_interrupt! { @@ -58,6 +30,13 @@ pub(crate) unsafe fn init() { foreach_dma_channel! { ($channel_peri:ident, $dma_peri:ident, gpdma, $channel_num:expr, $index:expr, $dmamux:tt) => { + impl crate::peripherals::$channel_peri { + fn waker() -> &'static AtomicWaker { + static WAKER: AtomicWaker = AtomicWaker::new(); + &WAKER + } + } + impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { unsafe fn start_write(&mut self, request: Request, buf: *const [W], reg_addr: *mut W, options: TransferOptions) { let (ptr, len) = super::slice_ptr_parts(buf); @@ -144,12 +123,12 @@ foreach_dma_channel! { } fn set_waker(&mut self, waker: &Waker) { - unsafe {low_level_api::set_waker($index, waker )} + Self::waker().register(waker); } fn on_irq() { unsafe { - low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index); + low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, Self::waker()); } } } @@ -257,15 +236,9 @@ mod low_level_api { ch.br1().read().bndt() } - /// Sets the waker for the specified DMA channel - pub unsafe fn set_waker(state_number: usize, waker: &Waker) { - STATE.channels[state_number].waker.register(waker); - } - /// Safety: Must be called with a matching set of parameters for a valid dma channel - pub unsafe fn on_irq_inner(dma: Gpdma, channel_num: u8, state_index: u8) { + pub unsafe fn on_irq_inner(dma: Gpdma, channel_num: u8, waker: &'static AtomicWaker) { let channel_num = channel_num as usize; - let state_index = state_index as usize; let ch = dma.ch(channel_num); let sr = ch.sr().read(); @@ -285,7 +258,7 @@ mod low_level_api { if sr.suspf() || sr.tcf() { ch.cr().write(|w| w.set_reset(true)); - STATE.channels[state_index].waker.wake(); + waker.wake(); } } }