aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/bdma/mod.rs22
-rw-r--r--embassy-stm32/src/bdma/v1.rs90
-rw-r--r--embassy-stm32/src/dma/mod.rs23
-rw-r--r--embassy-stm32/src/dma/v2.rs1
-rw-r--r--embassy-stm32/src/dma_traits.rs21
-rw-r--r--embassy-stm32/src/dmamux/mod.rs216
-rw-r--r--embassy-stm32/src/lib.rs5
-rw-r--r--embassy-stm32/src/usart/mod.rs7
-rw-r--r--examples/stm32l4/src/bin/usart_dma.rs96
m---------stm32-data0
-rw-r--r--stm32-metapac-gen/src/lib.rs18
11 files changed, 244 insertions, 255 deletions
diff --git a/embassy-stm32/src/bdma/mod.rs b/embassy-stm32/src/bdma/mod.rs
index 1a49f4e1d..ae7e9d238 100644
--- a/embassy-stm32/src/bdma/mod.rs
+++ b/embassy-stm32/src/bdma/mod.rs
@@ -6,25 +6,3 @@ mod _version;
6 6
7#[allow(unused)] 7#[allow(unused)]
8pub use _version::*; 8pub use _version::*;
9
10use core::future::Future;
11
12pub trait WriteDma<T> {
13 type WriteDmaFuture<'a>: Future<Output = ()> + 'a
14 where
15 Self: 'a;
16
17 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
18 where
19 T: 'a;
20}
21
22pub trait ReadDma<T> {
23 type ReadDmaFuture<'a>: Future<Output = ()> + 'a
24 where
25 Self: 'a;
26
27 fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a>
28 where
29 T: 'a;
30}
diff --git a/embassy-stm32/src/bdma/v1.rs b/embassy-stm32/src/bdma/v1.rs
index f81a08768..fd3bf699c 100644
--- a/embassy-stm32/src/bdma/v1.rs
+++ b/embassy-stm32/src/bdma/v1.rs
@@ -6,10 +6,11 @@ use embassy::interrupt::{Interrupt, InterruptExt};
6use embassy::util::{AtomicWaker, OnDrop}; 6use embassy::util::{AtomicWaker, OnDrop};
7use futures::future::poll_fn; 7use futures::future::poll_fn;
8 8
9use super::{ReadDma, WriteDma}; 9use crate::dma_traits::{ReadDma, WriteDma};
10use crate::interrupt; 10use crate::interrupt;
11use crate::pac; 11use crate::pac;
12use crate::pac::bdma::vals; 12use crate::pac::bdma::vals;
13use crate::rcc::sealed::RccPeripheral;
13 14
14const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8; 15const CH_COUNT: usize = pac::peripheral_count!(DMA) * 8;
15const CH_STATUS_NONE: u8 = 0; 16const CH_STATUS_NONE: u8 = 0;
@@ -57,6 +58,9 @@ pub(crate) async unsafe fn transfer_p2m(
57 while regs.cr().read().en() {} 58 while regs.cr().read().en() {}
58 }); 59 });
59 60
61 #[cfg(dmamux)]
62 crate::dmamux::configure_channel(1, 2);
63
60 regs.par().write_value(src as u32); 64 regs.par().write_value(src as u32);
61 regs.mar().write_value(dst.as_mut_ptr() as u32); 65 regs.mar().write_value(dst.as_mut_ptr() as u32);
62 regs.ndtr().write(|w| w.set_ndt(dst.len() as u16)); 66 regs.ndtr().write(|w| w.set_ndt(dst.len() as u16));
@@ -88,6 +92,9 @@ pub(crate) async unsafe fn transfer_m2p(
88 state_number: usize, 92 state_number: usize,
89 src: &[u8], 93 src: &[u8],
90 dst: *mut u8, 94 dst: *mut u8,
95 #[cfg(dmamux)] dmamux_regs: &'static pac::dmamux::Dmamux,
96 #[cfg(dmamux)] dmamux_ch_num: u8,
97 #[cfg(dmamux)] request: u8,
91) { 98) {
92 // ndtr is max 16 bits. 99 // ndtr is max 16 bits.
93 assert!(src.len() <= 0xFFFF); 100 assert!(src.len() <= 0xFFFF);
@@ -105,6 +112,9 @@ pub(crate) async unsafe fn transfer_m2p(
105 while regs.cr().read().en() {} 112 while regs.cr().read().en() {}
106 }); 113 });
107 114
115 #[cfg(dmamux)]
116 crate::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request);
117
108 regs.par().write_value(dst as u32); 118 regs.par().write_value(dst as u32);
109 regs.mar().write_value(src.as_ptr() as u32); 119 regs.mar().write_value(src.as_ptr() as u32);
110 regs.ndtr().write(|w| w.set_ndt(src.len() as u16)); 120 regs.ndtr().write(|w| w.set_ndt(src.len() as u16));
@@ -161,9 +171,10 @@ pub(crate) unsafe fn init() {
161 } 171 }
162 pac::peripherals! { 172 pac::peripherals! {
163 (bdma, DMA1) => { 173 (bdma, DMA1) => {
164 critical_section::with(|_| { 174 //critical_section::with(|_| {
165 pac::RCC.ahbenr().modify(|w| w.set_dmaen(true)); 175 //pac::RCC.ahbenr().modify(|w| w.set_dmaen(true));
166 }); 176 //});
177 crate::peripherals::DMA1::enable();
167 }; 178 };
168 } 179 }
169} 180}
@@ -220,8 +231,10 @@ macro_rules! impl_dma_channel {
220 } 231 }
221 } 232 }
222 233
234 #[cfg(not(dmamux))]
223 impl<T> WriteDma<T> for crate::peripherals::$channel_peri 235 impl<T> WriteDma<T> for crate::peripherals::$channel_peri
224 where 236 where
237 Self: crate::dmamux::sealed::PeripheralChannel<T, crate::dmamux::M2P>,
225 T: 'static, 238 T: 'static,
226 { 239 {
227 type WriteDmaFuture<'a> = impl Future<Output = ()>; 240 type WriteDmaFuture<'a> = impl Future<Output = ()>;
@@ -234,10 +247,47 @@ macro_rules! impl_dma_channel {
234 247
235 let state_num = self.state_num(); 248 let state_num = self.state_num();
236 let regs = self.regs(); 249 let regs = self.regs();
250
237 unsafe { transfer_m2p(regs, state_num, buf, dst) } 251 unsafe { transfer_m2p(regs, state_num, buf, dst) }
238 } 252 }
239 } 253 }
240 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.dma_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
241 impl<T> ReadDma<T> for crate::peripherals::$channel_peri 291 impl<T> ReadDma<T> for crate::peripherals::$channel_peri
242 where 292 where
243 T: 'static, 293 T: 'static,
@@ -292,6 +342,8 @@ pac::interrupts! {
292 342
293#[cfg(usart)] 343#[cfg(usart)]
294use crate::usart; 344use crate::usart;
345
346#[cfg(not(dmamux))]
295pac::peripheral_dma_channels! { 347pac::peripheral_dma_channels! {
296 ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => { 348 ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
297 impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } 349 impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
@@ -302,4 +354,34 @@ pac::peripheral_dma_channels! {
302 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } 354 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
303 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { } 355 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
304 }; 356 };
357
358 ($peri:ident, uart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
359 impl usart::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
360 impl usart::sealed::RxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
361 };
362
363 ($peri:ident, uart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
364 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
365 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
366 };
367}
368
369#[cfg(dmamux)]
370pac::peripherals! {
371 (usart, $peri:ident) => {
372 pac::dma_channels! {
373 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
374 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
375 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
376 };
377 }
378 };
379 (uart, $peri:ident) => {
380 pac::dma_channels! {
381 ($channel_peri:ident, $dma_peri:ident, $channel_num:expr) => {
382 impl usart::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
383 impl usart::sealed::TxDma<crate::peripherals::$peri> for crate::peripherals::$channel_peri { }
384 };
385 }
386 };
305} 387}
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 466cfa033..ed080cd16 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -1,6 +1,5 @@
1#![macro_use] 1#![macro_use]
2 2
3#[cfg(dma)]
4#[cfg_attr(dma_v1, path = "v1.rs")] 3#[cfg_attr(dma_v1, path = "v1.rs")]
5#[cfg_attr(dma_v2, path = "v2.rs")] 4#[cfg_attr(dma_v2, path = "v2.rs")]
6mod _version; 5mod _version;
@@ -8,25 +7,3 @@ mod _version;
8#[cfg(dma)] 7#[cfg(dma)]
9#[allow(unused)] 8#[allow(unused)]
10pub use _version::*; 9pub use _version::*;
11
12use core::future::Future;
13
14pub trait WriteDma<T> {
15 type WriteDmaFuture<'a>: Future<Output = ()> + 'a
16 where
17 Self: 'a;
18
19 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
20 where
21 T: 'a;
22}
23
24pub trait ReadDma<T> {
25 type ReadDmaFuture<'a>: Future<Output = ()> + 'a
26 where
27 Self: 'a;
28
29 fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a>
30 where
31 T: 'a;
32}
diff --git a/embassy-stm32/src/dma/v2.rs b/embassy-stm32/src/dma/v2.rs
index e7cd24710..5080776fb 100644
--- a/embassy-stm32/src/dma/v2.rs
+++ b/embassy-stm32/src/dma/v2.rs
@@ -1,5 +1,6 @@
1use core::task::Poll; 1use core::task::Poll;
2 2
3use crate::dma_traits::{ReadDma, WriteDma};
3use atomic_polyfill::{AtomicU8, Ordering}; 4use atomic_polyfill::{AtomicU8, Ordering};
4use embassy::interrupt::{Interrupt, InterruptExt}; 5use embassy::interrupt::{Interrupt, InterruptExt};
5use embassy::util::AtomicWaker; 6use embassy::util::AtomicWaker;
diff --git a/embassy-stm32/src/dma_traits.rs b/embassy-stm32/src/dma_traits.rs
new file mode 100644
index 000000000..8f1a9f40e
--- /dev/null
+++ b/embassy-stm32/src/dma_traits.rs
@@ -0,0 +1,21 @@
1use core::future::Future;
2
3pub trait WriteDma<T> {
4 type WriteDmaFuture<'a>: Future<Output = ()> + 'a
5 where
6 Self: 'a;
7
8 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
9 where
10 T: 'a;
11}
12
13pub trait ReadDma<T> {
14 type ReadDmaFuture<'a>: Future<Output = ()> + 'a
15 where
16 Self: 'a;
17
18 fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a>
19 where
20 T: 'a;
21}
diff --git a/embassy-stm32/src/dmamux/mod.rs b/embassy-stm32/src/dmamux/mod.rs
index b4d5b9831..745906cdd 100644
--- a/embassy-stm32/src/dmamux/mod.rs
+++ b/embassy-stm32/src/dmamux/mod.rs
@@ -20,41 +20,11 @@ use crate::peripherals;
20 20
21use core::future::Future; 21use core::future::Future;
22 22
23use crate::dma::{ReadDma, WriteDma}; 23use crate::dma_traits::{ReadDma, WriteDma};
24 24
25const CH_COUNT: usize = peripheral_count!(DMA) * 8; 25pub(crate) fn configure_channel(ch_num: u8, request_num: u8) {}
26const CH_STATUS_NONE: u8 = 0;
27const CH_STATUS_COMPLETED: u8 = 1;
28const CH_STATUS_ERROR: u8 = 2;
29
30struct State {
31 ch_wakers: [AtomicWaker; CH_COUNT],
32 ch_status: [AtomicU8; CH_COUNT],
33}
34
35impl State {
36 const fn new() -> Self {
37 const AW: AtomicWaker = AtomicWaker::new();
38 const AU: AtomicU8 = AtomicU8::new(CH_STATUS_NONE);
39 Self {
40 ch_wakers: [AW; CH_COUNT],
41 ch_status: [AU; CH_COUNT],
42 }
43 }
44}
45
46static STATE: State = State::new();
47
48#[allow(unused)]
49pub(crate) async unsafe fn transfer_p2m(
50 ch: &mut impl Channel,
51 ch_func: u8,
52 src: *const u8,
53 dst: &mut [u8],
54) {
55 unimplemented!()
56}
57 26
27/*
58#[allow(unused)] 28#[allow(unused)]
59pub(crate) async unsafe fn transfer_m2p( 29pub(crate) async unsafe fn transfer_m2p(
60 ch: &mut impl Channel, 30 ch: &mut impl Channel,
@@ -128,22 +98,36 @@ pub(crate) async unsafe fn transfer_m2p(
128 // TODO handle error 98 // TODO handle error
129 assert!(res == CH_STATUS_COMPLETED); 99 assert!(res == CH_STATUS_COMPLETED);
130} 100}
101 */
102
103pub(crate) unsafe fn configure_dmamux(
104 dmamux_regs: &pac::dmamux::Dmamux,
105 dmamux_ch_num: u8,
106 request: u8,
107) {
108 let ch_mux_regs = dmamux_regs.ccr(dmamux_ch_num as _);
109 ch_mux_regs.write(|reg| {
110 // one request?
111 reg.set_nbreq(0);
112 reg.set_dmareq_id(request);
113 });
114
115 ch_mux_regs.modify(|reg| {
116 reg.set_ege(true);
117 //reg.set_se(true);
118 //reg.set_soie(true);
119 });
120}
131 121
132pub(crate) mod sealed { 122pub(crate) mod sealed {
133 use super::*; 123 use super::*;
134 124
135 pub trait Bdma {
136 fn regs() -> &'static pac::bdma::Dma;
137 fn num() -> u8;
138 }
139
140 pub trait DmaMux { 125 pub trait DmaMux {
141 fn regs() -> &'static pac::dmamux::Dmamux; 126 fn regs() -> &'static pac::dmamux::Dmamux;
142 } 127 }
143 128
144 pub trait Channel { 129 pub trait Channel {
145 fn num(&self) -> usize; 130 fn num(&self) -> usize;
146 fn regs(&self) -> pac::bdma::Ch;
147 fn dma_regs() -> &'static pac::bdma::Dma; 131 fn dma_regs() -> &'static pac::bdma::Dma;
148 fn dma_ch_num(&self) -> u8; 132 fn dma_ch_num(&self) -> u8;
149 133
@@ -156,7 +140,6 @@ pub(crate) mod sealed {
156 } 140 }
157} 141}
158 142
159pub trait Bdma: sealed::Bdma {}
160pub trait DmaMux: sealed::DmaMux {} 143pub trait DmaMux: sealed::DmaMux {}
161pub trait Channel: sealed::Channel {} 144pub trait Channel: sealed::Channel {}
162pub trait PeripheralChannel<PERI, OP>: sealed::Channel {} 145pub trait PeripheralChannel<PERI, OP>: sealed::Channel {}
@@ -172,10 +155,6 @@ macro_rules! impl_dma_channel {
172 ($dma_num * 8) + $channel_num 155 ($dma_num * 8) + $channel_num
173 } 156 }
174 157
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 { 158 fn dma_regs() -> &'static pac::bdma::Dma {
180 &crate::pac::$dma_peri 159 &crate::pac::$dma_peri
181 } 160 }
@@ -192,42 +171,6 @@ macro_rules! impl_dma_channel {
192 ($dma_num * 8) + $channel_num 171 ($dma_num * 8) + $channel_num
193 } 172 }
194 } 173 }
195
196 impl<T> WriteDma<T> for peripherals::$channel_peri
197 where
198 Self: sealed::PeripheralChannel<T, M2P>,
199 T: 'static,
200 {
201 type WriteDmaFuture<'a> = impl Future<Output = ()>;
202
203 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
204 where
205 T: 'a,
206 {
207 let request = sealed::PeripheralChannel::<T, M2P>::request(self);
208 unsafe { transfer_m2p(self, request, buf, dst) }
209 }
210 }
211
212 impl<T> ReadDma<T> for peripherals::$channel_peri
213 where
214 Self: sealed::PeripheralChannel<T, P2M>,
215 T: 'static,
216 {
217 type ReadDmaFuture<'a> = impl Future<Output = ()>;
218
219 fn transfer<'a>(
220 &'a mut self,
221 src: *const u8,
222 buf: &'a mut [u8],
223 ) -> Self::ReadDmaFuture<'a>
224 where
225 T: 'a,
226 {
227 let request = sealed::PeripheralChannel::<T, P2M>::request(self);
228 unsafe { transfer_p2m(self, request, src, buf) }
229 }
230 }
231 }; 174 };
232} 175}
233 176
@@ -242,25 +185,8 @@ macro_rules! impl_dmamux {
242 }; 185 };
243} 186}
244 187
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
261peripherals! { 188peripherals! {
262 (bdma, DMA1) => { 189 (bdma, DMA1) => {
263 impl_bdma!(DMA1, 0);
264 dma_channels! { 190 dma_channels! {
265 ($channel_peri:ident, DMA1, $channel_num:expr) => { 191 ($channel_peri:ident, DMA1, $channel_num:expr) => {
266 impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA1, 0); 192 impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA1, 0);
@@ -268,7 +194,6 @@ peripherals! {
268 } 194 }
269 }; 195 };
270 (bdma, DMA2) => { 196 (bdma, DMA2) => {
271 impl_bdma!(DMA2, 1);
272 dma_channels! { 197 dma_channels! {
273 ($channel_peri:ident, DMA2, $channel_num:expr) => { 198 ($channel_peri:ident, DMA2, $channel_num:expr) => {
274 impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA2, 1); 199 impl_dma_channel!($channel_peri, DMAMUX1, $channel_num, DMA2, 1);
@@ -285,9 +210,6 @@ macro_rules! impl_usart_dma_requests {
285 dma_requests! { 210 dma_requests! {
286 // TODO: DRY this up. 211 // TODO: DRY this up.
287 (usart, $peri:ident, RX, $request:expr) => { 212 (usart, $peri:ident, RX, $request:expr) => {
288 impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
289 impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
290
291 impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri { 213 impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri {
292 fn request(&self) -> u8 { 214 fn request(&self) -> u8 {
293 $request 215 $request
@@ -299,9 +221,6 @@ macro_rules! impl_usart_dma_requests {
299 }; 221 };
300 222
301 (usart, $peri:ident, TX, $request:expr) => { 223 (usart, $peri:ident, TX, $request:expr) => {
302 impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
303 impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
304
305 impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri { 224 impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri {
306 fn request(&self) -> u8 { 225 fn request(&self) -> u8 {
307 $request 226 $request
@@ -313,9 +232,6 @@ macro_rules! impl_usart_dma_requests {
313 }; 232 };
314 233
315 (uart, $peri:ident, TX, $request:expr) => { 234 (uart, $peri:ident, TX, $request:expr) => {
316 impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
317 impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
318
319 impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri { 235 impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri {
320 fn request(&self) -> u8 { 236 fn request(&self) -> u8 {
321 $request 237 $request
@@ -326,9 +242,6 @@ macro_rules! impl_usart_dma_requests {
326 }; 242 };
327 243
328 (uart, $peri:ident, RX, $request:expr) => { 244 (uart, $peri:ident, RX, $request:expr) => {
329 impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
330 impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
331
332 impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri { 245 impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri {
333 fn request(&self) -> u8 { 246 fn request(&self) -> u8 {
334 $request 247 $request
@@ -351,86 +264,5 @@ dma_channels! {
351 }; 264 };
352} 265}
353 266
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 267/// safety: must be called only once
419pub(crate) unsafe fn init() { 268pub(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 f750c9899..4b2826ae8 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -20,6 +20,9 @@ pub mod gpio;
20pub mod rcc; 20pub mod rcc;
21 21
22// Sometimes-present hardware 22// Sometimes-present hardware
23#[cfg(any(dma, bdma, dmamux))]
24pub mod dma_traits;
25
23#[cfg(adc)] 26#[cfg(adc)]
24pub mod adc; 27pub mod adc;
25#[cfg(bdma)] 28#[cfg(bdma)]
@@ -28,7 +31,7 @@ pub mod bdma;
28pub mod clock; 31pub mod clock;
29#[cfg(dac)] 32#[cfg(dac)]
30pub mod dac; 33pub mod dac;
31#[cfg(any(dma, dmamux))] 34#[cfg(dma)]
32pub mod dma; 35pub mod dma;
33#[cfg(dmamux)] 36#[cfg(dmamux)]
34pub mod dmamux; 37pub mod dmamux;
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 2bab4016f..ddaed5bb9 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -73,11 +73,8 @@ pub enum Error {
73pub(crate) mod sealed { 73pub(crate) mod sealed {
74 use super::*; 74 use super::*;
75 75
76 #[cfg(any(dma, dmamux))] 76 #[cfg(any(dma, bdma, dmamux))]
77 use crate::dma::WriteDma; 77 use crate::dma_traits::WriteDma;
78
79 #[cfg(bdma)]
80 use crate::bdma::WriteDma;
81 78
82 pub trait Instance { 79 pub trait Instance {
83 fn regs(&self) -> crate::pac::usart::Usart; 80 fn regs(&self) -> crate::pac::usart::Usart;
diff --git a/examples/stm32l4/src/bin/usart_dma.rs b/examples/stm32l4/src/bin/usart_dma.rs
new file mode 100644
index 000000000..cc630e0df
--- /dev/null
+++ b/examples/stm32l4/src/bin/usart_dma.rs
@@ -0,0 +1,96 @@
1#![no_std]
2#![no_main]
3#![feature(trait_alias)]
4#![feature(min_type_alias_impl_trait)]
5#![feature(impl_trait_in_bindings)]
6#![feature(type_alias_impl_trait)]
7#![allow(incomplete_features)]
8
9#[path = "../example_common.rs"]
10mod example_common;
11use core::fmt::Write;
12use cortex_m_rt::entry;
13use embassy::executor::Executor;
14use embassy::time::Clock;
15use embassy::util::Forever;
16use embassy_stm32::usart::{Config, Uart};
17use example_common::*;
18use heapless::String;
19use stm32l4::stm32l4x5 as pac;
20
21#[embassy::task]
22async fn main_task() {
23 let mut p = embassy_stm32::init(Default::default());
24
25 let config = Config::default();
26 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, config);
27
28 for n in 0u32.. {
29 let mut s: String<128> = String::new();
30 core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap();
31
32 usart
33 .write_dma(&mut p.DMA1_3, s.as_bytes())
34 .await
35 .unwrap();
36 info!("wrote DMA");
37 }
38}
39
40struct ZeroClock;
41
42impl Clock for ZeroClock {
43 fn now(&self) -> u64 {
44 0
45 }
46}
47
48static EXECUTOR: Forever<Executor> = Forever::new();
49
50#[entry]
51fn main() -> ! {
52 info!("Hello World!");
53
54 let pp = pac::Peripherals::take().unwrap();
55
56 pp.DBGMCU.cr.modify(|_, w| {
57 w.dbg_sleep().set_bit();
58 w.dbg_standby().set_bit();
59 w.dbg_stop().set_bit()
60 });
61
62 pp.RCC.ahb1enr.modify(|_, w| {
63 unsafe {
64 w.bits( 0x07 );
65 }
66 w
67 //w.dmamuxen().set_bit();
68 //w.dma1en().set_bit();
69 //w.dma2en().set_bit();
70 //w
71 });
72
73 pp.RCC.ahb2enr.modify(|_, w| {
74 w.gpioaen().set_bit();
75 w.gpioben().set_bit();
76 w.gpiocen().set_bit();
77 w.gpioden().set_bit();
78 w.gpioeen().set_bit();
79 w.gpiofen().set_bit();
80 w
81 });
82
83 pp.RCC.apb2enr.modify(|_, w| {
84 w.syscfgen().set_bit();
85 w
86 });
87
88
89 unsafe { embassy::time::set_clock(&ZeroClock) };
90
91 let executor = EXECUTOR.put(Executor::new());
92
93 executor.run(|spawner| {
94 unwrap!(spawner.spawn(main_task()));
95 })
96}
diff --git a/stm32-data b/stm32-data
Subproject 409ed5502c254e462f3e31b0ea5ddee95f818a7 Subproject a2167373ee8fd0e75dce003bfdbadda8b32ff77
diff --git a/stm32-metapac-gen/src/lib.rs b/stm32-metapac-gen/src/lib.rs
index 978f70b92..3f6a03fcc 100644
--- a/stm32-metapac-gen/src/lib.rs
+++ b/stm32-metapac-gen/src/lib.rs
@@ -421,14 +421,16 @@ pub fn gen(options: Options) {
421 clock.to_ascii_lowercase() 421 clock.to_ascii_lowercase()
422 }; 422 };
423 423
424 peripheral_rcc_table.push(vec![ 424 if !name.starts_with("GPIO") {
425 name.clone(), 425 peripheral_rcc_table.push(vec![
426 clock, 426 name.clone(),
427 enable_reg.to_ascii_lowercase(), 427 clock,
428 reset_reg.to_ascii_lowercase(), 428 enable_reg.to_ascii_lowercase(),
429 format!("set_{}", enable_field.to_ascii_lowercase()), 429 reset_reg.to_ascii_lowercase(),
430 format!("set_{}", reset_field.to_ascii_lowercase()), 430 format!("set_{}", enable_field.to_ascii_lowercase()),
431 ]); 431 format!("set_{}", reset_field.to_ascii_lowercase()),
432 ]);
433 }
432 } 434 }
433 (None, Some(_)) => { 435 (None, Some(_)) => {
434 print!("Unable to find enable register for {}", name) 436 print!("Unable to find enable register for {}", name)