From 1ed2a0504aba38e4b404c776808ee5229cd72615 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis <dirbaio@dirbaio.net> Date: Mon, 29 Apr 2024 23:56:15 +0200 Subject: [PATCH] stm32/dma: add support for same channel with different req in different DMAs/DMAMUXes. --- embassy-stm32/build.rs | 59 ++++++++++++++++++--------------- embassy-stm32/src/dma/dmamux.rs | 24 -------------- embassy-stm32/src/dma/mod.rs | 2 +- embassy-stm32/src/macros.rs | 27 +-------------- 4 files changed, 35 insertions(+), 77 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index d2b352742..ba3af2550 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1169,42 +1169,52 @@ fn main() { let mut dupe = HashSet::new(); for ch in p.dma_channels { - // Some chips have multiple request numbers for the same (peri, signal, channel) combos. - // Ignore the dupes, picking the first one. Otherwise this causes conflicting trait impls - let key = (ch.signal, ch.channel); - if !dupe.insert(key) { - continue; - } - if let Some(tr) = signals.get(&(regs.kind, ch.signal)) { let peri = format_ident!("{}", p.name); - let channel = if let Some(channel) = &ch.channel { + let channels = if let Some(channel) = &ch.channel { // Chip with DMA/BDMA, without DMAMUX - let channel = format_ident!("{}", channel); - quote!({channel: #channel}) + vec![*channel] } else if let Some(dmamux) = &ch.dmamux { // Chip with DMAMUX - let dmamux = format_ident!("{}", dmamux); - quote!({dmamux: #dmamux}) + METADATA + .dma_channels + .iter() + .filter(|ch| ch.dmamux == Some(*dmamux)) + .map(|ch| ch.name) + .collect() } else if let Some(dma) = &ch.dma { // Chip with GPDMA - let dma = format_ident!("{}", dma); - quote!({dma: #dma}) + METADATA + .dma_channels + .iter() + .filter(|ch| ch.dma == *dma) + .map(|ch| ch.name) + .collect() } else { unreachable!(); }; - let request = if let Some(request) = ch.request { - let request = request as u8; - quote!(#request) - } else { - quote!(()) - }; + for channel in channels { + // Some chips have multiple request numbers for the same (peri, signal, channel) combos. + // Ignore the dupes, picking the first one. Otherwise this causes conflicting trait impls + let key = (ch.signal, channel.to_string()); + if !dupe.insert(key) { + continue; + } - g.extend(quote! { - dma_trait_impl!(#tr, #peri, #channel, #request); - }); + let request = if let Some(request) = ch.request { + let request = request as u8; + quote!(#request) + } else { + quote!(()) + }; + + let channel = format_ident!("{}", channel); + g.extend(quote! { + dma_trait_impl!(#tr, #peri, #channel, #request); + }); + } } } } @@ -1447,9 +1457,6 @@ fn main() { Some(dmamux) => { let dmamux = format_ident!("{}", dmamux); let num = ch.dmamux_channel.unwrap() as usize; - - g.extend(quote!(dmamux_channel_impl!(#name, #dmamux);)); - quote! { dmamux: crate::dma::DmamuxInfo { mux: crate::pac::#dmamux, diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs index dc7cd3a66..1585b30d4 100644 --- a/embassy-stm32/src/dma/dmamux.rs +++ b/embassy-stm32/src/dma/dmamux.rs @@ -19,30 +19,6 @@ pub(crate) fn configure_dmamux(info: &DmamuxInfo, request: u8) { }); } -pub(crate) trait SealedMuxChannel {} - -/// DMAMUX1 instance. -pub struct DMAMUX1; -/// DMAMUX2 instance. -#[cfg(stm32h7)] -pub struct DMAMUX2; - -/// DMAMUX channel trait. -#[allow(private_bounds)] -pub trait MuxChannel: SealedMuxChannel { - /// DMAMUX instance this channel is on. - type Mux; -} - -macro_rules! dmamux_channel_impl { - ($channel_peri:ident, $dmamux:ident) => { - impl crate::dma::SealedMuxChannel for crate::peripherals::$channel_peri {} - impl crate::dma::MuxChannel for crate::peripherals::$channel_peri { - type Mux = crate::dma::$dmamux; - } - }; -} - /// safety: must be called only once pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { crate::_generated::init_dmamux(); diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 8766d0a60..3f5687a62 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -14,7 +14,7 @@ pub use gpdma::*; #[cfg(dmamux)] mod dmamux; #[cfg(dmamux)] -pub use dmamux::*; +pub(crate) use dmamux::*; mod util; pub(crate) use util::*; diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index 14137bc37..02dce1266 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs @@ -36,32 +36,7 @@ macro_rules! dma_trait { #[allow(unused)] macro_rules! dma_trait_impl { - // DMAMUX - (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {dmamux: $dmamux:ident}, $request:expr) => { - impl<T> crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for T - where - T: crate::dma::Channel + crate::dma::MuxChannel<Mux = crate::dma::$dmamux>, - { - fn request(&self) -> crate::dma::Request { - $request - } - } - }; - - // DMAMUX - (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {dma: $dma:ident}, $request:expr) => { - impl<T> crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for T - where - T: crate::dma::Channel, - { - fn request(&self) -> crate::dma::Request { - $request - } - } - }; - - // DMA/GPDMA, without DMAMUX - (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {channel: $channel:ident}, $request:expr) => { + (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $channel:ident, $request:expr) => { impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$channel { fn request(&self) -> crate::dma::Request { $request