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