aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob McWhirter <[email protected]>2021-07-06 09:54:55 -0400
committerBob McWhirter <[email protected]>2021-07-13 10:08:43 -0400
commit6ec725309580b86889cf3d10070a1f18046182a0 (patch)
treeff0f1bcc7c5aaa65fdecfe7cbcf4ec06cc050a5b
parentacdf7f4f1380672a07045226df8fe74dffcb21dd (diff)
Checkpoint my DMA for thales.
-rw-r--r--embassy-stm32/src/dmamux/mod.rs204
-rw-r--r--embassy-stm32/src/lib.rs3
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};
6use embassy::util::AtomicWaker; 6use embassy::util::AtomicWaker;
7use futures::future::poll_fn; 7use futures::future::poll_fn;
8 8
9use crate::interrupt;
10
11use crate::pac::bdma::{regs, vals};
12
9use crate::pac; 13use crate::pac;
10use crate::pac::dma_channels; 14use crate::pac::dma_channels;
11use crate::pac::dma_requests; 15use crate::pac::dma_requests;
16use crate::pac::interrupts;
12use crate::pac::peripheral_count; 17use crate::pac::peripheral_count;
13use crate::pac::peripherals; 18use crate::pac::peripherals;
14use crate::peripherals; 19use 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
65pub(crate) mod sealed { 132pub(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
159pub trait Bdma: sealed::Bdma {}
82pub trait DmaMux: sealed::DmaMux {} 160pub trait DmaMux: sealed::DmaMux {}
83pub trait Channel: sealed::Channel {} 161pub trait Channel: sealed::Channel {}
84pub trait PeripheralChannel<PERI, OP>: sealed::Channel {} 162pub trait PeripheralChannel<PERI, OP>: sealed::Channel {}
@@ -87,9 +165,25 @@ pub struct P2M;
87pub struct M2P; 165pub struct M2P;
88 166
89macro_rules! impl_dma_channel { 167macro_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
245macro_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
151peripherals! { 261peripherals! {
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
354unsafe 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
419pub(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
428interrupts! {
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