From 6ec725309580b86889cf3d10070a1f18046182a0 Mon Sep 17 00:00:00 2001 From: Bob McWhirter Date: Tue, 6 Jul 2021 09:54:55 -0400 Subject: [PATCH] Checkpoint my DMA for thales. --- embassy-stm32/src/dmamux/mod.rs | 204 +++++++++++++++++++++++++++++++- embassy-stm32/src/lib.rs | 3 + 2 files changed, 203 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/dmamux/mod.rs b/embassy-stm32/src/dmamux/mod.rs index bbc4bfb1..b4d5b983 100644 --- a/embassy-stm32/src/dmamux/mod.rs +++ b/embassy-stm32/src/dmamux/mod.rs @@ -6,9 +6,14 @@ use embassy::interrupt::{Interrupt, InterruptExt}; use embassy::util::AtomicWaker; use futures::future::poll_fn; +use crate::interrupt; + +use crate::pac::bdma::{regs, vals}; + use crate::pac; use crate::pac::dma_channels; use crate::pac::dma_requests; +use crate::pac::interrupts; use crate::pac::peripheral_count; use crate::pac::peripherals; use crate::peripherals; @@ -57,19 +62,91 @@ pub(crate) async unsafe fn transfer_m2p( src: &[u8], dst: *mut u8, ) { + defmt::info!( + "m2p {} func {} {}-{}", + src.len(), + ch_func, + ch.num(), + ch.dma_ch_num() + ); + let n = ch.num(); + + STATE.ch_status[n].store(CH_STATUS_NONE, Ordering::Release); + + let ch_regs = ch.regs(); let dmamux_regs = ch.dmamux_regs(); let ch_mux_regs = dmamux_regs.ccr(ch.dmamux_ch_num() as _); - unimplemented!() + + ch_mux_regs.write(|reg| { + // one request? + reg.set_nbreq(0); + reg.set_dmareq_id(ch_func); + }); + + ch_mux_regs.modify(|reg| { + reg.set_ege(true); + //reg.set_se(true); + //reg.set_soie(true); + }); + + ch_regs.par().write_value(dst as _); + ch_regs.mar().write_value(src.as_ptr() as _); + ch_regs.ndtr().write_value(regs::Ndtr(src.len() as _)); + + ch_regs.cr().write(|reg| { + reg.set_dir(vals::Dir::FROMMEMORY); + reg.set_msize(vals::Size::BITS8); + reg.set_minc(vals::Inc::ENABLED); + reg.set_pinc(vals::Inc::DISABLED); + reg.set_teie(true); + reg.set_tcie(true); + reg.set_en(true); + }); + + let res = poll_fn(|cx| { + defmt::info!("poll"); + STATE.ch_wakers[n].register(cx.waker()); + match STATE.ch_status[n].load(Ordering::Acquire) { + CH_STATUS_NONE => Poll::Pending, + x => Poll::Ready(x), + } + }) + .await; + + defmt::info!("cr {:b}", ch_regs.cr().read().0); + + ch_regs.cr().modify(|reg| { + reg.set_en(false); + }); + + ch_mux_regs.modify(|reg| { + reg.set_ege(false); + //reg.set_se(true); + //reg.set_soie(true); + }); + + // TODO handle error + assert!(res == CH_STATUS_COMPLETED); } 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; + fn dmamux_regs(&self) -> &'static pac::dmamux::Dmamux; fn dmamux_ch_num(&self) -> u8; } @@ -79,6 +156,7 @@ pub(crate) mod sealed { } } +pub trait Bdma: sealed::Bdma {} pub trait DmaMux: sealed::DmaMux {} pub trait Channel: sealed::Channel {} pub trait PeripheralChannel: sealed::Channel {} @@ -87,9 +165,25 @@ pub struct P2M; pub struct M2P; macro_rules! impl_dma_channel { - ($channel_peri:ident, $dmamux_peri:ident, $channel_num:expr, $dma_num:expr) => { + ($channel_peri:ident, $dmamux_peri:ident, $channel_num:expr, $dma_peri: ident, $dma_num:expr) => { impl Channel for peripherals::$channel_peri {} impl sealed::Channel for peripherals::$channel_peri { + fn num(&self) -> usize { + ($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 + } + + fn dma_ch_num(&self) -> u8 { + $channel_num + } + fn dmamux_regs(&self) -> &'static pac::dmamux::Dmamux { &crate::pac::$dmamux_peri } @@ -148,18 +242,36 @@ 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, 0); + impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA1, 0); }; } }; (bdma, DMA2) => { + impl_bdma!(DMA2, 1); dma_channels! { ($channel_peri:ident, DMA2, $channel_num:expr) => { - impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, 1); + impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA2, 1); }; } }; @@ -238,3 +350,87 @@ dma_channels! { impl_usart_dma_requests!($channel_peri, $dma_peri, $channel_num); }; } + +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 = ::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 = ::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() + } + }; +} diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 67962fdd..f750c989 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -92,8 +92,11 @@ pub fn init(config: Config) -> Peripherals { dma::init(); #[cfg(bdma)] bdma::init(); + #[cfg(dmamux)] + dmamux::init(); #[cfg(exti)] exti::init(); + rcc::init(config.rcc); }