aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-07-15 05:42:06 +0200
committerBob McWhirter <[email protected]>2021-07-16 14:41:20 -0400
commit3d1391ef2d634ca6a90c68be7cc69af02e3dc33b (patch)
treeb73e2ca0a00486acff55fc200e2d3087c70b4ba1
parent69fb1b5418a4fb355d48b3b4357d0cd7562b5c4d (diff)
stm32/dma: impl all variants
-rw-r--r--embassy-stm32/src/bdma/mod.rs413
-rw-r--r--embassy-stm32/src/dma/bdma.rs222
-rw-r--r--embassy-stm32/src/dma/dma.rs210
-rw-r--r--embassy-stm32/src/dma/dmamux.rs61
-rw-r--r--embassy-stm32/src/dma/mod.rs67
-rw-r--r--embassy-stm32/src/dma/v1.rs2
-rw-r--r--embassy-stm32/src/dma/v2.rs331
-rw-r--r--embassy-stm32/src/dma_traits.rs32
-rw-r--r--embassy-stm32/src/dmamux/mod.rs137
-rw-r--r--embassy-stm32/src/lib.rs14
-rw-r--r--embassy-stm32/src/usart/mod.rs83
-rw-r--r--embassy-stm32/src/usart/v1.rs45
-rw-r--r--embassy-stm32/src/usart/v2.rs13
-rw-r--r--examples/stm32f4/src/bin/spi.rs2
-rw-r--r--examples/stm32f4/src/bin/usart.rs3
-rw-r--r--examples/stm32f4/src/bin/usart_dma.rs11
-rw-r--r--examples/stm32l4/src/bin/spi.rs2
-rw-r--r--examples/stm32l4/src/bin/usart.rs2
-rw-r--r--examples/stm32l4/src/bin/usart_dma.rs2
19 files changed, 664 insertions, 988 deletions
diff --git a/embassy-stm32/src/bdma/mod.rs b/embassy-stm32/src/bdma/mod.rs
deleted file mode 100644
index f57358f68..000000000
--- a/embassy-stm32/src/bdma/mod.rs
+++ /dev/null
@@ -1,413 +0,0 @@
1#![macro_use]
2
3use core::future::Future;
4use core::task::Poll;
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!(bdma) * 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();
38
39#[allow(unused)]
40pub(crate) async unsafe fn transfer_p2m(
41 regs: pac::bdma::Ch,
42 state_number: u8,
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 as usize].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 as usize].register(cx.waker());
82 match STATE.ch_status[state_number as usize].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: u8,
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 as usize].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 as usize].register(cx.waker());
137 match STATE.ch_status[state_number as usize].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..crate::pac::dma_channels_count!($dma) {
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 as RccPeripheral>::enable();
181 };
182 }
183}
184
185pub(crate) mod sealed {
186 use super::*;
187
188 pub trait Dma {
189 const NUM: u8;
190 }
191
192 pub trait Channel {
193 const CH_NUM: u8;
194 const STATE_NUM: u8;
195 const DMA_REGS: pac::bdma::Dma;
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) => {
208 impl Dma for crate::peripherals::$peri {}
209 impl sealed::Dma for crate::peripherals::$peri {
210 const NUM: u8 = dma_num!($peri);
211 }
212 };
213}
214
215macro_rules! impl_dma_channel {
216 ($channel_peri:ident, $dma_peri:ident, $ch_num:expr) => {
217 impl Channel for crate::peripherals::$channel_peri {}
218 impl sealed::Channel for crate::peripherals::$channel_peri {
219 const CH_NUM: u8 = $ch_num;
220 const STATE_NUM: u8 = (dma_num!($dma_peri) * 8) + $ch_num;
221 const DMA_REGS: pac::bdma::Dma = crate::pac::$dma_peri;
222
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!($dma_peri) * 8) + $ch_num
230 //}
231 }
232
233 #[cfg(not(dmamux))]
234 impl<T> WriteDma<T> for crate::peripherals::$channel_peri
235 where
236 T: 'static,
237 {
238 type WriteDmaFuture<'a> = impl Future<Output = ()>;
239
240 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
241 where
242 T: 'a,
243 {
244 use sealed::Channel as _Channel;
245
246 let state_num = Self::STATE_NUM;
247 let regs = self.regs();
248
249 unsafe { transfer_m2p(regs, state_num, buf, dst) }
250 }
251 }
252
253 #[cfg(dmamux)]
254 impl<T> WriteDma<T> for crate::peripherals::$channel_peri
255 where
256 Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>,
257 T: 'static,
258 {
259 type WriteDmaFuture<'a> = impl Future<Output = ()>;
260
261 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
262 where
263 T: 'a,
264 {
265 use sealed::Channel as _Channel;
266
267 let state_num = Self::STATE_NUM;
268 let regs = self.regs();
269
270 use crate::dmamux::sealed::Channel as MuxChannel;
271 use crate::dmamux::sealed::PeripheralChannel;
272 let dmamux_regs = <crate::peripherals::$channel_peri as MuxChannel>::DMAMUX_REGS;
273 let dmamux_ch_num =
274 <crate::peripherals::$channel_peri as MuxChannel>::DMAMUX_CH_NUM;
275 let request = <crate::peripherals::$channel_peri as PeripheralChannel<
276 T,
277 crate::dmamux::M2P,
278 >>::REQUEST;
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::P2M>,
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 = <crate::peripherals::$channel_peri as MuxChannel>::DMAMUX_REGS;
340 let dmamux_ch_num =
341 <crate::peripherals::$channel_peri as MuxChannel>::DMAMUX_CH_NUM;
342 let request = <crate::peripherals::$channel_peri as PeripheralChannel<
343 T,
344 crate::dmamux::P2M,
345 >>::REQUEST;
346 unsafe {
347 transfer_p2m(
348 regs,
349 state_num,
350 src,
351 buf,
352 dmamux_regs,
353 dmamux_ch_num,
354 request,
355 )
356 }
357 }
358 }
359 };
360}
361
362macro_rules! dma_num {
363 (DMA1) => {
364 0
365 };
366 (DMA2) => {
367 1
368 };
369 (BDMA) => {
370 0
371 };
372}
373pac::peripherals! {
374 (bdma, $peri:ident) => {
375 impl_dma!($peri);
376 };
377}
378
379pac::bdma_channels! {
380 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
381 impl_dma_channel!($channel_peri, $dma_peri, $channel_num);
382 };
383}
384
385pac::interrupts! {
386 (DMA, $irq:ident) => {
387 #[crate::interrupt]
388 unsafe fn $irq () {
389 on_irq()
390 }
391 };
392}
393
394#[cfg(usart)]
395use crate::usart;
396
397pac::peripherals! {
398 (usart, $peri:ident) => {
399 impl<T:Channel + crate::dma_traits::WriteDma<crate::peripherals::$peri>> usart::TxDma<crate::peripherals::$peri> for T {}
400 impl<T:Channel + crate::dma_traits::WriteDma<crate::peripherals::$peri>> usart::sealed::TxDma<crate::peripherals::$peri> for T {}
401
402 impl<T:Channel + crate::dma_traits::ReadDma<crate::peripherals::$peri>> usart::RxDma<crate::peripherals::$peri> for T {}
403 impl<T:Channel + crate::dma_traits::ReadDma<crate::peripherals::$peri>> usart::sealed::RxDma<crate::peripherals::$peri> for T {}
404 };
405
406 (uart, $peri:ident) => {
407 impl<T:Channel + crate::dma_traits::WriteDma<crate::peripherals::$peri>> usart::TxDma<crate::peripherals::$peri> for T {}
408 impl<T:Channel + crate::dma_traits::WriteDma<crate::peripherals::$peri>> usart::sealed::TxDma<crate::peripherals::$peri> for T {}
409
410 impl<T:Channel + crate::dma_traits::ReadDma<crate::peripherals::$peri>> usart::RxDma<crate::peripherals::$peri> for T {}
411 impl<T:Channel + crate::dma_traits::ReadDma<crate::peripherals::$peri>> usart::sealed::RxDma<crate::peripherals::$peri> for T {}
412 };
413}
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
new file mode 100644
index 000000000..9449d4bf8
--- /dev/null
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -0,0 +1,222 @@
1#![macro_use]
2
3use core::future::Future;
4use core::task::Poll;
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::{Channel, Request};
12use crate::interrupt;
13use crate::pac;
14use crate::pac::bdma::vals;
15use crate::rcc::sealed::RccPeripheral;
16
17const CH_COUNT: usize = pac::peripheral_count!(bdma) * 8;
18const CH_STATUS_NONE: u8 = 0;
19const CH_STATUS_COMPLETED: u8 = 1;
20const CH_STATUS_ERROR: u8 = 2;
21
22struct State {
23 ch_wakers: [AtomicWaker; CH_COUNT],
24 ch_status: [AtomicU8; CH_COUNT],
25}
26
27impl State {
28 const fn new() -> Self {
29 const AW: AtomicWaker = AtomicWaker::new();
30 const AU: AtomicU8 = AtomicU8::new(CH_STATUS_NONE);
31 Self {
32 ch_wakers: [AW; CH_COUNT],
33 ch_status: [AU; CH_COUNT],
34 }
35 }
36}
37
38static STATE: State = State::new();
39
40#[allow(unused)]
41pub(crate) async unsafe fn do_transfer(
42 dma: pac::bdma::Dma,
43 channel_number: u8,
44 state_number: u8,
45 request: Request,
46 dir: vals::Dir,
47 peri_addr: *const u8,
48 mem_addr: *mut u8,
49 mem_len: usize,
50 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
51 #[cfg(dmamux)] dmamux_ch_num: u8,
52) {
53 // ndtr is max 16 bits.
54 assert!(mem_len <= 0xFFFF);
55
56 let ch = dma.ch(channel_number as _);
57
58 // Reset status
59 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA
60 STATE.ch_status[state_number as usize].store(CH_STATUS_NONE, Ordering::Release);
61
62 let on_drop = OnDrop::new(|| unsafe {
63 ch.cr().modify(|w| {
64 w.set_tcie(false);
65 w.set_teie(false);
66 w.set_en(false);
67 });
68 while ch.cr().read().en() {}
69 });
70
71 #[cfg(dmamux)]
72 super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
73
74 #[cfg(bdma_v2)]
75 critical_section::with(|_| {
76 dma.cselr()
77 .modify(|w| w.set_cs(channel_number as _, request))
78 });
79
80 ch.par().write_value(peri_addr as u32);
81 ch.mar().write_value(mem_addr as u32);
82 ch.ndtr().write(|w| w.set_ndt(mem_len as u16));
83 ch.cr().write(|w| {
84 w.set_psize(vals::Size::BITS8);
85 w.set_msize(vals::Size::BITS8);
86 w.set_minc(vals::Inc::ENABLED);
87 w.set_dir(dir);
88 w.set_teie(true);
89 w.set_tcie(true);
90 w.set_en(true);
91 });
92
93 let res = poll_fn(|cx| {
94 STATE.ch_wakers[state_number as usize].register(cx.waker());
95 match STATE.ch_status[state_number as usize].load(Ordering::Acquire) {
96 CH_STATUS_NONE => Poll::Pending,
97 x => Poll::Ready(x),
98 }
99 })
100 .await;
101
102 on_drop.defuse();
103
104 // TODO handle error
105 assert!(res == CH_STATUS_COMPLETED);
106}
107
108macro_rules! dma_num {
109 (DMA1) => {
110 0
111 };
112 (DMA2) => {
113 1
114 };
115 (BDMA) => {
116 0
117 };
118}
119
120unsafe fn on_irq() {
121 pac::peripherals! {
122 (bdma, $dma:ident) => {
123 let isr = pac::$dma.isr().read();
124 pac::$dma.ifcr().write_value(isr);
125 let dman = dma_num!($dma);
126
127 for chn in 0..crate::pac::dma_channels_count!($dma) {
128 let n = dman * 8 + chn;
129 if isr.teif(chn) {
130 STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed);
131 STATE.ch_wakers[n].wake();
132 } else if isr.tcif(chn) {
133 STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed);
134 STATE.ch_wakers[n].wake();
135 }
136 }
137 };
138 }
139}
140
141
142/// safety: must be called only once
143pub(crate) unsafe fn init() {
144 pac::interrupts! {
145 (DMA, $irq:ident) => {
146 crate::interrupt::$irq::steal().enable();
147 };
148 }
149 pac::peripherals! {
150 (bdma, $peri:ident) => {
151 crate::peripherals::$peri::enable();
152 };
153 }
154}
155
156pac::bdma_channels! {
157 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
158 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {}
159 impl Channel for crate::peripherals::$channel_peri
160 {
161 type ReadFuture<'a> = impl Future<Output = ()>;
162 type WriteFuture<'a> = impl Future<Output = ()>;
163
164 fn read<'a>(
165 &'a mut self,
166 request: Request,
167 src: *mut u8,
168 buf: &'a mut [u8],
169 ) -> Self::ReadFuture<'a> {
170 unsafe {
171 do_transfer(
172 crate::pac::$dma_peri,
173 $channel_num,
174 (dma_num!($dma_peri) * 8) + $channel_num,
175 request,
176 vals::Dir::FROMPERIPHERAL,
177 src,
178 buf.as_mut_ptr(),
179 buf.len(),
180 #[cfg(dmamux)]
181 <Self as super::dmamux::MuxChannel>::DMAMUX_REGS,
182 #[cfg(dmamux)]
183 <Self as super::dmamux::MuxChannel>::DMAMUX_CH_NUM,
184 )
185 }
186 }
187
188 fn write<'a>(
189 &'a mut self,
190 request: Request,
191 buf: &'a [u8],
192 dst: *mut u8,
193 ) -> Self::WriteFuture<'a> {
194 unsafe {
195 do_transfer(
196 crate::pac::$dma_peri,
197 $channel_num,
198 (dma_num!($dma_peri) * 8) + $channel_num,
199 request,
200 vals::Dir::FROMMEMORY,
201 dst,
202 buf.as_ptr() as *mut u8,
203 buf.len(),
204 #[cfg(dmamux)]
205 <Self as super::dmamux::MuxChannel>::DMAMUX_REGS,
206 #[cfg(dmamux)]
207 <Self as super::dmamux::MuxChannel>::DMAMUX_CH_NUM,
208 )
209 }
210 }
211 }
212 };
213}
214
215pac::interrupts! {
216 (DMA, $irq:ident) => {
217 #[crate::interrupt]
218 unsafe fn $irq () {
219 on_irq()
220 }
221 };
222}
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
new file mode 100644
index 000000000..b0df6ddc5
--- /dev/null
+++ b/embassy-stm32/src/dma/dma.rs
@@ -0,0 +1,210 @@
1use core::task::Poll;
2
3use atomic_polyfill::{AtomicU8, Ordering};
4use core::future::Future;
5use embassy::interrupt::{Interrupt, InterruptExt};
6use embassy::util::AtomicWaker;
7use futures::future::poll_fn;
8
9use crate::interrupt;
10use crate::pac;
11use crate::pac::dma::{regs, vals};
12use crate::rcc::sealed::RccPeripheral;
13
14use super::{Channel, Request};
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();
38
39//async unsafe fn do_transfer(ch: &mut impl Channel, ch_func: u8, src: *const u8, dst: &mut [u8]) {
40
41pub(crate) async unsafe fn do_transfer(
42 dma: pac::dma::Dma,
43 channel_number: u8,
44 state_number: u8,
45 request: Request,
46 dir: vals::Dir,
47 peri_addr: *const u8,
48 mem_addr: *mut u8,
49 mem_len: usize,
50 #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux,
51 #[cfg(dmamux)] dmamux_ch_num: u8,
52) {
53 // ndtr is max 16 bits.
54 assert!(mem_len <= 0xFFFF);
55
56 // Reset status
57 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA
58 STATE.ch_status[state_number as usize].store(CH_STATUS_NONE, Ordering::Release);
59
60 let ch = dma.st(channel_number as _);
61
62 #[cfg(dmamux)]
63 super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
64
65 unsafe {
66 ch.par().write_value(peri_addr as u32);
67 ch.m0ar().write_value(mem_addr as u32);
68 ch.ndtr().write_value(regs::Ndtr(mem_len as _));
69 ch.cr().write(|w| {
70 w.set_dir(dir);
71 w.set_msize(vals::Size::BITS8);
72 w.set_psize(vals::Size::BITS8);
73 w.set_minc(vals::Inc::INCREMENTED);
74 w.set_pinc(vals::Inc::FIXED);
75 w.set_teie(true);
76 w.set_tcie(true);
77 w.set_en(true);
78
79 #[cfg(dma_v2)]
80 w.set_chsel(request);
81 });
82 }
83
84 let res = poll_fn(|cx| {
85 let n = channel_number as usize;
86 STATE.ch_wakers[n].register(cx.waker());
87 match STATE.ch_status[n].load(Ordering::Acquire) {
88 CH_STATUS_NONE => Poll::Pending,
89 x => Poll::Ready(x),
90 }
91 })
92 .await;
93
94 // TODO handle error
95 assert!(res == CH_STATUS_COMPLETED);
96}
97
98macro_rules! dma_num {
99 (DMA1) => {
100 0
101 };
102 (DMA2) => {
103 1
104 };
105}
106
107unsafe fn on_irq() {
108 pac::peripherals! {
109 (dma, $dma:ident) => {
110 for isrn in 0..2 {
111 let isr = pac::$dma.isr(isrn).read();
112 pac::$dma.ifcr(isrn).write_value(isr);
113 let dman = dma_num!($dma);
114
115 for chn in 0..4 {
116 let n = dman * 8 + isrn * 4 + chn;
117 if isr.teif(chn) {
118 STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed);
119 STATE.ch_wakers[n].wake();
120 } else if isr.tcif(chn) {
121 STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed);
122 STATE.ch_wakers[n].wake();
123 }
124 }
125 }
126 };
127 }
128}
129
130/// safety: must be called only once
131pub(crate) unsafe fn init() {
132 pac::interrupts! {
133 (DMA, $irq:ident) => {
134 interrupt::$irq::steal().enable();
135 };
136 }
137 pac::peripherals! {
138 (dma, $peri:ident) => {
139 crate::peripherals::$peri::enable();
140 };
141 }
142}
143
144pac::dma_channels! {
145 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
146 impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri {}
147 impl Channel for crate::peripherals::$channel_peri
148 {
149 type ReadFuture<'a> = impl Future<Output = ()>;
150 type WriteFuture<'a> = impl Future<Output = ()>;
151
152 fn read<'a>(
153 &'a mut self,
154 request: Request,
155 src: *mut u8,
156 buf: &'a mut [u8],
157 ) -> Self::ReadFuture<'a> {
158 unsafe {
159 do_transfer(
160 crate::pac::$dma_peri,
161 $channel_num,
162 (dma_num!($dma_peri) * 8) + $channel_num,
163 request,
164 vals::Dir::PERIPHERALTOMEMORY,
165 src,
166 buf.as_mut_ptr(),
167 buf.len(),
168 #[cfg(dmamux)]
169 <Self as super::dmamux::MuxChannel>::DMAMUX_REGS,
170 #[cfg(dmamux)]
171 <Self as super::dmamux::MuxChannel>::DMAMUX_CH_NUM,
172 )
173 }
174 }
175
176 fn write<'a>(
177 &'a mut self,
178 request: Request,
179 buf: &'a [u8],
180 dst: *mut u8,
181 ) -> Self::WriteFuture<'a> {
182 unsafe {
183 do_transfer(
184 crate::pac::$dma_peri,
185 $channel_num,
186 (dma_num!($dma_peri) * 8) + $channel_num,
187 request,
188 vals::Dir::MEMORYTOPERIPHERAL,
189 dst,
190 buf.as_ptr() as *mut u8,
191 buf.len(),
192 #[cfg(dmamux)]
193 <Self as super::dmamux::MuxChannel>::DMAMUX_REGS,
194 #[cfg(dmamux)]
195 <Self as super::dmamux::MuxChannel>::DMAMUX_CH_NUM,
196 )
197 }
198 }
199 }
200 };
201}
202
203pac::interrupts! {
204 (DMA, $irq:ident) => {
205 #[crate::interrupt]
206 unsafe fn $irq () {
207 on_irq()
208 }
209 };
210}
diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs
new file mode 100644
index 000000000..ca2879c2e
--- /dev/null
+++ b/embassy-stm32/src/dma/dmamux.rs
@@ -0,0 +1,61 @@
1#![macro_use]
2
3use crate::pac;
4use crate::peripherals;
5
6pub(crate) unsafe fn configure_dmamux(
7 dmamux_regs: pac::dmamux::Dmamux,
8 dmamux_ch_num: u8,
9 request: u8,
10) {
11 let ch_mux_regs = dmamux_regs.ccr(dmamux_ch_num as _);
12 ch_mux_regs.write(|reg| {
13 reg.set_nbreq(0);
14 reg.set_dmareq_id(request);
15 });
16
17 ch_mux_regs.modify(|reg| {
18 reg.set_ege(true);
19 });
20}
21
22pub(crate) trait MuxChannel {
23 const DMAMUX_CH_NUM: u8;
24 const DMAMUX_REGS: pac::dmamux::Dmamux;
25}
26
27macro_rules! dma_num {
28 (DMA1) => {
29 0
30 };
31 (DMA2) => {
32 1
33 };
34 (BDMA) => {
35 0
36 };
37}
38
39macro_rules! dmamux_peri {
40 (DMA1) => {
41 crate::pac::DMAMUX1
42 };
43 (DMA2) => {
44 crate::pac::DMAMUX1
45 };
46 (BDMA) => {
47 crate::pac::DMAMUX1
48 };
49}
50
51pac::bdma_channels! {
52 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
53 impl MuxChannel for peripherals::$channel_peri {
54 const DMAMUX_CH_NUM: u8 = (dma_num!($dma_peri) * 8) + $channel_num;
55 const DMAMUX_REGS: pac::dmamux::Dmamux = dmamux_peri!($dma_peri);
56 }
57 };
58}
59
60/// safety: must be called only once
61pub(crate) unsafe fn init() {}
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index ed080cd16..ebad3d7b6 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -1,9 +1,62 @@
1#![macro_use] 1#[cfg(bdma)]
2mod bdma;
3#[cfg(dma)]
4mod dma;
5#[cfg(dmamux)]
6mod dmamux;
2 7
3#[cfg_attr(dma_v1, path = "v1.rs")] 8use core::future::Future;
4#[cfg_attr(dma_v2, path = "v2.rs")] 9use embassy::util::Unborrow;
5mod _version;
6 10
7#[cfg(dma)] 11#[cfg(any(bdma_v2, dma_v2, dmamux))]
8#[allow(unused)] 12pub type Request = u8;
9pub use _version::*; 13#[cfg(not(any(bdma_v2, dma_v2, dmamux)))]
14pub type Request = ();
15
16pub(crate) mod sealed {
17 pub trait Channel {}
18}
19
20pub trait Channel: sealed::Channel {
21 type ReadFuture<'a>: Future<Output = ()> + 'a
22 where
23 Self: 'a;
24
25 type WriteFuture<'a>: Future<Output = ()> + 'a
26 where
27 Self: 'a;
28
29 fn read<'a>(
30 &'a mut self,
31 request: Request,
32 src: *mut u8,
33 buf: &'a mut [u8],
34 ) -> Self::ReadFuture<'a>;
35
36 fn write<'a>(
37 &'a mut self,
38 request: Request,
39 buf: &'a [u8],
40 dst: *mut u8,
41 ) -> Self::WriteFuture<'a>;
42}
43
44pub struct NoDma;
45
46unsafe impl Unborrow for NoDma {
47 type Target = NoDma;
48
49 unsafe fn unborrow(self) -> Self::Target {
50 self
51 }
52}
53
54// safety: must be called only once at startup
55pub(crate) unsafe fn init() {
56 #[cfg(bdma)]
57 bdma::init();
58 #[cfg(dma)]
59 dma::init();
60 #[cfg(dmamux)]
61 dmamux::init();
62}
diff --git a/embassy-stm32/src/dma/v1.rs b/embassy-stm32/src/dma/v1.rs
deleted file mode 100644
index 4544108e5..000000000
--- a/embassy-stm32/src/dma/v1.rs
+++ /dev/null
@@ -1,2 +0,0 @@
1/// safety: must be called only once
2pub(crate) unsafe fn init() {}
diff --git a/embassy-stm32/src/dma/v2.rs b/embassy-stm32/src/dma/v2.rs
deleted file mode 100644
index df3b922ff..000000000
--- a/embassy-stm32/src/dma/v2.rs
+++ /dev/null
@@ -1,331 +0,0 @@
1use core::task::Poll;
2
3use crate::dma_traits::{ReadDma, WriteDma};
4use atomic_polyfill::{AtomicU8, Ordering};
5use core::future::Future;
6use embassy::interrupt::{Interrupt, InterruptExt};
7use embassy::util::AtomicWaker;
8use futures::future::poll_fn;
9
10use crate::interrupt;
11use crate::pac;
12use crate::pac::dma::{regs, vals};
13
14use crate::pac::dma_channels;
15use crate::pac::interrupts;
16use crate::pac::peripheral_count;
17use crate::pac::peripheral_dma_channels;
18use crate::pac::peripherals;
19use crate::peripherals;
20
21const CH_COUNT: usize = peripheral_count!(DMA) * 8;
22const CH_STATUS_NONE: u8 = 0;
23const CH_STATUS_COMPLETED: u8 = 1;
24const CH_STATUS_ERROR: u8 = 2;
25
26struct State {
27 ch_wakers: [AtomicWaker; CH_COUNT],
28 ch_status: [AtomicU8; CH_COUNT],
29}
30
31impl State {
32 const fn new() -> Self {
33 const AW: AtomicWaker = AtomicWaker::new();
34 const AU: AtomicU8 = AtomicU8::new(CH_STATUS_NONE);
35 Self {
36 ch_wakers: [AW; CH_COUNT],
37 ch_status: [AU; CH_COUNT],
38 }
39 }
40}
41
42static STATE: State = State::new();
43
44#[allow(unused)] // Used by usart/v1.rs which may or may not be enabled
45pub(crate) async unsafe fn transfer_p2m(
46 ch: &mut impl Channel,
47 ch_func: u8,
48 src: *const u8,
49 dst: &mut [u8],
50) {
51 let n = ch.num();
52 let c = ch.regs();
53
54 // ndtr is max 16 bits.
55 assert!(dst.len() <= 0xFFFF);
56
57 // Reset status
58 // Generate a DMB here to flush the store buffer (M7) before enabling the DMA
59 STATE.ch_status[n].store(CH_STATUS_NONE, Ordering::Release);
60
61 unsafe {
62 c.par().write_value(src as _);
63 c.m0ar().write_value(dst.as_ptr() as _);
64 c.ndtr().write_value(regs::Ndtr(dst.len() as _));
65 c.cr().write(|w| {
66 w.set_dir(vals::Dir::PERIPHERALTOMEMORY);
67 w.set_msize(vals::Size::BITS8);
68 w.set_psize(vals::Size::BITS8);
69 w.set_minc(vals::Inc::INCREMENTED);
70 w.set_pinc(vals::Inc::FIXED);
71 w.set_chsel(ch_func);
72 w.set_teie(true);
73 w.set_tcie(true);
74 w.set_en(true);
75 });
76 }
77
78 let res = poll_fn(|cx| {
79 STATE.ch_wakers[n].register(cx.waker());
80 match STATE.ch_status[n].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)] // Used by usart/v1.rs which may or may not be enabled
92pub(crate) async unsafe fn transfer_m2p(
93 ch: &mut impl Channel,
94 ch_func: u8,
95 src: &[u8],
96 dst: *mut u8,
97) {
98 let n = ch.num();
99 let c = ch.regs();
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[n].store(CH_STATUS_NONE, Ordering::Release);
107
108 unsafe {
109 c.par().write_value(dst as _);
110 c.m0ar().write_value(src.as_ptr() as _);
111 c.ndtr().write_value(regs::Ndtr(src.len() as _));
112 c.cr().write(|w| {
113 w.set_dir(vals::Dir::MEMORYTOPERIPHERAL);
114 w.set_msize(vals::Size::BITS8);
115 w.set_psize(vals::Size::BITS8);
116 w.set_minc(vals::Inc::INCREMENTED);
117 w.set_pinc(vals::Inc::FIXED);
118 w.set_chsel(ch_func);
119 w.set_teie(true);
120 w.set_tcie(true);
121 w.set_en(true);
122 });
123 }
124
125 let res = poll_fn(|cx| {
126 STATE.ch_wakers[n].register(cx.waker());
127 match STATE.ch_status[n].load(Ordering::Acquire) {
128 CH_STATUS_NONE => {
129 let left = c.ndtr().read().ndt();
130 Poll::Pending
131 }
132 x => Poll::Ready(x),
133 }
134 })
135 .await;
136
137 // TODO handle error
138 assert!(res == CH_STATUS_COMPLETED);
139}
140
141unsafe fn on_irq() {
142 peripherals! {
143 (dma, $dma:ident) => {
144 for isrn in 0..2 {
145 let isr = pac::$dma.isr(isrn).read();
146 pac::$dma.ifcr(isrn).write_value(isr);
147 let dman = <peripherals::$dma as sealed::Dma>::num() as usize;
148
149 for chn in 0..4 {
150 let n = dman * 8 + isrn * 4 + chn;
151 if isr.teif(chn) {
152 STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed);
153 STATE.ch_wakers[n].wake();
154 } else if isr.tcif(chn) {
155 STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed);
156 STATE.ch_wakers[n].wake();
157 }
158 }
159 }
160 };
161 }
162}
163
164/// safety: must be called only once
165pub(crate) unsafe fn init() {
166 interrupts! {
167 (DMA, $irq:ident) => {
168 interrupt::$irq::steal().enable();
169 };
170 }
171}
172
173pub(crate) mod sealed {
174 use super::*;
175
176 pub trait Dma {
177 fn num() -> u8;
178 fn regs() -> &'static pac::dma::Dma;
179 }
180
181 pub trait Channel {
182 fn dma_regs() -> &'static pac::dma::Dma;
183
184 fn num(&self) -> usize;
185
186 fn ch_num(&self) -> u8;
187
188 fn regs(&self) -> pac::dma::St {
189 Self::dma_regs().st(self.ch_num() as _)
190 }
191 }
192
193 pub trait PeripheralChannel<PERI, OP>: Channel {
194 fn request(&self) -> u8;
195 }
196}
197
198pub trait Dma: sealed::Dma + Sized {}
199pub trait Channel: sealed::Channel + Sized {}
200pub trait PeripheralChannel<PERI, OP>: sealed::PeripheralChannel<PERI, OP> + Sized {}
201
202macro_rules! impl_dma {
203 ($peri:ident, $num:expr) => {
204 impl Dma for peripherals::$peri {}
205 impl sealed::Dma for peripherals::$peri {
206 fn num() -> u8 {
207 $num
208 }
209 fn regs() -> &'static pac::dma::Dma {
210 &pac::$peri
211 }
212 }
213 };
214}
215
216macro_rules! impl_dma_channel {
217 ($channel_peri:ident, $dma_peri:ident, $dma_num:expr, $ch_num:expr) => {
218 impl Channel for peripherals::$channel_peri {}
219 impl sealed::Channel for peripherals::$channel_peri {
220 #[inline]
221 fn dma_regs() -> &'static pac::dma::Dma {
222 &crate::pac::$dma_peri
223 }
224
225 fn num(&self) -> usize {
226 ($dma_num * 8) + $ch_num
227 }
228
229 fn ch_num(&self) -> u8 {
230 $ch_num
231 }
232 }
233
234 impl<T> WriteDma<T> for peripherals::$channel_peri
235 where
236 Self: sealed::PeripheralChannel<T, M2P>,
237 T: 'static,
238 {
239 type WriteDmaFuture<'a> = impl Future<Output = ()>;
240
241 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
242 where
243 T: 'a,
244 {
245 let request = sealed::PeripheralChannel::<T, M2P>::request(self);
246 unsafe { transfer_m2p(self, request, buf, dst) }
247 }
248 }
249
250 impl<T> ReadDma<T> for peripherals::$channel_peri
251 where
252 Self: sealed::PeripheralChannel<T, P2M>,
253 T: 'static,
254 {
255 type ReadDmaFuture<'a> = impl Future<Output = ()>;
256
257 fn transfer<'a>(
258 &'a mut self,
259 src: *const u8,
260 buf: &'a mut [u8],
261 ) -> Self::ReadDmaFuture<'a>
262 where
263 T: 'a,
264 {
265 let request = sealed::PeripheralChannel::<T, P2M>::request(self);
266 unsafe { transfer_p2m(self, request, src, buf) }
267 }
268 }
269 };
270}
271
272peripherals! {
273 (dma, DMA1) => {
274 impl_dma!(DMA1, 0);
275 dma_channels! {
276 ($channel_peri:ident, DMA1, $channel_num:expr) => {
277 impl_dma_channel!($channel_peri, DMA1, 0, $channel_num);
278 };
279 }
280 };
281 (dma, DMA2) => {
282 impl_dma!(DMA2, 1);
283 dma_channels! {
284 ($channel_peri:ident, DMA2, $channel_num:expr) => {
285 impl_dma_channel!($channel_peri, DMA2, 1, $channel_num);
286 };
287 }
288 };
289}
290
291interrupts! {
292 (DMA, $irq:ident) => {
293 #[crate::interrupt]
294 unsafe fn $irq () {
295 on_irq()
296 }
297 };
298}
299
300pub struct P2M;
301pub struct M2P;
302
303#[cfg(usart)]
304use crate::usart;
305peripheral_dma_channels! {
306 ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => {
307 impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
308 impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
309
310 impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri {
311 fn request(&self) -> u8 {
312 $event_num
313 }
314 }
315
316 impl PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri { }
317 };
318
319 ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => {
320 impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
321 impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
322
323 impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri {
324 fn request(&self) -> u8 {
325 $event_num
326 }
327 }
328
329 impl PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri { }
330 };
331}
diff --git a/embassy-stm32/src/dma_traits.rs b/embassy-stm32/src/dma_traits.rs
deleted file mode 100644
index 6733d911a..000000000
--- a/embassy-stm32/src/dma_traits.rs
+++ /dev/null
@@ -1,32 +0,0 @@
1use core::future::Future;
2use embassy::util::Unborrow;
3
4pub trait WriteDma<T> {
5 type WriteDmaFuture<'a>: Future<Output = ()> + 'a
6 where
7 Self: 'a;
8
9 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
10 where
11 T: 'a;
12}
13
14pub trait ReadDma<T> {
15 type ReadDmaFuture<'a>: Future<Output = ()> + 'a
16 where
17 Self: 'a;
18
19 fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a>
20 where
21 T: 'a;
22}
23
24pub struct NoDma;
25
26unsafe impl Unborrow for NoDma {
27 type Target = NoDma;
28
29 unsafe fn unborrow(self) -> Self::Target {
30 self
31 }
32}
diff --git a/embassy-stm32/src/dmamux/mod.rs b/embassy-stm32/src/dmamux/mod.rs
deleted file mode 100644
index ecea0b290..000000000
--- a/embassy-stm32/src/dmamux/mod.rs
+++ /dev/null
@@ -1,137 +0,0 @@
1#![macro_use]
2
3use crate::pac;
4use crate::pac::bdma_channels;
5use crate::pac::dma_requests;
6use crate::pac::peripherals;
7use crate::peripherals;
8
9pub(crate) unsafe fn configure_dmamux(
10 dmamux_regs: pac::dmamux::Dmamux,
11 dmamux_ch_num: u8,
12 request: u8,
13) {
14 let ch_mux_regs = dmamux_regs.ccr(dmamux_ch_num as _);
15 ch_mux_regs.write(|reg| {
16 reg.set_nbreq(0);
17 reg.set_dmareq_id(request);
18 });
19
20 ch_mux_regs.modify(|reg| {
21 reg.set_ege(true);
22 });
23}
24
25pub(crate) mod sealed {
26 use super::*;
27
28 pub trait Channel {
29 const DMAMUX_CH_NUM: u8;
30 const DMAMUX_REGS: pac::dmamux::Dmamux;
31 }
32
33 pub trait PeripheralChannel<PERI, OP>: Channel {
34 const REQUEST: u8;
35 }
36}
37
38pub trait Channel: sealed::Channel {}
39pub trait PeripheralChannel<PERI, OP>: sealed::Channel {}
40
41pub struct P2M;
42pub struct M2P;
43
44macro_rules! dma_num {
45 (DMA1) => {
46 0
47 };
48 (DMA2) => {
49 1
50 };
51 (BDMA) => {
52 0
53 };
54}
55
56macro_rules! dmamux_peri {
57 (DMA1) => {
58 crate::pac::DMAMUX1
59 };
60 (DMA2) => {
61 crate::pac::DMAMUX1
62 };
63 (BDMA) => {
64 crate::pac::DMAMUX1
65 };
66}
67
68#[allow(unused)]
69macro_rules! impl_dma_channel {
70 ($channel_peri:ident, $channel_num:expr, $dma_peri: ident) => {
71 impl Channel for peripherals::$channel_peri {}
72 impl sealed::Channel for peripherals::$channel_peri {
73 const DMAMUX_CH_NUM: u8 = (dma_num!($dma_peri) * 8) + $channel_num;
74 const DMAMUX_REGS: pac::dmamux::Dmamux = dmamux_peri!($dma_peri);
75 }
76 };
77}
78
79peripherals! {
80 (bdma, $peri:ident) => {
81 bdma_channels! {
82 ($channel_peri:ident, $peri, $channel_num:expr) => {
83 impl_dma_channel!($channel_peri, $channel_num, $peri);
84 };
85 }
86 };
87}
88
89#[allow(unused)]
90macro_rules! impl_peripheral_channel {
91 ($channel_peri:ident, $direction:ident, $peri:ident, $request:expr) => {
92 impl sealed::PeripheralChannel<peripherals::$peri, $direction>
93 for peripherals::$channel_peri
94 {
95 const REQUEST: u8 = $request;
96 }
97
98 impl PeripheralChannel<peripherals::$peri, $direction> for peripherals::$channel_peri {}
99 };
100}
101
102#[allow(unused)]
103macro_rules! impl_usart_dma_requests {
104 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
105 dma_requests! {
106 (usart, $peri:ident, RX, $request:expr) => {
107 impl_peripheral_channel!($channel_peri, P2M, $peri, $request);
108 };
109
110 (usart, $peri:ident, TX, $request:expr) => {
111 impl_peripheral_channel!($channel_peri, M2P, $peri, $request);
112 };
113
114 (uart, $peri:ident, RX, $request:expr) => {
115 impl_peripheral_channel!($channel_peri, P2M, $peri, $request);
116 };
117
118 (uart, $peri:ident, TX, $request:expr) => {
119 impl_peripheral_channel!($channel_peri, M2P, $peri, $request);
120 };
121 }
122 };
123}
124
125#[allow(unused)]
126#[cfg(usart)]
127use crate::usart;
128
129bdma_channels! {
130 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
131 #[cfg(usart)]
132 impl_usart_dma_requests!($channel_peri, $dma_peri, $channel_num);
133 };
134}
135
136/// safety: must be called only once
137pub(crate) unsafe fn init() {}
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 22999a69e..c10310e2d 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -19,25 +19,18 @@ pub mod interrupt;
19pub mod time; 19pub mod time;
20 20
21// Always-present hardware 21// Always-present hardware
22pub mod dma;
22pub mod gpio; 23pub mod gpio;
23pub mod rcc; 24pub mod rcc;
24 25
25// Sometimes-present hardware 26// Sometimes-present hardware
26#[cfg(any(dma, bdma, dmamux))]
27pub mod dma_traits;
28 27
29#[cfg(adc)] 28#[cfg(adc)]
30pub mod adc; 29pub mod adc;
31#[cfg(bdma)]
32pub mod bdma;
33#[cfg(timer)] 30#[cfg(timer)]
34pub mod clock; 31pub mod clock;
35#[cfg(dac)] 32#[cfg(dac)]
36pub mod dac; 33pub mod dac;
37#[cfg(dma)]
38pub mod dma;
39#[cfg(dmamux)]
40pub mod dmamux;
41#[cfg(all(eth, feature = "net"))] 34#[cfg(all(eth, feature = "net"))]
42pub mod eth; 35pub mod eth;
43#[cfg(exti)] 36#[cfg(exti)]
@@ -94,12 +87,7 @@ pub fn init(config: Config) -> Peripherals {
94 let p = Peripherals::take(); 87 let p = Peripherals::take();
95 88
96 unsafe { 89 unsafe {
97 #[cfg(dma)]
98 dma::init(); 90 dma::init();
99 #[cfg(bdma)]
100 bdma::init();
101 #[cfg(dmamux)]
102 dmamux::init();
103 #[cfg(exti)] 91 #[cfg(exti)]
104 exti::init(); 92 exti::init();
105 93
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index c3ac8bc59..bf6fa9131 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -3,7 +3,7 @@
3#[cfg_attr(usart_v1, path = "v1.rs")] 3#[cfg_attr(usart_v1, path = "v1.rs")]
4#[cfg_attr(usart_v2, path = "v2.rs")] 4#[cfg_attr(usart_v2, path = "v2.rs")]
5mod _version; 5mod _version;
6use crate::peripherals; 6use crate::{dma, peripherals};
7pub use _version::*; 7pub use _version::*;
8 8
9use crate::gpio::Pin; 9use crate::gpio::Pin;
@@ -72,9 +72,6 @@ pub enum Error {
72pub(crate) mod sealed { 72pub(crate) mod sealed {
73 use super::*; 73 use super::*;
74 74
75 #[cfg(any(dma, bdma, dmamux))]
76 use crate::dma_traits::WriteDma;
77
78 pub trait Instance { 75 pub trait Instance {
79 fn regs(&self) -> crate::pac::usart::Usart; 76 fn regs(&self) -> crate::pac::usart::Usart;
80 } 77 }
@@ -94,11 +91,13 @@ pub(crate) mod sealed {
94 fn af_num(&self) -> u8; 91 fn af_num(&self) -> u8;
95 } 92 }
96 93
97 #[cfg(any(bdma, dma, dmamux))] 94 pub trait RxDma<T: Instance> {
98 pub trait RxDma<T: Instance> {} 95 fn request(&self) -> dma::Request;
96 }
99 97
100 #[cfg(any(bdma, dma, dmamux))] 98 pub trait TxDma<T: Instance> {
101 pub trait TxDma<T: Instance>: WriteDma<T> {} 99 fn request(&self) -> dma::Request;
100 }
102} 101}
103 102
104pub trait Instance: sealed::Instance + RccPeripheral {} 103pub trait Instance: sealed::Instance + RccPeripheral {}
@@ -107,12 +106,8 @@ pub trait TxPin<T: Instance>: sealed::TxPin<T> {}
107pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {} 106pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {}
108pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {} 107pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {}
109pub trait CkPin<T: Instance>: sealed::CkPin<T> {} 108pub trait CkPin<T: Instance>: sealed::CkPin<T> {}
110 109pub trait RxDma<T: Instance>: sealed::RxDma<T> + dma::Channel {}
111#[cfg(any(bdma, dma, dmamux))] 110pub trait TxDma<T: Instance>: sealed::TxDma<T> + dma::Channel {}
112pub trait RxDma<T: Instance>: sealed::RxDma<T> {}
113
114#[cfg(any(bdma, dma, dmamux))]
115pub trait TxDma<T: Instance>: sealed::TxDma<T> {}
116 111
117crate::pac::peripherals!( 112crate::pac::peripherals!(
118 (usart, $inst:ident) => { 113 (usart, $inst:ident) => {
@@ -141,46 +136,86 @@ macro_rules! impl_pin {
141crate::pac::peripheral_pins!( 136crate::pac::peripheral_pins!(
142 137
143 // USART 138 // USART
144
145 ($inst:ident, usart, USART, $pin:ident, TX, $af:expr) => { 139 ($inst:ident, usart, USART, $pin:ident, TX, $af:expr) => {
146 impl_pin!($inst, $pin, TxPin, $af); 140 impl_pin!($inst, $pin, TxPin, $af);
147 }; 141 };
148
149 ($inst:ident, usart, USART, $pin:ident, RX, $af:expr) => { 142 ($inst:ident, usart, USART, $pin:ident, RX, $af:expr) => {
150 impl_pin!($inst, $pin, RxPin, $af); 143 impl_pin!($inst, $pin, RxPin, $af);
151 }; 144 };
152
153 ($inst:ident, usart, USART, $pin:ident, CTS, $af:expr) => { 145 ($inst:ident, usart, USART, $pin:ident, CTS, $af:expr) => {
154 impl_pin!($inst, $pin, CtsPin, $af); 146 impl_pin!($inst, $pin, CtsPin, $af);
155 }; 147 };
156
157 ($inst:ident, usart, USART, $pin:ident, RTS, $af:expr) => { 148 ($inst:ident, usart, USART, $pin:ident, RTS, $af:expr) => {
158 impl_pin!($inst, $pin, RtsPin, $af); 149 impl_pin!($inst, $pin, RtsPin, $af);
159 }; 150 };
160
161 ($inst:ident, usart, USART, $pin:ident, CK, $af:expr) => { 151 ($inst:ident, usart, USART, $pin:ident, CK, $af:expr) => {
162 impl_pin!($inst, $pin, CkPin, $af); 152 impl_pin!($inst, $pin, CkPin, $af);
163 }; 153 };
164 154
165 // UART 155 // UART
166
167 ($inst:ident, uart, UART, $pin:ident, TX, $af:expr) => { 156 ($inst:ident, uart, UART, $pin:ident, TX, $af:expr) => {
168 impl_pin!($inst, $pin, TxPin, $af); 157 impl_pin!($inst, $pin, TxPin, $af);
169 }; 158 };
170
171 ($inst:ident, uart, UART, $pin:ident, RX, $af:expr) => { 159 ($inst:ident, uart, UART, $pin:ident, RX, $af:expr) => {
172 impl_pin!($inst, $pin, RxPin, $af); 160 impl_pin!($inst, $pin, RxPin, $af);
173 }; 161 };
174
175 ($inst:ident, uart, UART, $pin:ident, CTS, $af:expr) => { 162 ($inst:ident, uart, UART, $pin:ident, CTS, $af:expr) => {
176 impl_pin!($inst, $pin, CtsPin, $af); 163 impl_pin!($inst, $pin, CtsPin, $af);
177 }; 164 };
178
179 ($inst:ident, uart, UART, $pin:ident, RTS, $af:expr) => { 165 ($inst:ident, uart, UART, $pin:ident, RTS, $af:expr) => {
180 impl_pin!($inst, $pin, RtsPin, $af); 166 impl_pin!($inst, $pin, RtsPin, $af);
181 }; 167 };
182
183 ($inst:ident, uart, UART, $pin:ident, CK, $af:expr) => { 168 ($inst:ident, uart, UART, $pin:ident, CK, $af:expr) => {
184 impl_pin!($inst, $pin, CkPin, $af); 169 impl_pin!($inst, $pin, CkPin, $af);
185 }; 170 };
186); 171);
172
173macro_rules! impl_dma {
174 ($inst:ident, ALL, $signal:ident, $request:expr) => {
175 impl<T: crate::dma::Channel> sealed::$signal<peripherals::$inst> for T {
176 fn request(&self) -> dma::Request {
177 $request
178 }
179 }
180
181 impl<T: crate::dma::Channel> $signal<peripherals::$inst> for T {}
182 };
183 ($inst:ident, $channel:ident, $signal:ident, $request:expr) => {
184 impl sealed::$signal<peripherals::$inst> for peripherals::$channel {
185 fn request(&self) -> dma::Request {
186 $request
187 }
188 }
189
190 impl $signal<peripherals::$inst> for peripherals::$channel {}
191 };
192}
193
194crate::pac::peripheral_dma_channels! {
195 ($peri:ident, usart, $kind:ident, RX, $channel:ident, $dma_peri:ident, $channel_num:expr, $request:expr) => {
196 impl_dma!($peri, $channel, RxDma, $request);
197 };
198 ($peri:ident, usart, $kind:ident, TX, $channel:ident, $dma_peri:ident, $channel_num:expr, $request:expr) => {
199 impl_dma!($peri, $channel, TxDma, $request);
200 };
201 ($peri:ident, uart, $kind:ident, RX, $channel:ident, $dma_peri:ident, $channel_num:expr, $request:expr) => {
202 impl_dma!($peri, $channel, RxDma, $request);
203 };
204 ($peri:ident, uart, $kind:ident, TX, $channel:ident, $dma_peri:ident, $channel_num:expr, $request:expr) => {
205 impl_dma!($peri, $channel, TxDma, $request);
206 };
207}
208crate::pac::dma_requests! {
209 (usart, $peri:ident, RX, $request:expr) => {
210 impl_dma!($peri, ALL, RxDma, $request);
211 };
212 (usart, $peri:ident, TX, $request:expr) => {
213 impl_dma!($peri, ALL, TxDma, $request);
214 };
215 (uart, $peri:ident, RX, $request:expr) => {
216 impl_dma!($peri, ALL, RxDma, $request);
217 };
218 (uart, $peri:ident, TX, $request:expr) => {
219 impl_dma!($peri, ALL, TxDma, $request);
220 };
221}
diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs
index 169938952..0f39c364b 100644
--- a/embassy-stm32/src/usart/v1.rs
+++ b/embassy-stm32/src/usart/v1.rs
@@ -1,25 +1,31 @@
1use core::future::Future;
1use core::marker::PhantomData; 2use core::marker::PhantomData;
2
3use embassy::util::Unborrow; 3use embassy::util::Unborrow;
4use embassy_extras::unborrow; 4use embassy_extras::unborrow;
5 5use futures::TryFutureExt;
6use crate::pac::usart::{regs, vals};
7 6
8use super::*; 7use super::*;
8use crate::dma::NoDma;
9use crate::pac::usart::{regs, vals};
9 10
10pub struct Uart<'d, T: Instance> { 11pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
11 inner: T, 12 inner: T,
12 phantom: PhantomData<&'d mut T>, 13 phantom: PhantomData<&'d mut T>,
14 tx_dma: TxDma,
15 #[allow(dead_code)]
16 rx_dma: RxDma,
13} 17}
14 18
15impl<'d, T: Instance> Uart<'d, T> { 19impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
16 pub fn new( 20 pub fn new(
17 inner: impl Unborrow<Target = T>, 21 inner: impl Unborrow<Target = T>,
18 rx: impl Unborrow<Target = impl RxPin<T>>, 22 rx: impl Unborrow<Target = impl RxPin<T>>,
19 tx: impl Unborrow<Target = impl TxPin<T>>, 23 tx: impl Unborrow<Target = impl TxPin<T>>,
24 tx_dma: impl Unborrow<Target = TxDma>,
25 rx_dma: impl Unborrow<Target = RxDma>,
20 config: Config, 26 config: Config,
21 ) -> Self { 27 ) -> Self {
22 unborrow!(inner, rx, tx); 28 unborrow!(inner, rx, tx, tx_dma, rx_dma);
23 29
24 T::enable(); 30 T::enable();
25 let pclk_freq = T::frequency(); 31 let pclk_freq = T::frequency();
@@ -53,11 +59,16 @@ impl<'d, T: Instance> Uart<'d, T> {
53 Self { 59 Self {
54 inner, 60 inner,
55 phantom: PhantomData, 61 phantom: PhantomData,
62 tx_dma,
63 rx_dma,
56 } 64 }
57 } 65 }
58 66
59 #[cfg(dma)] 67 async fn write_dma(&mut self, buffer: &[u8]) -> Result<(), Error>
60 pub async fn write_dma(&mut self, ch: &mut impl TxDma<T>, buffer: &[u8]) -> Result<(), Error> { 68 where
69 TxDma: crate::usart::TxDma<T>,
70 {
71 let ch = &mut self.tx_dma;
61 unsafe { 72 unsafe {
62 self.inner.regs().cr3().modify(|reg| { 73 self.inner.regs().cr3().modify(|reg| {
63 reg.set_dmat(true); 74 reg.set_dmat(true);
@@ -65,7 +76,7 @@ impl<'d, T: Instance> Uart<'d, T> {
65 } 76 }
66 let r = self.inner.regs(); 77 let r = self.inner.regs();
67 let dst = r.dr().ptr() as *mut u8; 78 let dst = r.dr().ptr() as *mut u8;
68 ch.transfer(buffer, dst).await; 79 ch.write(ch.request(), buffer, dst).await;
69 Ok(()) 80 Ok(())
70 } 81 }
71 82
@@ -98,7 +109,9 @@ impl<'d, T: Instance> Uart<'d, T> {
98 } 109 }
99} 110}
100 111
101impl<'d, T: Instance> embedded_hal::blocking::serial::Write<u8> for Uart<'d, T> { 112impl<'d, T: Instance, RxDma> embedded_hal::blocking::serial::Write<u8>
113 for Uart<'d, T, NoDma, RxDma>
114{
102 type Error = Error; 115 type Error = Error;
103 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { 116 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
104 unsafe { 117 unsafe {
@@ -118,3 +131,15 @@ impl<'d, T: Instance> embedded_hal::blocking::serial::Write<u8> for Uart<'d, T>
118 Ok(()) 131 Ok(())
119 } 132 }
120} 133}
134
135// rustfmt::skip because intellij removes the 'where' claus on the associated type.
136#[rustfmt::skip]
137impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Write for Uart<'d, T, TxDma, RxDma>
138 where TxDma: crate::usart::TxDma<T>
139{
140 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>>;
141
142 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
143 self.write_dma(buf).map_err(|_| embassy_traits::uart::Error::Other)
144 }
145}
diff --git a/embassy-stm32/src/usart/v2.rs b/embassy-stm32/src/usart/v2.rs
index b958c0a0c..b97e36148 100644
--- a/embassy-stm32/src/usart/v2.rs
+++ b/embassy-stm32/src/usart/v2.rs
@@ -1,21 +1,18 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2use core::future::Future;
3use futures::TryFutureExt;
3use embassy::util::Unborrow; 4use embassy::util::Unborrow;
4use embassy_extras::unborrow; 5use embassy_extras::unborrow;
5 6
6use crate::pac::usart::{regs, vals}; 7use crate::pac::usart::{regs, vals};
7
8use super::*; 8use super::*;
9use core::future::Future; 9use crate::dma::NoDma;
10use futures::TryFutureExt;
11
12use crate::dma_traits::NoDma;
13 10
14#[allow(dead_code)]
15pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> { 11pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> {
16 inner: T, 12 inner: T,
17 phantom: PhantomData<&'d mut T>, 13 phantom: PhantomData<&'d mut T>,
18 tx_dma: TxDma, 14 tx_dma: TxDma,
15 #[allow(dead_code)]
19 rx_dma: RxDma, 16 rx_dma: RxDma,
20} 17}
21 18
@@ -83,7 +80,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
83 } 80 }
84 let r = self.inner.regs(); 81 let r = self.inner.regs();
85 let dst = r.tdr().ptr() as *mut u8; 82 let dst = r.tdr().ptr() as *mut u8;
86 ch.transfer(buffer, dst).await; 83 ch.write(ch.request(), buffer, dst).await;
87 Ok(()) 84 Ok(())
88 } 85 }
89 86
diff --git a/examples/stm32f4/src/bin/spi.rs b/examples/stm32f4/src/bin/spi.rs
index dda0ee4ed..aa48ceed5 100644
--- a/examples/stm32f4/src/bin/spi.rs
+++ b/examples/stm32f4/src/bin/spi.rs
@@ -61,7 +61,7 @@ fn main() -> ! {
61 let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh); 61 let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh);
62 62
63 loop { 63 loop {
64 let mut buf = [0x0A; 4]; 64 let mut buf = [0x0Au8; 4];
65 unwrap!(cs.set_low()); 65 unwrap!(cs.set_low());
66 unwrap!(spi.transfer(&mut buf)); 66 unwrap!(spi.transfer(&mut buf));
67 unwrap!(cs.set_high()); 67 unwrap!(cs.set_high());
diff --git a/examples/stm32f4/src/bin/usart.rs b/examples/stm32f4/src/bin/usart.rs
index 42f154b05..31525036a 100644
--- a/examples/stm32f4/src/bin/usart.rs
+++ b/examples/stm32f4/src/bin/usart.rs
@@ -12,6 +12,7 @@ use cortex_m::prelude::_embedded_hal_blocking_serial_Write;
12use embassy::executor::Executor; 12use embassy::executor::Executor;
13use embassy::time::Clock; 13use embassy::time::Clock;
14use embassy::util::Forever; 14use embassy::util::Forever;
15use embassy_stm32::dma::NoDma;
15use embassy_stm32::usart::{Config, Uart}; 16use embassy_stm32::usart::{Config, Uart};
16use example_common::*; 17use example_common::*;
17 18
@@ -23,7 +24,7 @@ async fn main_task() {
23 let p = embassy_stm32::init(Default::default()); 24 let p = embassy_stm32::init(Default::default());
24 25
25 let config = Config::default(); 26 let config = Config::default();
26 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config); 27 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, NoDma, NoDma, config);
27 28
28 usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap(); 29 usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap();
29 info!("wrote Hello, starting echo"); 30 info!("wrote Hello, starting echo");
diff --git a/examples/stm32f4/src/bin/usart_dma.rs b/examples/stm32f4/src/bin/usart_dma.rs
index 66ca6242b..39e199d58 100644
--- a/examples/stm32f4/src/bin/usart_dma.rs
+++ b/examples/stm32f4/src/bin/usart_dma.rs
@@ -13,26 +13,25 @@ use cortex_m_rt::entry;
13use embassy::executor::Executor; 13use embassy::executor::Executor;
14use embassy::time::Clock; 14use embassy::time::Clock;
15use embassy::util::Forever; 15use embassy::util::Forever;
16use embassy_stm32::dma::NoDma;
16use embassy_stm32::usart::{Config, Uart}; 17use embassy_stm32::usart::{Config, Uart};
18use embassy_traits::uart::Write as _;
17use example_common::*; 19use example_common::*;
18use heapless::String; 20use heapless::String;
19use stm32f4::stm32f429 as pac; 21use stm32f4::stm32f429 as pac;
20 22
21#[embassy::task] 23#[embassy::task]
22async fn main_task() { 24async fn main_task() {
23 let mut p = embassy_stm32::init(Default::default()); 25 let p = embassy_stm32::init(Default::default());
24 26
25 let config = Config::default(); 27 let config = Config::default();
26 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config); 28 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, p.DMA1_3, NoDma, config);
27 29
28 for n in 0u32.. { 30 for n in 0u32.. {
29 let mut s: String<128> = String::new(); 31 let mut s: String<128> = String::new();
30 core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap(); 32 core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap();
31 33
32 usart 34 usart.write(s.as_bytes()).await.unwrap();
33 .write_dma(&mut p.DMA1_3, s.as_bytes())
34 .await
35 .unwrap();
36 info!("wrote DMA"); 35 info!("wrote DMA");
37 } 36 }
38} 37}
diff --git a/examples/stm32l4/src/bin/spi.rs b/examples/stm32l4/src/bin/spi.rs
index 45ccfcebc..7cac01fd4 100644
--- a/examples/stm32l4/src/bin/spi.rs
+++ b/examples/stm32l4/src/bin/spi.rs
@@ -57,7 +57,7 @@ fn main() -> ! {
57 let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh); 57 let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh);
58 58
59 loop { 59 loop {
60 let mut buf = [0x0A; 4]; 60 let mut buf = [0x0Au8; 4];
61 unwrap!(cs.set_low()); 61 unwrap!(cs.set_low());
62 unwrap!(spi.transfer(&mut buf)); 62 unwrap!(spi.transfer(&mut buf));
63 unwrap!(cs.set_high()); 63 unwrap!(cs.set_high());
diff --git a/examples/stm32l4/src/bin/usart.rs b/examples/stm32l4/src/bin/usart.rs
index e9a44f151..f572b1eff 100644
--- a/examples/stm32l4/src/bin/usart.rs
+++ b/examples/stm32l4/src/bin/usart.rs
@@ -13,7 +13,7 @@ use cortex_m_rt::entry;
13use embassy::executor::Executor; 13use embassy::executor::Executor;
14use embassy::time::Clock; 14use embassy::time::Clock;
15use embassy::util::Forever; 15use embassy::util::Forever;
16use embassy_stm32::dma_traits::NoDma; 16use embassy_stm32::dma::NoDma;
17use embassy_stm32::pac; 17use embassy_stm32::pac;
18use embassy_stm32::usart::{Config, Uart}; 18use embassy_stm32::usart::{Config, Uart};
19use example_common::*; 19use example_common::*;
diff --git a/examples/stm32l4/src/bin/usart_dma.rs b/examples/stm32l4/src/bin/usart_dma.rs
index 1eadd3ad4..12857bc78 100644
--- a/examples/stm32l4/src/bin/usart_dma.rs
+++ b/examples/stm32l4/src/bin/usart_dma.rs
@@ -13,7 +13,7 @@ use cortex_m_rt::entry;
13use embassy::executor::Executor; 13use embassy::executor::Executor;
14use embassy::time::Clock; 14use embassy::time::Clock;
15use embassy::util::Forever; 15use embassy::util::Forever;
16use embassy_stm32::dma_traits::NoDma; 16use embassy_stm32::dma::NoDma;
17use embassy_stm32::pac; 17use embassy_stm32::pac;
18use embassy_stm32::usart::{Config, Uart}; 18use embassy_stm32::usart::{Config, Uart};
19use embassy_traits::uart::Write as _; 19use embassy_traits::uart::Write as _;