diff options
author | Bob McWhirter <bmcwhirt@redhat.com> | 2021-07-08 14:55:27 -0400 |
---|---|---|
committer | Bob McWhirter <bmcwhirt@redhat.com> | 2021-07-13 10:09:35 -0400 |
commit | f01ddd5f5c2ec9505037663db8b1d54d7c153b0f (patch) | |
tree | f379fb7dccd2530dca2c0b613358ff3ec042ca3a /embassy-stm32 | |
parent | 6ec725309580b86889cf3d10070a1f18046182a0 (diff) | |
download | embassy-f01ddd5f5c2ec9505037663db8b1d54d7c153b0f.zip |
Mix dmamux into bdma_v1.
Diffstat (limited to 'embassy-stm32')
-rw-r--r-- | embassy-stm32/src/bdma/mod.rs | 22 | ||||
-rw-r--r-- | embassy-stm32/src/bdma/v1.rs | 90 | ||||
-rw-r--r-- | embassy-stm32/src/dma/mod.rs | 23 | ||||
-rw-r--r-- | embassy-stm32/src/dma/v2.rs | 1 | ||||
-rw-r--r-- | embassy-stm32/src/dma_traits.rs | 21 | ||||
-rw-r--r-- | embassy-stm32/src/dmamux/mod.rs | 216 | ||||
-rw-r--r-- | embassy-stm32/src/lib.rs | 5 | ||||
-rw-r--r-- | embassy-stm32/src/usart/mod.rs | 7 |
8 files changed, 138 insertions, 247 deletions
diff --git a/embassy-stm32/src/bdma/mod.rs b/embassy-stm32/src/bdma/mod.rs index 1a49f4e1..ae7e9d23 100644 --- a/embassy-stm32/src/bdma/mod.rs +++ b/embassy-stm32/src/bdma/mod.rs @@ -6,25 +6,3 @@ mod _version; #[allow(unused)] pub use _version::*; - -use core::future::Future; - -pub trait WriteDma<T> { - type WriteDmaFuture<'a>: Future<Output = ()> + 'a - where - Self: 'a; - - fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> - where - T: 'a; -} - -pub trait ReadDma<T> { - type ReadDmaFuture<'a>: Future<Output = ()> + 'a - where - Self: 'a; - - fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a> - where - T: 'a; -} diff --git a/embassy-stm32/src/bdma/v1.rs b/embassy-stm32/src/bdma/v1.rs index f81a0876..fd3bf699 100644 --- a/embassy-stm32/src/bdma/v1.rs +++ b/embassy-stm32/src/bdma/v1.rs @@ -6,10 +6,11 @@ use embassy::interrupt::{Interrupt, InterruptExt}; use embassy::util::{AtomicWaker, OnDrop}; use futures::future::poll_fn; -use super::{ReadDma, WriteDma}; +use crate::dma_traits::{ReadDma, WriteDma}; use crate::interrupt; use crate::pac; use crate::pac::bdma::vals; +use crate::rcc::sealed::RccPeripheral; const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8; const CH_STATUS_NONE: u8 = 0; @@ -57,6 +58,9 @@ pub(crate) async unsafe fn transfer_p2m( while regs.cr().read().en() {} }); + #[cfg(dmamux)] + crate::dmamux::configure_channel(1, 2); + regs.par().write_value(src as u32); regs.mar().write_value(dst.as_mut_ptr() as u32); regs.ndtr().write(|w| w.set_ndt(dst.len() as u16)); @@ -88,6 +92,9 @@ pub(crate) async unsafe fn transfer_m2p( state_number: usize, src: &[u8], dst: *mut u8, + #[cfg(dmamux)] dmamux_regs: &'static pac::dmamux::Dmamux, + #[cfg(dmamux)] dmamux_ch_num: u8, + #[cfg(dmamux)] request: u8, ) { // ndtr is max 16 bits. assert!(src.len() <= 0xFFFF); @@ -105,6 +112,9 @@ pub(crate) async unsafe fn transfer_m2p( while regs.cr().read().en() {} }); + #[cfg(dmamux)] + crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request); + regs.par().write_value(dst as u32); regs.mar().write_value(src.as_ptr() as u32); regs.ndtr().write(|w| w.set_ndt(src.len() as u16)); @@ -161,9 +171,10 @@ pub(crate) unsafe fn init() { } pac::peripherals! { (bdma, DMA1) => { - critical_section::with(|_| { - pac::RCC.ahbenr().modify(|w| w.set_dmaen(true)); - }); + //critical_section::with(|_| { + //pac::RCC.ahbenr().modify(|w| w.set_dmaen(true)); + //}); + crate::peripherals::DMA1::enable(); }; } } @@ -220,8 +231,10 @@ macro_rules! impl_dma_channel { } } + #[cfg(not(dmamux))] impl<T> WriteDma<T> for crate::peripherals::$channel_peri where + Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>, T: 'static, { type WriteDmaFuture<'a> = impl Future<Output = ()>; @@ -234,10 +247,47 @@ macro_rules! impl_dma_channel { let state_num = self.state_num(); let regs = self.regs(); + unsafe { transfer_m2p(regs, state_num, buf, dst) } } } + #[cfg(dmamux)] + impl<T> WriteDma<T> for crate::peripherals::$channel_peri + where + Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>, + T: 'static, + { + type WriteDmaFuture<'a> = impl Future<Output = ()>; + + fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> + where + T: 'a, + { + use sealed::Channel as _Channel; + + let state_num = self.state_num(); + let regs = self.regs(); + + use crate::dmamux::sealed::Channel as _MuxChannel; + use crate::dmamux::sealed::PeripheralChannel; + let dmamux_regs = self.dmamux_regs(); + let dmamux_ch_num = self.dma_ch_num(); + let request = PeripheralChannel::<T, crate::dmamux::M2P>::request(self); + unsafe { + transfer_m2p( + regs, + state_num, + buf, + dst, + dmamux_regs, + dmamux_ch_num, + request, + ) + } + } + } + impl<T> ReadDma<T> for crate::peripherals::$channel_peri where T: 'static, @@ -292,6 +342,8 @@ pac::interrupts! { #[cfg(usart)] use crate::usart; + +#[cfg(not(dmamux))] pac::peripheral_dma_channels! { ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } @@ -302,4 +354,34 @@ pac::peripheral_dma_channels! { impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } }; + + ($peri:ident, uart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { + impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } + impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } + }; + + ($peri:ident, uart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { + impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } + impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } + }; +} + +#[cfg(dmamux)] +pac::peripherals! { + (usart, $peri:ident) => { + pac::dma_channels! { + ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { + impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } + impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } + }; + } + }; + (uart, $peri:ident) => { + pac::dma_channels! { + ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { + impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } + impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } + }; + } + }; } diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 466cfa03..ed080cd1 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -1,6 +1,5 @@ #![macro_use] -#[cfg(dma)] #[cfg_attr(dma_v1, path = "v1.rs")] #[cfg_attr(dma_v2, path = "v2.rs")] mod _version; @@ -8,25 +7,3 @@ mod _version; #[cfg(dma)] #[allow(unused)] pub use _version::*; - -use core::future::Future; - -pub trait WriteDma<T> { - type WriteDmaFuture<'a>: Future<Output = ()> + 'a - where - Self: 'a; - - fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> - where - T: 'a; -} - -pub trait ReadDma<T> { - type ReadDmaFuture<'a>: Future<Output = ()> + 'a - where - Self: 'a; - - fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a> - where - T: 'a; -} diff --git a/embassy-stm32/src/dma/v2.rs b/embassy-stm32/src/dma/v2.rs index e7cd2471..5080776f 100644 --- a/embassy-stm32/src/dma/v2.rs +++ b/embassy-stm32/src/dma/v2.rs @@ -1,5 +1,6 @@ use core::task::Poll; +use crate::dma_traits::{ReadDma, WriteDma}; use atomic_polyfill::{AtomicU8, Ordering}; use embassy::interrupt::{Interrupt, InterruptExt}; use embassy::util::AtomicWaker; diff --git a/embassy-stm32/src/dma_traits.rs b/embassy-stm32/src/dma_traits.rs new file mode 100644 index 00000000..8f1a9f40 --- /dev/null +++ b/embassy-stm32/src/dma_traits.rs @@ -0,0 +1,21 @@ +use core::future::Future; + +pub trait WriteDma<T> { + type WriteDmaFuture<'a>: Future<Output = ()> + 'a + where + Self: 'a; + + fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> + where + T: 'a; +} + +pub trait ReadDma<T> { + type ReadDmaFuture<'a>: Future<Output = ()> + 'a + where + Self: 'a; + + fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a> + where + T: 'a; +} diff --git a/embassy-stm32/src/dmamux/mod.rs b/embassy-stm32/src/dmamux/mod.rs index b4d5b983..745906cd 100644 --- a/embassy-stm32/src/dmamux/mod.rs +++ b/embassy-stm32/src/dmamux/mod.rs @@ -20,41 +20,11 @@ use crate::peripherals; use core::future::Future; -use crate::dma::{ReadDma, WriteDma}; +use crate::dma_traits::{ReadDma, WriteDma}; -const CH_COUNT: usize = peripheral_count!(DMA) * 8; -const CH_STATUS_NONE: u8 = 0; -const CH_STATUS_COMPLETED: u8 = 1; -const CH_STATUS_ERROR: u8 = 2; - -struct State { - ch_wakers: [AtomicWaker; CH_COUNT], - ch_status: [AtomicU8; CH_COUNT], -} - -impl State { - const fn new() -> Self { - const AW: AtomicWaker = AtomicWaker::new(); - const AU: AtomicU8 = AtomicU8::new(CH_STATUS_NONE); - Self { - ch_wakers: [AW; CH_COUNT], - ch_status: [AU; CH_COUNT], - } - } -} - -static STATE: State = State::new(); - -#[allow(unused)] -pub(crate) async unsafe fn transfer_p2m( - ch: &mut impl Channel, - ch_func: u8, - src: *const u8, - dst: &mut [u8], -) { - unimplemented!() -} +pub(crate) fn configure_channel(ch_num: u8, request_num: u8) {} +/* #[allow(unused)] pub(crate) async unsafe fn transfer_m2p( ch: &mut impl Channel, @@ -128,22 +98,36 @@ pub(crate) async unsafe fn transfer_m2p( // TODO handle error assert!(res == CH_STATUS_COMPLETED); } + */ + +pub(crate) unsafe fn configure_dmamux( + dmamux_regs: &pac::dmamux::Dmamux, + dmamux_ch_num: u8, + request: u8, +) { + let ch_mux_regs = dmamux_regs.ccr(dmamux_ch_num as _); + ch_mux_regs.write(|reg| { + // one request? + reg.set_nbreq(0); + reg.set_dmareq_id(request); + }); + + ch_mux_regs.modify(|reg| { + reg.set_ege(true); + //reg.set_se(true); + //reg.set_soie(true); + }); +} pub(crate) mod sealed { use super::*; - pub trait Bdma { - fn regs() -> &'static pac::bdma::Dma; - fn num() -> u8; - } - pub trait DmaMux { fn regs() -> &'static pac::dmamux::Dmamux; } pub trait Channel { fn num(&self) -> usize; - fn regs(&self) -> pac::bdma::Ch; fn dma_regs() -> &'static pac::bdma::Dma; fn dma_ch_num(&self) -> u8; @@ -156,7 +140,6 @@ pub(crate) mod sealed { } } -pub trait Bdma: sealed::Bdma {} pub trait DmaMux: sealed::DmaMux {} pub trait Channel: sealed::Channel {} pub trait PeripheralChannel<PERI, OP>: sealed::Channel {} @@ -172,10 +155,6 @@ macro_rules! impl_dma_channel { ($dma_num * 8) + $channel_num } - fn regs(&self) -> pac::bdma::Ch { - Self::dma_regs().ch(self.dma_ch_num() as _) - } - fn dma_regs() -> &'static pac::bdma::Dma { &crate::pac::$dma_peri } @@ -192,42 +171,6 @@ macro_rules! impl_dma_channel { ($dma_num * 8) + $channel_num } } - - impl<T> WriteDma<T> for peripherals::$channel_peri - where - Self: sealed::PeripheralChannel<T, M2P>, - T: 'static, - { - type WriteDmaFuture<'a> = impl Future<Output = ()>; - - fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> - where - T: 'a, - { - let request = sealed::PeripheralChannel::<T, M2P>::request(self); - unsafe { transfer_m2p(self, request, buf, dst) } - } - } - - impl<T> ReadDma<T> for peripherals::$channel_peri - where - Self: sealed::PeripheralChannel<T, P2M>, - T: 'static, - { - type ReadDmaFuture<'a> = impl Future<Output = ()>; - - fn transfer<'a>( - &'a mut self, - src: *const u8, - buf: &'a mut [u8], - ) -> Self::ReadDmaFuture<'a> - where - T: 'a, - { - let request = sealed::PeripheralChannel::<T, P2M>::request(self); - unsafe { transfer_p2m(self, request, src, buf) } - } - } }; } @@ -242,25 +185,8 @@ macro_rules! impl_dmamux { }; } -macro_rules! impl_bdma { - ($peri:ident, $dma_num:expr) => { - impl sealed::Bdma for peripherals::$peri { - fn num() -> u8 { - $dma_num - } - - fn regs() -> &'static pac::bdma::Dma { - &pac::$peri - } - } - - impl Bdma for peripherals::$peri {} - }; -} - peripherals! { (bdma, DMA1) => { - impl_bdma!(DMA1, 0); dma_channels! { ($channel_peri:ident, DMA1, $channel_num:expr) => { impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA1, 0); @@ -268,7 +194,6 @@ peripherals! { } }; (bdma, DMA2) => { - impl_bdma!(DMA2, 1); dma_channels! { ($channel_peri:ident, DMA2, $channel_num:expr) => { impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA2, 1); @@ -285,9 +210,6 @@ macro_rules! impl_usart_dma_requests { dma_requests! { // TODO: DRY this up. (usart, $peri:ident, RX, $request:expr) => { - impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { } - impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { } - impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri { fn request(&self) -> u8 { $request @@ -299,9 +221,6 @@ macro_rules! impl_usart_dma_requests { }; (usart, $peri:ident, TX, $request:expr) => { - impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { } - impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { } - impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri { fn request(&self) -> u8 { $request @@ -313,9 +232,6 @@ macro_rules! impl_usart_dma_requests { }; (uart, $peri:ident, TX, $request:expr) => { - impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { } - impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { } - impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri { fn request(&self) -> u8 { $request @@ -326,9 +242,6 @@ macro_rules! impl_usart_dma_requests { }; (uart, $peri:ident, RX, $request:expr) => { - impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { } - impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { } - impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri { fn request(&self) -> u8 { $request @@ -351,86 +264,5 @@ dma_channels! { }; } -unsafe fn on_irq() { - defmt::info!("irq fire"); - peripherals! { - //(bdma, $dma:ident) => { - (bdma, DMA1) => { - defmt::info!("---> dma DMA1"); - //for isrn in 0..2 { - //let isr = pac::$dma.isr(isrn).read(); - let isr = pac::DMA1.isr().read(); - pac::DMA1.ifcr().write_value(isr); - let dman = <peripherals::DMA1 as sealed::Bdma>::num() as usize; - - for chn in 0..8 { - let n = dman * 8 + chn; - defmt::info!("n={}", n); - if isr.teif(chn) { - defmt::info!("transfer error"); - STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Release); - STATE.ch_wakers[n].wake(); - } else if isr.tcif(chn) { - defmt::info!("transfer complete"); - STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Release); - STATE.ch_wakers[n].wake(); - } else if isr.htif(chn) { - defmt::info!("half transfer"); - } else if isr.gif(chn) { - defmt::info!("half transfer"); - } - } - //} - }; - - (bdma, DMA2) => { - defmt::info!("---> dma DMA2"); - //for isrn in 0..2 { - //let isr = pac::$dma.isr(isrn).read(); - let isr = pac::DMA2.isr().read(); - pac::DMA2.ifcr().write_value(isr); - let dman = <peripherals::DMA2 as sealed::Bdma>::num() as usize; - - for chn in 0..8 { - let n = dman * 8 + chn; - defmt::info!("n={}", n); - if isr.teif(chn) { - defmt::info!("transfer error"); - STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Release); - STATE.ch_wakers[n].wake(); - } else if isr.tcif(chn) { - defmt::info!("transfer complete"); - STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Release); - STATE.ch_wakers[n].wake(); - } else if isr.htif(chn) { - defmt::info!("half transfer"); - } else if isr.gif(chn) { - defmt::info!("half transfer"); - } - } - //} - }; - - } - defmt::info!("irq fire complete"); -} - /// safety: must be called only once -pub(crate) unsafe fn init() { - interrupts! { - (DMA, $irq:ident) => { - defmt::info!("enable irq {}", stringify!($irq)); - interrupt::$irq::steal().enable(); - }; - } -} - -interrupts! { - (DMA, $irq:ident) => { - #[crate::interrupt] - unsafe fn $irq () { - defmt::info!("irq firing {}", stringify!($irq)); - on_irq() - } - }; -} +pub(crate) unsafe fn init() {} diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index f750c989..4b2826ae 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -20,6 +20,9 @@ pub mod gpio; pub mod rcc; // Sometimes-present hardware +#[cfg(any(dma, bdma, dmamux))] +pub mod dma_traits; + #[cfg(adc)] pub mod adc; #[cfg(bdma)] @@ -28,7 +31,7 @@ pub mod bdma; pub mod clock; #[cfg(dac)] pub mod dac; -#[cfg(any(dma, dmamux))] +#[cfg(dma)] pub mod dma; #[cfg(dmamux)] pub mod dmamux; diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 2bab4016..ddaed5bb 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -73,11 +73,8 @@ pub enum Error { pub(crate) mod sealed { use super::*; - #[cfg(any(dma, dmamux))] - use crate::dma::WriteDma; - - #[cfg(bdma)] - use crate::bdma::WriteDma; + #[cfg(any(dma, bdma, dmamux))] + use crate::dma_traits::WriteDma; pub trait Instance { fn regs(&self) -> crate::pac::usart::Usart; |