From 043f0ea5088e02f509b3e1f013192c44c7854540 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Fri, 2 Jul 2021 09:54:31 -0400 Subject: [PATCH] Checkpoint DMAMUX channel setup. --- embassy-stm32/src/dmamux/mod.rs | 187 ++++++++++++++++++++++++++++++ embassy-stm32/src/lib.rs | 2 + embassy-stm32/src/usart/v3.rs | 2 +- examples/stm32l4/src/bin/usart.rs | 4 - 4 files changed, 190 insertions(+), 5 deletions(-) create mode 100644 embassy-stm32/src/dmamux/mod.rs diff --git a/embassy-stm32/src/dmamux/mod.rs b/embassy-stm32/src/dmamux/mod.rs new file mode 100644 index 00000000..4939d26a --- /dev/null +++ b/embassy-stm32/src/dmamux/mod.rs @@ -0,0 +1,187 @@ +#![macro_use] + +use crate::pac::dma_channels; +use crate::pac::dma_requests; +use crate::pac::peripherals; +use crate::peripherals; + +use core::future::Future; + +use crate::dma::{ReadDma, WriteDma}; + +#[allow(unused)] +pub(crate) async unsafe fn transfer_p2m( + ch: &mut impl Channel, + ch_func: u8, + src: *const u8, + dst: &mut [u8], +) { + unimplemented!() +} + +#[allow(unused)] +pub(crate) async unsafe fn transfer_m2p( + ch: &mut impl Channel, + ch_func: u8, + src: &[u8], + dst: *mut u8, +) { + unimplemented!() +} + +pub(crate) mod sealed { + use super::*; + + pub trait DmaMux {} + + pub trait Channel { + fn dmamux_ch_num(&self) -> u8; + } + + pub trait PeripheralChannel: Channel { + fn request(&self) -> u8; + } +} + +pub trait DmaMux: sealed::DmaMux {} +pub trait Channel: sealed::Channel {} +pub trait PeripheralChannel: sealed::Channel {} + +pub struct P2M; +pub struct M2P; + +macro_rules! impl_dma_channel { + ($channel_peri:ident, $dmamux_peri:ident, $channel_num:expr, $dma_num:expr) => { + impl Channel for peripherals::$channel_peri {} + impl sealed::Channel for peripherals::$channel_peri { + fn dmamux_ch_num(&self) -> u8 { + ($dma_num * 8) + $channel_num + } + } + + impl WriteDma for peripherals::$channel_peri + where + Self: sealed::PeripheralChannel, + T: 'static, + { + type WriteDmaFuture<'a> = impl Future; + + fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> + where + T: 'a, + { + let request = sealed::PeripheralChannel::::request(self); + unsafe { transfer_m2p(self, request, buf, dst) } + } + } + + impl ReadDma for peripherals::$channel_peri + where + Self: sealed::PeripheralChannel, + T: 'static, + { + type ReadDmaFuture<'a> = impl Future; + + fn transfer<'a>( + &'a mut self, + src: *const u8, + buf: &'a mut [u8], + ) -> Self::ReadDmaFuture<'a> + where + T: 'a, + { + let request = sealed::PeripheralChannel::::request(self); + unsafe { transfer_p2m(self, request, src, buf) } + } + } + }; +} + +peripherals! { + (bdma, DMA1) => { + //impl_dma!(DMA1, 0); + dma_channels! { + ($channel_peri:ident, DMA1, $channel_num:expr) => { + impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, 0); + }; + } + }; + (bdma, DMA2) => { + //impl_dma!(DMA2, 1); + dma_channels! { + ($channel_peri:ident, DMA2, $channel_num:expr) => { + impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, 1); + }; + } + }; +} + +macro_rules! impl_usart_dma_requests { + ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { + dma_requests! { + (usart, $peri:ident, RX, $request:expr) => { + impl usart::RxDma for peripherals::$channel_peri { } + impl usart::sealed::RxDma for peripherals::$channel_peri { } + + impl sealed::PeripheralChannel for peripherals::$channel_peri { + fn request(&self) -> u8 { + $request + } + } + + impl PeripheralChannel for peripherals::$channel_peri { } + + }; + + (usart, $peri:ident, TX, $request:expr) => { + impl usart::TxDma for peripherals::$channel_peri { } + impl usart::sealed::TxDma for peripherals::$channel_peri { } + + impl sealed::PeripheralChannel for peripherals::$channel_peri { + fn request(&self) -> u8 { + $request + } + } + + impl PeripheralChannel for peripherals::$channel_peri { } + + }; + + (uart, $peri:ident, TX, $request:expr) => { + impl usart::RxDma for peripherals::$channel_peri { } + impl usart::sealed::RxDma for peripherals::$channel_peri { } + + impl sealed::PeripheralChannel for peripherals::$channel_peri { + fn request(&self) -> u8 { + $request + } + } + + impl PeripheralChannel for peripherals::$channel_peri { } + }; + + (uart, $peri:ident, RX, $request:expr) => { + impl usart::TxDma for peripherals::$channel_peri { } + impl usart::sealed::TxDma for peripherals::$channel_peri { } + + impl sealed::PeripheralChannel for peripherals::$channel_peri { + fn request(&self) -> u8 { + $request + } + } + + impl PeripheralChannel for peripherals::$channel_peri { } + }; + } + + }; +} + +#[cfg(usart)] +use crate::usart; + +dma_channels! { + ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { + impl_usart_dma_requests!($channel_peri, $dma_peri, $channel_num); + }; +} diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 35a8d3ba..67962fdd 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -30,6 +30,8 @@ pub mod clock; pub mod dac; #[cfg(any(dma, dmamux))] pub mod dma; +#[cfg(dmamux)] +pub mod dmamux; #[cfg(all(eth, feature = "net"))] pub mod eth; #[cfg(exti)] diff --git a/embassy-stm32/src/usart/v3.rs b/embassy-stm32/src/usart/v3.rs index 1e905144..0071c597 100644 --- a/embassy-stm32/src/usart/v3.rs +++ b/embassy-stm32/src/usart/v3.rs @@ -57,7 +57,7 @@ impl<'d, T: Instance> Uart<'d, T> { } } - #[cfg(dma)] + #[cfg(any(dma, dmamux))] pub async fn write_dma(&mut self, ch: &mut impl TxDma, buffer: &[u8]) -> Result<(), Error> { unsafe { self.inner.regs().cr3().modify(|reg| { diff --git a/examples/stm32l4/src/bin/usart.rs b/examples/stm32l4/src/bin/usart.rs index 5b6d9eaa..0b14eeb5 100644 --- a/examples/stm32l4/src/bin/usart.rs +++ b/examples/stm32l4/src/bin/usart.rs @@ -82,10 +82,6 @@ fn main() -> ! { w.syscfgen().set_bit(); w }); - //pp.RCC.apb1enr.modify(|_, w| { - //w.usart3en().enabled(); - //w - //}); unsafe { embassy::time::set_clock(&ZeroClock) };