diff options
| author | Bob McWhirter <[email protected]> | 2021-07-06 09:54:55 -0400 |
|---|---|---|
| committer | Bob McWhirter <[email protected]> | 2021-07-13 10:08:43 -0400 |
| commit | 6ec725309580b86889cf3d10070a1f18046182a0 (patch) | |
| tree | ff0f1bcc7c5aaa65fdecfe7cbcf4ec06cc050a5b | |
| parent | acdf7f4f1380672a07045226df8fe74dffcb21dd (diff) | |
Checkpoint my DMA for thales.
| -rw-r--r-- | embassy-stm32/src/dmamux/mod.rs | 204 | ||||
| -rw-r--r-- | 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 bbc4bfb1b..b4d5b9831 100644 --- a/embassy-stm32/src/dmamux/mod.rs +++ b/embassy-stm32/src/dmamux/mod.rs | |||
| @@ -6,9 +6,14 @@ use embassy::interrupt::{Interrupt, InterruptExt}; | |||
| 6 | use embassy::util::AtomicWaker; | 6 | use embassy::util::AtomicWaker; |
| 7 | use futures::future::poll_fn; | 7 | use futures::future::poll_fn; |
| 8 | 8 | ||
| 9 | use crate::interrupt; | ||
| 10 | |||
| 11 | use crate::pac::bdma::{regs, vals}; | ||
| 12 | |||
| 9 | use crate::pac; | 13 | use crate::pac; |
| 10 | use crate::pac::dma_channels; | 14 | use crate::pac::dma_channels; |
| 11 | use crate::pac::dma_requests; | 15 | use crate::pac::dma_requests; |
| 16 | use crate::pac::interrupts; | ||
| 12 | use crate::pac::peripheral_count; | 17 | use crate::pac::peripheral_count; |
| 13 | use crate::pac::peripherals; | 18 | use crate::pac::peripherals; |
| 14 | use crate::peripherals; | 19 | use crate::peripherals; |
| @@ -57,19 +62,91 @@ pub(crate) async unsafe fn transfer_m2p( | |||
| 57 | src: &[u8], | 62 | src: &[u8], |
| 58 | dst: *mut u8, | 63 | dst: *mut u8, |
| 59 | ) { | 64 | ) { |
| 65 | defmt::info!( | ||
| 66 | "m2p {} func {} {}-{}", | ||
| 67 | src.len(), | ||
| 68 | ch_func, | ||
| 69 | ch.num(), | ||
| 70 | ch.dma_ch_num() | ||
| 71 | ); | ||
| 72 | let n = ch.num(); | ||
| 73 | |||
| 74 | STATE.ch_status[n].store(CH_STATUS_NONE, Ordering::Release); | ||
| 75 | |||
| 76 | let ch_regs = ch.regs(); | ||
| 60 | let dmamux_regs = ch.dmamux_regs(); | 77 | let dmamux_regs = ch.dmamux_regs(); |
| 61 | let ch_mux_regs = dmamux_regs.ccr(ch.dmamux_ch_num() as _); | 78 | let ch_mux_regs = dmamux_regs.ccr(ch.dmamux_ch_num() as _); |
| 62 | unimplemented!() | 79 | |
| 80 | ch_mux_regs.write(|reg| { | ||
| 81 | // one request? | ||
| 82 | reg.set_nbreq(0); | ||
| 83 | reg.set_dmareq_id(ch_func); | ||
| 84 | }); | ||
| 85 | |||
| 86 | ch_mux_regs.modify(|reg| { | ||
| 87 | reg.set_ege(true); | ||
| 88 | //reg.set_se(true); | ||
| 89 | //reg.set_soie(true); | ||
| 90 | }); | ||
| 91 | |||
| 92 | ch_regs.par().write_value(dst as _); | ||
| 93 | ch_regs.mar().write_value(src.as_ptr() as _); | ||
| 94 | ch_regs.ndtr().write_value(regs::Ndtr(src.len() as _)); | ||
| 95 | |||
| 96 | ch_regs.cr().write(|reg| { | ||
| 97 | reg.set_dir(vals::Dir::FROMMEMORY); | ||
| 98 | reg.set_msize(vals::Size::BITS8); | ||
| 99 | reg.set_minc(vals::Inc::ENABLED); | ||
| 100 | reg.set_pinc(vals::Inc::DISABLED); | ||
| 101 | reg.set_teie(true); | ||
| 102 | reg.set_tcie(true); | ||
| 103 | reg.set_en(true); | ||
| 104 | }); | ||
| 105 | |||
| 106 | let res = poll_fn(|cx| { | ||
| 107 | defmt::info!("poll"); | ||
| 108 | STATE.ch_wakers[n].register(cx.waker()); | ||
| 109 | match STATE.ch_status[n].load(Ordering::Acquire) { | ||
| 110 | CH_STATUS_NONE => Poll::Pending, | ||
| 111 | x => Poll::Ready(x), | ||
| 112 | } | ||
| 113 | }) | ||
| 114 | .await; | ||
| 115 | |||
| 116 | defmt::info!("cr {:b}", ch_regs.cr().read().0); | ||
| 117 | |||
| 118 | ch_regs.cr().modify(|reg| { | ||
| 119 | reg.set_en(false); | ||
| 120 | }); | ||
| 121 | |||
| 122 | ch_mux_regs.modify(|reg| { | ||
| 123 | reg.set_ege(false); | ||
| 124 | //reg.set_se(true); | ||
| 125 | //reg.set_soie(true); | ||
| 126 | }); | ||
| 127 | |||
| 128 | // TODO handle error | ||
| 129 | assert!(res == CH_STATUS_COMPLETED); | ||
| 63 | } | 130 | } |
| 64 | 131 | ||
| 65 | pub(crate) mod sealed { | 132 | pub(crate) mod sealed { |
| 66 | use super::*; | 133 | use super::*; |
| 67 | 134 | ||
| 135 | pub trait Bdma { | ||
| 136 | fn regs() -> &'static pac::bdma::Dma; | ||
| 137 | fn num() -> u8; | ||
| 138 | } | ||
| 139 | |||
| 68 | pub trait DmaMux { | 140 | pub trait DmaMux { |
| 69 | fn regs() -> &'static pac::dmamux::Dmamux; | 141 | fn regs() -> &'static pac::dmamux::Dmamux; |
| 70 | } | 142 | } |
| 71 | 143 | ||
| 72 | pub trait Channel { | 144 | pub trait Channel { |
| 145 | fn num(&self) -> usize; | ||
| 146 | fn regs(&self) -> pac::bdma::Ch; | ||
| 147 | fn dma_regs() -> &'static pac::bdma::Dma; | ||
| 148 | fn dma_ch_num(&self) -> u8; | ||
| 149 | |||
| 73 | fn dmamux_regs(&self) -> &'static pac::dmamux::Dmamux; | 150 | fn dmamux_regs(&self) -> &'static pac::dmamux::Dmamux; |
| 74 | fn dmamux_ch_num(&self) -> u8; | 151 | fn dmamux_ch_num(&self) -> u8; |
| 75 | } | 152 | } |
| @@ -79,6 +156,7 @@ pub(crate) mod sealed { | |||
| 79 | } | 156 | } |
| 80 | } | 157 | } |
| 81 | 158 | ||
| 159 | pub trait Bdma: sealed::Bdma {} | ||
| 82 | pub trait DmaMux: sealed::DmaMux {} | 160 | pub trait DmaMux: sealed::DmaMux {} |
| 83 | pub trait Channel: sealed::Channel {} | 161 | pub trait Channel: sealed::Channel {} |
| 84 | pub trait PeripheralChannel<PERI, OP>: sealed::Channel {} | 162 | pub trait PeripheralChannel<PERI, OP>: sealed::Channel {} |
| @@ -87,9 +165,25 @@ pub struct P2M; | |||
| 87 | pub struct M2P; | 165 | pub struct M2P; |
| 88 | 166 | ||
| 89 | macro_rules! impl_dma_channel { | 167 | macro_rules! impl_dma_channel { |
| 90 | ($channel_peri:ident, $dmamux_peri:ident, $channel_num:expr, $dma_num:expr) => { | 168 | ($channel_peri:ident, $dmamux_peri:ident, $channel_num:expr, $dma_peri: ident, $dma_num:expr) => { |
| 91 | impl Channel for peripherals::$channel_peri {} | 169 | impl Channel for peripherals::$channel_peri {} |
| 92 | impl sealed::Channel for peripherals::$channel_peri { | 170 | impl sealed::Channel for peripherals::$channel_peri { |
| 171 | fn num(&self) -> usize { | ||
| 172 | ($dma_num * 8) + $channel_num | ||
| 173 | } | ||
| 174 | |||
| 175 | fn regs(&self) -> pac::bdma::Ch { | ||
| 176 | Self::dma_regs().ch(self.dma_ch_num() as _) | ||
| 177 | } | ||
| 178 | |||
| 179 | fn dma_regs() -> &'static pac::bdma::Dma { | ||
| 180 | &crate::pac::$dma_peri | ||
| 181 | } | ||
| 182 | |||
| 183 | fn dma_ch_num(&self) -> u8 { | ||
| 184 | $channel_num | ||
| 185 | } | ||
| 186 | |||
| 93 | fn dmamux_regs(&self) -> &'static pac::dmamux::Dmamux { | 187 | fn dmamux_regs(&self) -> &'static pac::dmamux::Dmamux { |
| 94 | &crate::pac::$dmamux_peri | 188 | &crate::pac::$dmamux_peri |
| 95 | } | 189 | } |
| @@ -148,18 +242,36 @@ macro_rules! impl_dmamux { | |||
| 148 | }; | 242 | }; |
| 149 | } | 243 | } |
| 150 | 244 | ||
| 245 | macro_rules! impl_bdma { | ||
| 246 | ($peri:ident, $dma_num:expr) => { | ||
| 247 | impl sealed::Bdma for peripherals::$peri { | ||
| 248 | fn num() -> u8 { | ||
| 249 | $dma_num | ||
| 250 | } | ||
| 251 | |||
| 252 | fn regs() -> &'static pac::bdma::Dma { | ||
| 253 | &pac::$peri | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | impl Bdma for peripherals::$peri {} | ||
| 258 | }; | ||
| 259 | } | ||
| 260 | |||
| 151 | peripherals! { | 261 | peripherals! { |
| 152 | (bdma, DMA1) => { | 262 | (bdma, DMA1) => { |
| 263 | impl_bdma!(DMA1, 0); | ||
| 153 | dma_channels! { | 264 | dma_channels! { |
| 154 | ($channel_peri:ident, DMA1, $channel_num:expr) => { | 265 | ($channel_peri:ident, DMA1, $channel_num:expr) => { |
| 155 | impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, 0); | 266 | impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA1, 0); |
| 156 | }; | 267 | }; |
| 157 | } | 268 | } |
| 158 | }; | 269 | }; |
| 159 | (bdma, DMA2) => { | 270 | (bdma, DMA2) => { |
| 271 | impl_bdma!(DMA2, 1); | ||
| 160 | dma_channels! { | 272 | dma_channels! { |
| 161 | ($channel_peri:ident, DMA2, $channel_num:expr) => { | 273 | ($channel_peri:ident, DMA2, $channel_num:expr) => { |
| 162 | impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, 1); | 274 | impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA2, 1); |
| 163 | }; | 275 | }; |
| 164 | } | 276 | } |
| 165 | }; | 277 | }; |
| @@ -238,3 +350,87 @@ dma_channels! { | |||
| 238 | impl_usart_dma_requests!($channel_peri, $dma_peri, $channel_num); | 350 | impl_usart_dma_requests!($channel_peri, $dma_peri, $channel_num); |
| 239 | }; | 351 | }; |
| 240 | } | 352 | } |
| 353 | |||
| 354 | unsafe fn on_irq() { | ||
| 355 | defmt::info!("irq fire"); | ||
| 356 | peripherals! { | ||
| 357 | //(bdma, $dma:ident) => { | ||
| 358 | (bdma, DMA1) => { | ||
| 359 | defmt::info!("---> dma DMA1"); | ||
| 360 | //for isrn in 0..2 { | ||
| 361 | //let isr = pac::$dma.isr(isrn).read(); | ||
| 362 | let isr = pac::DMA1.isr().read(); | ||
| 363 | pac::DMA1.ifcr().write_value(isr); | ||
| 364 | let dman = <peripherals::DMA1 as sealed::Bdma>::num() as usize; | ||
| 365 | |||
| 366 | for chn in 0..8 { | ||
| 367 | let n = dman * 8 + chn; | ||
| 368 | defmt::info!("n={}", n); | ||
| 369 | if isr.teif(chn) { | ||
| 370 | defmt::info!("transfer error"); | ||
| 371 | STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Release); | ||
| 372 | STATE.ch_wakers[n].wake(); | ||
| 373 | } else if isr.tcif(chn) { | ||
| 374 | defmt::info!("transfer complete"); | ||
| 375 | STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Release); | ||
| 376 | STATE.ch_wakers[n].wake(); | ||
| 377 | } else if isr.htif(chn) { | ||
| 378 | defmt::info!("half transfer"); | ||
| 379 | } else if isr.gif(chn) { | ||
| 380 | defmt::info!("half transfer"); | ||
| 381 | } | ||
| 382 | } | ||
| 383 | //} | ||
| 384 | }; | ||
| 385 | |||
| 386 | (bdma, DMA2) => { | ||
| 387 | defmt::info!("---> dma DMA2"); | ||
| 388 | //for isrn in 0..2 { | ||
| 389 | //let isr = pac::$dma.isr(isrn).read(); | ||
| 390 | let isr = pac::DMA2.isr().read(); | ||
| 391 | pac::DMA2.ifcr().write_value(isr); | ||
| 392 | let dman = <peripherals::DMA2 as sealed::Bdma>::num() as usize; | ||
| 393 | |||
| 394 | for chn in 0..8 { | ||
| 395 | let n = dman * 8 + chn; | ||
| 396 | defmt::info!("n={}", n); | ||
| 397 | if isr.teif(chn) { | ||
| 398 | defmt::info!("transfer error"); | ||
| 399 | STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Release); | ||
| 400 | STATE.ch_wakers[n].wake(); | ||
| 401 | } else if isr.tcif(chn) { | ||
| 402 | defmt::info!("transfer complete"); | ||
| 403 | STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Release); | ||
| 404 | STATE.ch_wakers[n].wake(); | ||
| 405 | } else if isr.htif(chn) { | ||
| 406 | defmt::info!("half transfer"); | ||
| 407 | } else if isr.gif(chn) { | ||
| 408 | defmt::info!("half transfer"); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | //} | ||
| 412 | }; | ||
| 413 | |||
| 414 | } | ||
| 415 | defmt::info!("irq fire complete"); | ||
| 416 | } | ||
| 417 | |||
| 418 | /// safety: must be called only once | ||
| 419 | pub(crate) unsafe fn init() { | ||
| 420 | interrupts! { | ||
| 421 | (DMA, $irq:ident) => { | ||
| 422 | defmt::info!("enable irq {}", stringify!($irq)); | ||
| 423 | interrupt::$irq::steal().enable(); | ||
| 424 | }; | ||
| 425 | } | ||
| 426 | } | ||
| 427 | |||
| 428 | interrupts! { | ||
| 429 | (DMA, $irq:ident) => { | ||
| 430 | #[crate::interrupt] | ||
| 431 | unsafe fn $irq () { | ||
| 432 | defmt::info!("irq firing {}", stringify!($irq)); | ||
| 433 | on_irq() | ||
| 434 | } | ||
| 435 | }; | ||
| 436 | } | ||
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 67962fdde..f750c9899 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -92,8 +92,11 @@ pub fn init(config: Config) -> Peripherals { | |||
| 92 | dma::init(); | 92 | dma::init(); |
| 93 | #[cfg(bdma)] | 93 | #[cfg(bdma)] |
| 94 | bdma::init(); | 94 | bdma::init(); |
| 95 | #[cfg(dmamux)] | ||
| 96 | dmamux::init(); | ||
| 95 | #[cfg(exti)] | 97 | #[cfg(exti)] |
| 96 | exti::init(); | 98 | exti::init(); |
| 99 | |||
| 97 | rcc::init(config.rcc); | 100 | rcc::init(config.rcc); |
| 98 | } | 101 | } |
| 99 | 102 | ||
