stm32/dma: add support for same channel with different req in different DMAs/DMAMUXes.

This commit is contained in:
Dario Nieuwenhuis 2024-04-29 23:56:15 +02:00
parent 7fb74ff756
commit 1ed2a0504a
4 changed files with 35 additions and 77 deletions

View File

@ -1169,42 +1169,52 @@ fn main() {
let mut dupe = HashSet::new(); let mut dupe = HashSet::new();
for ch in p.dma_channels { 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)) { if let Some(tr) = signals.get(&(regs.kind, ch.signal)) {
let peri = format_ident!("{}", p.name); 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 // Chip with DMA/BDMA, without DMAMUX
let channel = format_ident!("{}", channel); vec![*channel]
quote!({channel: #channel})
} else if let Some(dmamux) = &ch.dmamux { } else if let Some(dmamux) = &ch.dmamux {
// Chip with DMAMUX // Chip with DMAMUX
let dmamux = format_ident!("{}", dmamux); METADATA
quote!({dmamux: #dmamux}) .dma_channels
.iter()
.filter(|ch| ch.dmamux == Some(*dmamux))
.map(|ch| ch.name)
.collect()
} else if let Some(dma) = &ch.dma { } else if let Some(dma) = &ch.dma {
// Chip with GPDMA // Chip with GPDMA
let dma = format_ident!("{}", dma); METADATA
quote!({dma: #dma}) .dma_channels
.iter()
.filter(|ch| ch.dma == *dma)
.map(|ch| ch.name)
.collect()
} else { } else {
unreachable!(); unreachable!();
}; };
let request = if let Some(request) = ch.request { for channel in channels {
let request = request as u8; // Some chips have multiple request numbers for the same (peri, signal, channel) combos.
quote!(#request) // Ignore the dupes, picking the first one. Otherwise this causes conflicting trait impls
} else { let key = (ch.signal, channel.to_string());
quote!(()) if !dupe.insert(key) {
}; continue;
}
g.extend(quote! { let request = if let Some(request) = ch.request {
dma_trait_impl!(#tr, #peri, #channel, #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) => { Some(dmamux) => {
let dmamux = format_ident!("{}", dmamux); let dmamux = format_ident!("{}", dmamux);
let num = ch.dmamux_channel.unwrap() as usize; let num = ch.dmamux_channel.unwrap() as usize;
g.extend(quote!(dmamux_channel_impl!(#name, #dmamux);));
quote! { quote! {
dmamux: crate::dma::DmamuxInfo { dmamux: crate::dma::DmamuxInfo {
mux: crate::pac::#dmamux, mux: crate::pac::#dmamux,

View File

@ -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 /// safety: must be called only once
pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) {
crate::_generated::init_dmamux(); crate::_generated::init_dmamux();

View File

@ -14,7 +14,7 @@ pub use gpdma::*;
#[cfg(dmamux)] #[cfg(dmamux)]
mod dmamux; mod dmamux;
#[cfg(dmamux)] #[cfg(dmamux)]
pub use dmamux::*; pub(crate) use dmamux::*;
mod util; mod util;
pub(crate) use util::*; pub(crate) use util::*;

View File

@ -36,32 +36,7 @@ macro_rules! dma_trait {
#[allow(unused)] #[allow(unused)]
macro_rules! dma_trait_impl { macro_rules! dma_trait_impl {
// DMAMUX (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $channel:ident, $request:expr) => {
(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) => {
impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$channel { impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$channel {
fn request(&self) -> crate::dma::Request { fn request(&self) -> crate::dma::Request {
$request $request