aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/bdma/mod.rs439
-rw-r--r--embassy-stm32/src/bdma/v1.rs437
-rw-r--r--embassy-stm32/src/bdma/v2.rs1
-rw-r--r--embassy-stm32/src/dmamux/mod.rs80
4 files changed, 436 insertions, 521 deletions
diff --git a/embassy-stm32/src/bdma/mod.rs b/embassy-stm32/src/bdma/mod.rs
index ae7e9d238..523dc2545 100644
--- a/embassy-stm32/src/bdma/mod.rs
+++ b/embassy-stm32/src/bdma/mod.rs
@@ -1,8 +1,439 @@
1#![macro_use] 1#![macro_use]
2 2
3#[cfg_attr(bdma_v1, path = "v1.rs")] 3use core::future::Future;
4#[cfg_attr(bdma_v2, path = "v2.rs")] 4use core::task::Poll;
5mod _version; 5
6use atomic_polyfill::{AtomicU8, Ordering};
7use embassy::interrupt::{Interrupt, InterruptExt};
8use embassy::util::{AtomicWaker, OnDrop};
9use futures::future::poll_fn;
10
11use crate::dma_traits::{ReadDma, WriteDma};
12use crate::interrupt;
13use crate::pac;
14use crate::pac::bdma::vals;
15
16const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8;
17const CH_STATUS_NONE: u8 = 0;
18const CH_STATUS_COMPLETED: u8 = 1;
19const CH_STATUS_ERROR: u8 = 2;
20
21struct State {
22 ch_wakers: [AtomicWaker; CH_COUNT],
23 ch_status: [AtomicU8; CH_COUNT],
24}
25
26impl State {
27 const fn new() -> Self {
28 const AW: AtomicWaker = AtomicWaker::new();
29 const AU: AtomicU8 = AtomicU8::new(CH_STATUS_NONE);
30 Self {
31 ch_wakers: [AW; CH_COUNT],
32 ch_status: [AU; CH_COUNT],
33 }
34 }
35}
36
37static STATE: State = State::new();
6 38
7#[allow(unused)] 39#[allow(unused)]
8pub use _version::*; 40pub(crate) async unsafe fn transfer_p2m(
41 regs: pac::bdma::Ch,
42 state_number: usize,
43 src: *const u8,
44 dst: &mut [u8],
45 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
46 #[cfg(dmamux)] dmamux_ch_num: u8,
47 #[cfg(dmamux)] request: u8,
48) {
49 // ndtr is max 16 bits.
50 assert!(dst.len() <= 0xFFFF);
51
52 // Reset status
53 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA
54 STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release);
55
56 let on_drop = OnDrop::new(|| unsafe {
57 regs.cr().modify(|w| {
58 w.set_tcie(false);
59 w.set_teie(false);
60 w.set_en(false);
61 });
62 while regs.cr().read().en() {}
63 });
64
65 #[cfg(dmamux)]
66 crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
67
68 regs.par().write_value(src as u32);
69 regs.mar().write_value(dst.as_mut_ptr() as u32);
70 regs.ndtr().write(|w| w.set_ndt(dst.len() as u16));
71 regs.cr().write(|w| {
72 w.set_psize(vals::Size::BITS8);
73 w.set_msize(vals::Size::BITS8);
74 w.set_minc(vals::Inc::ENABLED);
75 w.set_teie(true);
76 w.set_tcie(true);
77 w.set_en(true);
78 });
79
80 let res = poll_fn(|cx| {
81 STATE.ch_wakers[state_number].register(cx.waker());
82 match STATE.ch_status[state_number].load(Ordering::Acquire) {
83 CH_STATUS_NONE => Poll::Pending,
84 x => Poll::Ready(x),
85 }
86 })
87 .await;
88
89 // TODO handle error
90 assert!(res == CH_STATUS_COMPLETED);
91}
92
93#[allow(unused)]
94pub(crate) async unsafe fn transfer_m2p(
95 regs: pac::bdma::Ch,
96 state_number: usize,
97 src: &[u8],
98 dst: *mut u8,
99 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
100 #[cfg(dmamux)] dmamux_ch_num: u8,
101 #[cfg(dmamux)] request: u8,
102) {
103 // ndtr is max 16 bits.
104 assert!(src.len() <= 0xFFFF);
105
106 // Reset status
107 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA
108 STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release);
109
110 let on_drop = OnDrop::new(|| unsafe {
111 regs.cr().modify(|w| {
112 w.set_tcie(false);
113 w.set_teie(false);
114 w.set_en(false);
115 });
116 while regs.cr().read().en() {}
117 });
118
119 #[cfg(dmamux)]
120 crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
121
122 regs.par().write_value(dst as u32);
123 regs.mar().write_value(src.as_ptr() as u32);
124 regs.ndtr().write(|w| w.set_ndt(src.len() as u16));
125 regs.cr().write(|w| {
126 w.set_psize(vals::Size::BITS8);
127 w.set_msize(vals::Size::BITS8);
128 w.set_minc(vals::Inc::ENABLED);
129 w.set_dir(vals::Dir::FROMMEMORY);
130 w.set_teie(true);
131 w.set_tcie(true);
132 w.set_en(true);
133 });
134
135 let res = poll_fn(|cx| {
136 STATE.ch_wakers[state_number].register(cx.waker());
137 match STATE.ch_status[state_number].load(Ordering::Acquire) {
138 CH_STATUS_NONE => Poll::Pending,
139 x => Poll::Ready(x),
140 }
141 })
142 .await;
143
144 // TODO handle error
145 assert!(res == CH_STATUS_COMPLETED);
146}
147
148unsafe fn on_irq() {
149 pac::peripherals! {
150 (bdma, $dma:ident) => {
151 let isr = pac::$dma.isr().read();
152 pac::$dma.ifcr().write_value(isr);
153 let dman = <crate::peripherals::$dma as sealed::Dma>::num() as usize;
154
155 for chn in 0..7 {
156 let n = dman * 8 + chn;
157 if isr.teif(chn) {
158 STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed);
159 STATE.ch_wakers[n].wake();
160 } else if isr.tcif(chn) {
161 STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed);
162 STATE.ch_wakers[n].wake();
163 }
164 }
165 };
166 }
167}
168
169use crate::rcc::sealed::RccPeripheral;
170
171/// safety: must be called only once
172pub(crate) unsafe fn init() {
173 pac::interrupts! {
174 (DMA, $irq:ident) => {
175 crate::interrupt::$irq::steal().enable();
176 };
177 }
178 pac::peripherals! {
179 (bdma, $peri:ident) => {
180 crate::peripherals::$peri::enable();
181 };
182 }
183}
184
185pub(crate) mod sealed {
186 use super::*;
187
188 pub trait Dma {
189 fn num() -> u8;
190 }
191
192 pub trait Channel {
193 fn dma_regs() -> pac::bdma::Dma;
194
195 fn state_num(&self) -> usize;
196
197 fn ch_num(&self) -> u8;
198
199 fn regs(&self) -> pac::bdma::Ch {
200 Self::dma_regs().ch(self.ch_num() as usize)
201 }
202 }
203}
204
205pub trait Dma: sealed::Dma + Sized {}
206pub trait Channel: sealed::Channel + Sized {}
207
208macro_rules! impl_dma {
209 ($peri:ident, $num:expr) => {
210 impl Dma for crate::peripherals::$peri {}
211 impl sealed::Dma for crate::peripherals::$peri {
212 fn num() -> u8 {
213 $num
214 }
215 }
216 };
217}
218
219macro_rules! impl_dma_channel {
220 ($channel_peri:ident, $dma_peri:ident, $dma_num:expr, $ch_num:expr) => {
221 impl Channel for crate::peripherals::$channel_peri {}
222 impl sealed::Channel for crate::peripherals::$channel_peri {
223 #[inline]
224 fn dma_regs() -> pac::bdma::Dma {
225 crate::pac::$dma_peri
226 }
227
228 fn state_num(&self) -> usize {
229 ($dma_num * 8) + $ch_num
230 }
231
232 fn ch_num(&self) -> u8 {
233 $ch_num
234 }
235 }
236
237 #[cfg(not(dmamux))]
238 impl<T> WriteDma<T> for crate::peripherals::$channel_peri
239 where
240 T: 'static,
241 {
242 type WriteDmaFuture<'a> = impl Future<Output = ()>;
243
244 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
245 where
246 T: 'a,
247 {
248 use sealed::Channel as _Channel;
249
250 let state_num = self.state_num();
251 let regs = self.regs();
252
253 unsafe { transfer_m2p(regs, state_num, buf, dst) }
254 }
255 }
256
257 #[cfg(dmamux)]
258 impl<T> WriteDma<T> for crate::peripherals::$channel_peri
259 where
260 Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>,
261 T: 'static,
262 {
263 type WriteDmaFuture<'a> = impl Future<Output = ()>;
264
265 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
266 where
267 T: 'a,
268 {
269 use sealed::Channel as _Channel;
270
271 let state_num = self.state_num();
272 let regs = self.regs();
273
274 use crate::dmamux::sealed::Channel as _MuxChannel;
275 use crate::dmamux::sealed::PeripheralChannel;
276 let dmamux_regs = self.dmamux_regs();
277 let dmamux_ch_num = self.dmamux_ch_num();
278 let request = PeripheralChannel::<T, crate::dmamux::M2P>::request(self);
279 unsafe {
280 transfer_m2p(
281 regs,
282 state_num,
283 buf,
284 dst,
285 dmamux_regs,
286 dmamux_ch_num,
287 request,
288 )
289 }
290 }
291 }
292
293 #[cfg(not(dmamux))]
294 impl<T> ReadDma<T> for crate::peripherals::$channel_peri
295 where
296 T: 'static,
297 {
298 type ReadDmaFuture<'a> = impl Future<Output = ()>;
299
300 fn transfer<'a>(
301 &'a mut self,
302 src: *const u8,
303 buf: &'a mut [u8],
304 ) -> Self::ReadDmaFuture<'a>
305 where
306 T: 'a,
307 {
308 use sealed::Channel as _Channel;
309
310 let state_num = self.state_num();
311 let regs = self.regs();
312 unsafe { transfer_p2m(regs, state_num, src, buf) }
313 }
314 }
315
316 #[cfg(dmamux)]
317 impl<T> ReadDma<T> for crate::peripherals::$channel_peri
318 where
319 Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>,
320 T: 'static,
321 {
322 type ReadDmaFuture<'a> = impl Future<Output = ()>;
323
324 fn transfer<'a>(
325 &'a mut self,
326 src: *const u8,
327 buf: &'a mut [u8],
328 ) -> Self::ReadDmaFuture<'a>
329 where
330 T: 'a,
331 {
332 use sealed::Channel as _Channel;
333
334 let state_num = self.state_num();
335 let regs = self.regs();
336
337 use crate::dmamux::sealed::Channel as _MuxChannel;
338 use crate::dmamux::sealed::PeripheralChannel;
339 let dmamux_regs = self.dmamux_regs();
340 let dmamux_ch_num = self.dmamux_ch_num();
341 let request = PeripheralChannel::<T, crate::dmamux::M2P>::request(self);
342 unsafe {
343 transfer_p2m(
344 regs,
345 state_num,
346 src,
347 buf,
348 dmamux_regs,
349 dmamux_ch_num,
350 request,
351 )
352 }
353 }
354 }
355 };
356}
357
358pac::peripherals! {
359 (bdma, DMA1) => {
360 impl_dma!(DMA1, 0);
361 pac::bdma_channels! {
362 ($channel_peri:ident, DMA1, $channel_num:expr) => {
363 impl_dma_channel!($channel_peri, DMA1, 0, $channel_num);
364 };
365 }
366 };
367 (bdma, DMA2) => {
368 impl_dma!(DMA2, 1);
369 pac::bdma_channels! {
370 ($channel_peri:ident, DMA2, $channel_num:expr) => {
371 impl_dma_channel!($channel_peri, DMA2, 1, $channel_num);
372 };
373 }
374 };
375 // Because H7cm changes the naming
376 (bdma, BDMA) => {
377 impl_dma!(BDMA, 0);
378 pac::bdma_channels! {
379 ($channel_peri:ident, BDMA, $channel_num:expr) => {
380 impl_dma_channel!($channel_peri, BDMA, 0, $channel_num);
381 };
382 }
383 };
384}
385
386pac::interrupts! {
387 (DMA, $irq:ident) => {
388 #[crate::interrupt]
389 unsafe fn $irq () {
390 on_irq()
391 }
392 };
393}
394
395#[cfg(usart)]
396use crate::usart;
397
398#[cfg(not(dmamux))]
399pac::peripheral_dma_channels! {
400 ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
401 impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
402 impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
403 };
404
405 ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
406 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
407 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
408 };
409
410 ($peri:ident, uart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
411 impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
412 impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
413 };
414
415 ($peri:ident, uart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
416 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
417 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
418 };
419}
420
421#[cfg(dmamux)]
422pac::peripherals! {
423 (usart, $peri:ident) => {
424 pac::bdma_channels! {
425 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
426 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
427 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
428 };
429 }
430 };
431 (uart, $peri:ident) => {
432 pac::bdma_channels! {
433 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
434 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
435 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
436 };
437 }
438 };
439}
diff --git a/embassy-stm32/src/bdma/v1.rs b/embassy-stm32/src/bdma/v1.rs
deleted file mode 100644
index e5b0b18b1..000000000
--- a/embassy-stm32/src/bdma/v1.rs
+++ /dev/null
@@ -1,437 +0,0 @@
1use core::future::Future;
2use core::task::Poll;
3
4use atomic_polyfill::{AtomicU8, Ordering};
5use embassy::interrupt::{Interrupt, InterruptExt};
6use embassy::util::{AtomicWaker, OnDrop};
7use futures::future::poll_fn;
8
9use crate::dma_traits::{ReadDma, WriteDma};
10use crate::interrupt;
11use crate::pac;
12use crate::pac::bdma::vals;
13
14const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8;
15const CH_STATUS_NONE: u8 = 0;
16const CH_STATUS_COMPLETED: u8 = 1;
17const CH_STATUS_ERROR: u8 = 2;
18
19struct State {
20 ch_wakers: [AtomicWaker; CH_COUNT],
21 ch_status: [AtomicU8; CH_COUNT],
22}
23
24impl State {
25 const fn new() -> Self {
26 const AW: AtomicWaker = AtomicWaker::new();
27 const AU: AtomicU8 = AtomicU8::new(CH_STATUS_NONE);
28 Self {
29 ch_wakers: [AW; CH_COUNT],
30 ch_status: [AU; CH_COUNT],
31 }
32 }
33}
34
35static STATE: State = State::new();
36
37#[allow(unused)]
38pub(crate) async unsafe fn transfer_p2m(
39 regs: pac::bdma::Ch,
40 state_number: usize,
41 src: *const u8,
42 dst: &mut [u8],
43 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
44 #[cfg(dmamux)] dmamux_ch_num: u8,
45 #[cfg(dmamux)] request: u8,
46) {
47 // ndtr is max 16 bits.
48 assert!(dst.len() <= 0xFFFF);
49
50 // Reset status
51 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA
52 STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release);
53
54 let on_drop = OnDrop::new(|| unsafe {
55 regs.cr().modify(|w| {
56 w.set_tcie(false);
57 w.set_teie(false);
58 w.set_en(false);
59 });
60 while regs.cr().read().en() {}
61 });
62
63 #[cfg(dmamux)]
64 crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
65
66 regs.par().write_value(src as u32);
67 regs.mar().write_value(dst.as_mut_ptr() as u32);
68 regs.ndtr().write(|w| w.set_ndt(dst.len() as u16));
69 regs.cr().write(|w| {
70 w.set_psize(vals::Size::BITS8);
71 w.set_msize(vals::Size::BITS8);
72 w.set_minc(vals::Inc::ENABLED);
73 w.set_teie(true);
74 w.set_tcie(true);
75 w.set_en(true);
76 });
77
78 let res = poll_fn(|cx| {
79 STATE.ch_wakers[state_number].register(cx.waker());
80 match STATE.ch_status[state_number].load(Ordering::Acquire) {
81 CH_STATUS_NONE => Poll::Pending,
82 x => Poll::Ready(x),
83 }
84 })
85 .await;
86
87 // TODO handle error
88 assert!(res == CH_STATUS_COMPLETED);
89}
90
91#[allow(unused)]
92pub(crate) async unsafe fn transfer_m2p(
93 regs: pac::bdma::Ch,
94 state_number: usize,
95 src: &[u8],
96 dst: *mut u8,
97 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
98 #[cfg(dmamux)] dmamux_ch_num: u8,
99 #[cfg(dmamux)] request: u8,
100) {
101 // ndtr is max 16 bits.
102 assert!(src.len() <= 0xFFFF);
103
104 // Reset status
105 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA
106 STATE.ch_status[state_number].store(CH_STATUS_NONE, Ordering::Release);
107
108 let on_drop = OnDrop::new(|| unsafe {
109 regs.cr().modify(|w| {
110 w.set_tcie(false);
111 w.set_teie(false);
112 w.set_en(false);
113 });
114 while regs.cr().read().en() {}
115 });
116
117 #[cfg(dmamux)]
118 crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
119
120 regs.par().write_value(dst as u32);
121 regs.mar().write_value(src.as_ptr() as u32);
122 regs.ndtr().write(|w| w.set_ndt(src.len() as u16));
123 regs.cr().write(|w| {
124 w.set_psize(vals::Size::BITS8);
125 w.set_msize(vals::Size::BITS8);
126 w.set_minc(vals::Inc::ENABLED);
127 w.set_dir(vals::Dir::FROMMEMORY);
128 w.set_teie(true);
129 w.set_tcie(true);
130 w.set_en(true);
131 });
132
133 let res = poll_fn(|cx| {
134 STATE.ch_wakers[state_number].register(cx.waker());
135 match STATE.ch_status[state_number].load(Ordering::Acquire) {
136 CH_STATUS_NONE => Poll::Pending,
137 x => Poll::Ready(x),
138 }
139 })
140 .await;
141
142 // TODO handle error
143 assert!(res == CH_STATUS_COMPLETED);
144}
145
146unsafe fn on_irq() {
147 pac::peripherals! {
148 (bdma, $dma:ident) => {
149 let isr = pac::$dma.isr().read();
150 pac::$dma.ifcr().write_value(isr);
151 let dman = <crate::peripherals::$dma as sealed::Dma>::num() as usize;
152
153 for chn in 0..7 {
154 let n = dman * 8 + chn;
155 if isr.teif(chn) {
156 STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed);
157 STATE.ch_wakers[n].wake();
158 } else if isr.tcif(chn) {
159 STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed);
160 STATE.ch_wakers[n].wake();
161 }
162 }
163 };
164 }
165}
166
167use crate::rcc::sealed::RccPeripheral;
168
169/// safety: must be called only once
170pub(crate) unsafe fn init() {
171 pac::interrupts! {
172 (DMA, $irq:ident) => {
173 crate::interrupt::$irq::steal().enable();
174 };
175 }
176 pac::peripherals! {
177 (bdma, $peri:ident) => {
178 crate::peripherals::$peri::enable();
179 };
180 }
181}
182
183pub(crate) mod sealed {
184 use super::*;
185
186 pub trait Dma {
187 fn num() -> u8;
188 }
189
190 pub trait Channel {
191 fn dma_regs() -> pac::bdma::Dma;
192
193 fn state_num(&self) -> usize;
194
195 fn ch_num(&self) -> u8;
196
197 fn regs(&self) -> pac::bdma::Ch {
198 Self::dma_regs().ch(self.ch_num() as usize)
199 }
200 }
201}
202
203pub trait Dma: sealed::Dma + Sized {}
204pub trait Channel: sealed::Channel + Sized {}
205
206macro_rules! impl_dma {
207 ($peri:ident, $num:expr) => {
208 impl Dma for crate::peripherals::$peri {}
209 impl sealed::Dma for crate::peripherals::$peri {
210 fn num() -> u8 {
211 $num
212 }
213 }
214 };
215}
216
217macro_rules! impl_dma_channel {
218 ($channel_peri:ident, $dma_peri:ident, $dma_num:expr, $ch_num:expr) => {
219 impl Channel for crate::peripherals::$channel_peri {}
220 impl sealed::Channel for crate::peripherals::$channel_peri {
221 #[inline]
222 fn dma_regs() -> pac::bdma::Dma {
223 crate::pac::$dma_peri
224 }
225
226 fn state_num(&self) -> usize {
227 ($dma_num * 8) + $ch_num
228 }
229
230 fn ch_num(&self) -> u8 {
231 $ch_num
232 }
233 }
234
235 #[cfg(not(dmamux))]
236 impl<T> WriteDma<T> for crate::peripherals::$channel_peri
237 where
238 T: 'static,
239 {
240 type WriteDmaFuture<'a> = impl Future<Output = ()>;
241
242 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
243 where
244 T: 'a,
245 {
246 use sealed::Channel as _Channel;
247
248 let state_num = self.state_num();
249 let regs = self.regs();
250
251 unsafe { transfer_m2p(regs, state_num, buf, dst) }
252 }
253 }
254
255 #[cfg(dmamux)]
256 impl<T> WriteDma<T> for crate::peripherals::$channel_peri
257 where
258 Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>,
259 T: 'static,
260 {
261 type WriteDmaFuture<'a> = impl Future<Output = ()>;
262
263 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
264 where
265 T: 'a,
266 {
267 use sealed::Channel as _Channel;
268
269 let state_num = self.state_num();
270 let regs = self.regs();
271
272 use crate::dmamux::sealed::Channel as _MuxChannel;
273 use crate::dmamux::sealed::PeripheralChannel;
274 let dmamux_regs = self.dmamux_regs();
275 let dmamux_ch_num = self.dmamux_ch_num();
276 let request = PeripheralChannel::<T, crate::dmamux::M2P>::request(self);
277 unsafe {
278 transfer_m2p(
279 regs,
280 state_num,
281 buf,
282 dst,
283 dmamux_regs,
284 dmamux_ch_num,
285 request,
286 )
287 }
288 }
289 }
290
291 #[cfg(not(dmamux))]
292 impl<T> ReadDma<T> for crate::peripherals::$channel_peri
293 where
294 T: 'static,
295 {
296 type ReadDmaFuture<'a> = impl Future<Output = ()>;
297
298 fn transfer<'a>(
299 &'a mut self,
300 src: *const u8,
301 buf: &'a mut [u8],
302 ) -> Self::ReadDmaFuture<'a>
303 where
304 T: 'a,
305 {
306 use sealed::Channel as _Channel;
307
308 let state_num = self.state_num();
309 let regs = self.regs();
310 unsafe { transfer_p2m(regs, state_num, src, buf) }
311 }
312 }
313
314 #[cfg(dmamux)]
315 impl<T> ReadDma<T> for crate::peripherals::$channel_peri
316 where
317 Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>,
318 T: 'static,
319 {
320 type ReadDmaFuture<'a> = impl Future<Output = ()>;
321
322 fn transfer<'a>(
323 &'a mut self,
324 src: *const u8,
325 buf: &'a mut [u8],
326 ) -> Self::ReadDmaFuture<'a>
327 where
328 T: 'a,
329 {
330 use sealed::Channel as _Channel;
331
332 let state_num = self.state_num();
333 let regs = self.regs();
334
335 use crate::dmamux::sealed::Channel as _MuxChannel;
336 use crate::dmamux::sealed::PeripheralChannel;
337 let dmamux_regs = self.dmamux_regs();
338 let dmamux_ch_num = self.dmamux_ch_num();
339 let request = PeripheralChannel::<T, crate::dmamux::M2P>::request(self);
340 unsafe {
341 transfer_p2m(
342 regs,
343 state_num,
344 src,
345 buf,
346 dmamux_regs,
347 dmamux_ch_num,
348 request,
349 )
350 }
351 }
352 }
353 };
354}
355
356pac::peripherals! {
357 (bdma, DMA1) => {
358 impl_dma!(DMA1, 0);
359 pac::bdma_channels! {
360 ($channel_peri:ident, DMA1, $channel_num:expr) => {
361 impl_dma_channel!($channel_peri, DMA1, 0, $channel_num);
362 };
363 }
364 };
365 (bdma, DMA2) => {
366 impl_dma!(DMA2, 1);
367 pac::bdma_channels! {
368 ($channel_peri:ident, DMA2, $channel_num:expr) => {
369 impl_dma_channel!($channel_peri, DMA2, 1, $channel_num);
370 };
371 }
372 };
373 // Because H7cm changes the naming
374 (bdma, BDMA) => {
375 impl_dma!(BDMA, 0);
376 pac::bdma_channels! {
377 ($channel_peri:ident, BDMA, $channel_num:expr) => {
378 impl_dma_channel!($channel_peri, BDMA, 0, $channel_num);
379 };
380 }
381 };
382}
383
384pac::interrupts! {
385 (DMA, $irq:ident) => {
386 #[crate::interrupt]
387 unsafe fn $irq () {
388 on_irq()
389 }
390 };
391}
392
393#[cfg(usart)]
394use crate::usart;
395
396#[cfg(not(dmamux))]
397pac::peripheral_dma_channels! {
398 ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
399 impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
400 impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
401 };
402
403 ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
404 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
405 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
406 };
407
408 ($peri:ident, uart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
409 impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
410 impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
411 };
412
413 ($peri:ident, uart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
414 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
415 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
416 };
417}
418
419#[cfg(dmamux)]
420pac::peripherals! {
421 (usart, $peri:ident) => {
422 pac::bdma_channels! {
423 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
424 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
425 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
426 };
427 }
428 };
429 (uart, $peri:ident) => {
430 pac::bdma_channels! {
431 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
432 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
433 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
434 };
435 }
436 };
437}
diff --git a/embassy-stm32/src/bdma/v2.rs b/embassy-stm32/src/bdma/v2.rs
deleted file mode 100644
index 956b83cd1..000000000
--- a/embassy-stm32/src/bdma/v2.rs
+++ /dev/null
@@ -1 +0,0 @@
1pub(crate) unsafe fn init() {}
diff --git a/embassy-stm32/src/dmamux/mod.rs b/embassy-stm32/src/dmamux/mod.rs
index ebb1748db..0f3fb9a8f 100644
--- a/embassy-stm32/src/dmamux/mod.rs
+++ b/embassy-stm32/src/dmamux/mod.rs
@@ -6,82 +6,6 @@ use crate::pac::dma_requests;
6use crate::pac::peripherals; 6use crate::pac::peripherals;
7use crate::peripherals; 7use crate::peripherals;
8 8
9/*
10#[allow(unused)]
11pub(crate) async unsafe fn transfer_m2p(
12 ch: &mut impl Channel,
13 ch_func: u8,
14 src: &[u8],
15 dst: *mut u8,
16) {
17 defmt::info!(
18 "m2p {} func {} {}-{}",
19 src.len(),
20 ch_func,
21 ch.num(),
22 ch.dma_ch_num()
23 );
24 let n = ch.num();
25
26 STATE.ch_status[n].store(CH_STATUS_NONE, Ordering::Release);
27
28 let ch_regs = ch.regs();
29 let dmamux_regs = ch.dmamux_regs();
30 let ch_mux_regs = dmamux_regs.ccr(ch.dmamux_ch_num() as _);
31
32 ch_mux_regs.write(|reg| {
33 // one request?
34 reg.set_nbreq(0);
35 reg.set_dmareq_id(ch_func);
36 });
37
38 ch_mux_regs.modify(|reg| {
39 reg.set_ege(true);
40 //reg.set_se(true);
41 //reg.set_soie(true);
42 });
43
44 ch_regs.par().write_value(dst as _);
45 ch_regs.mar().write_value(src.as_ptr() as _);
46 ch_regs.ndtr().write_value(regs::Ndtr(src.len() as _));
47
48 ch_regs.cr().write(|reg| {
49 reg.set_dir(vals::Dir::FROMMEMORY);
50 reg.set_msize(vals::Size::BITS8);
51 reg.set_minc(vals::Inc::ENABLED);
52 reg.set_pinc(vals::Inc::DISABLED);
53 reg.set_teie(true);
54 reg.set_tcie(true);
55 reg.set_en(true);
56 });
57
58 let res = poll_fn(|cx| {
59 defmt::info!("poll");
60 STATE.ch_wakers[n].register(cx.waker());
61 match STATE.ch_status[n].load(Ordering::Acquire) {
62 CH_STATUS_NONE => Poll::Pending,
63 x => Poll::Ready(x),
64 }
65 })
66 .await;
67
68 defmt::info!("cr {:b}", ch_regs.cr().read().0);
69
70 ch_regs.cr().modify(|reg| {
71 reg.set_en(false);
72 });
73
74 ch_mux_regs.modify(|reg| {
75 reg.set_ege(false);
76 //reg.set_se(true);
77 //reg.set_soie(true);
78 });
79
80 // TODO handle error
81 assert!(res == CH_STATUS_COMPLETED);
82}
83 */
84
85pub(crate) unsafe fn configure_dmamux( 9pub(crate) unsafe fn configure_dmamux(
86 dmamux_regs: pac::dmamux::Dmamux, 10 dmamux_regs: pac::dmamux::Dmamux,
87 dmamux_ch_num: u8, 11 dmamux_ch_num: u8,
@@ -89,15 +13,12 @@ pub(crate) unsafe fn configure_dmamux(
89) { 13) {
90 let ch_mux_regs = dmamux_regs.ccr(dmamux_ch_num as _); 14 let ch_mux_regs = dmamux_regs.ccr(dmamux_ch_num as _);
91 ch_mux_regs.write(|reg| { 15 ch_mux_regs.write(|reg| {
92 // one request?
93 reg.set_nbreq(0); 16 reg.set_nbreq(0);
94 reg.set_dmareq_id(request); 17 reg.set_dmareq_id(request);
95 }); 18 });
96 19
97 ch_mux_regs.modify(|reg| { 20 ch_mux_regs.modify(|reg| {
98 reg.set_ege(true); 21 reg.set_ege(true);
99 //reg.set_se(true);
100 //reg.set_soie(true);
101 }); 22 });
102} 23}
103 24
@@ -236,6 +157,7 @@ use crate::usart;
236 157
237bdma_channels! { 158bdma_channels! {
238 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { 159 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
160 #[cfg(usart)]
239 impl_usart_dma_requests!($channel_peri, $dma_peri, $channel_num); 161 impl_usart_dma_requests!($channel_peri, $dma_peri, $channel_num);
240 }; 162 };
241} 163}