aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob McWhirter <[email protected]>2021-06-30 10:50:37 -0400
committerGitHub <[email protected]>2021-06-30 10:50:37 -0400
commitda014afb89c73570bdcde4070b94c7e3de6e7446 (patch)
tree378e293c83e2c92615648916d4e0070a29981301
parentd49adc98beebe5b7982204150ebdc0a485fefab2 (diff)
parentf3b9c977630a0a91eb80e730643760db50d22189 (diff)
Merge pull request #253 from bobmcwhirter/dma_tables
Generate dma-related macro tables.
-rw-r--r--embassy-stm32/gen.py13
-rw-r--r--embassy-stm32/src/bdma/mod.rs69
-rw-r--r--embassy-stm32/src/dma/mod.rs67
-rw-r--r--embassy-stm32/src/dma/v2.rs338
-rw-r--r--embassy-stm32/src/rcc/f4/mod.rs4
-rw-r--r--embassy-stm32/src/usart/mod.rs18
-rw-r--r--embassy-stm32/src/usart/v1.rs29
-rw-r--r--examples/stm32f4/src/bin/usart.rs2
-rw-r--r--examples/stm32f4/src/bin/usart_dma.rs4
m---------stm32-data0
-rw-r--r--stm32-metapac/Cargo.toml1
-rw-r--r--stm32-metapac/gen/src/lib.rs124
12 files changed, 472 insertions, 197 deletions
diff --git a/embassy-stm32/gen.py b/embassy-stm32/gen.py
index 386c5ce17..01c778716 100644
--- a/embassy-stm32/gen.py
+++ b/embassy-stm32/gen.py
@@ -73,13 +73,16 @@ with open(output_file, 'w') as f:
73 pins.add(pin) 73 pins.add(pin)
74 singletons.append(pin) 74 singletons.append(pin)
75 75
76 if block_mod == 'dma': 76 # if block_mod == 'dma':
77 custom_singletons = True 77 # custom_singletons = True
78 for ch_num in range(8): 78 # for ch_num in range(8):
79 channel = f'{name}_CH{ch_num}' 79 # channel = f'{name}_CH{ch_num}'
80 singletons.append(channel) 80 # singletons.append(channel)
81 81
82 if not custom_singletons: 82 if not custom_singletons:
83 singletons.append(name) 83 singletons.append(name)
84 84
85 for (channel_id, defn) in core['dma_channels'].items():
86 singletons.append( channel_id )
87
85 f.write(f"embassy_extras::peripherals!({','.join(singletons)});") 88 f.write(f"embassy_extras::peripherals!({','.join(singletons)});")
diff --git a/embassy-stm32/src/bdma/mod.rs b/embassy-stm32/src/bdma/mod.rs
new file mode 100644
index 000000000..e85ade5df
--- /dev/null
+++ b/embassy-stm32/src/bdma/mod.rs
@@ -0,0 +1,69 @@
1#![macro_use]
2
3#[cfg_attr(bdma_v1, path = "v1.rs")]
4#[cfg_attr(bdma_v2, path = "v2.rs")]
5mod _version;
6
7#[allow(unused)]
8pub use _version::*;
9
10use crate::pac;
11use crate::peripherals;
12
13pub(crate) mod sealed {
14 use super::*;
15
16 pub trait Channel {
17 fn num(&self) -> u8;
18
19 fn dma_num(&self) -> u8 {
20 self.num() / 8
21 }
22 fn ch_num(&self) -> u8 {
23 self.num() % 8
24 }
25 fn regs(&self) -> pac::dma::Dma {
26 pac::DMA(self.num() as _)
27 }
28 }
29}
30
31pub trait Channel: sealed::Channel + Sized {}
32
33macro_rules! impl_dma_channel {
34 ($channel_peri:ident, $dma_num:expr, $ch_num:expr) => {
35 impl Channel for peripherals::$channel_peri {}
36 impl sealed::Channel for peripherals::$channel_peri {
37 #[inline]
38 fn num(&self) -> u8 {
39 $dma_num * 8 + $ch_num
40 }
41 }
42 };
43}
44
45/*
46crate::pac::peripherals!(
47 (dma,DMA1) => {
48 impl_dma_channel!(DMA1_CH0, 0, 0);
49 impl_dma_channel!(DMA1_CH1, 0, 1);
50 impl_dma_channel!(DMA1_CH2, 0, 2);
51 impl_dma_channel!(DMA1_CH3, 0, 3);
52 impl_dma_channel!(DMA1_CH4, 0, 4);
53 impl_dma_channel!(DMA1_CH5, 0, 5);
54 impl_dma_channel!(DMA1_CH6, 0, 6);
55 impl_dma_channel!(DMA1_CH7, 0, 7);
56 };
57
58 (dma,DMA2) => {
59 impl_dma_channel!(DMA2_CH0, 1, 0);
60 impl_dma_channel!(DMA2_CH1, 1, 1);
61 impl_dma_channel!(DMA2_CH2, 1, 2);
62 impl_dma_channel!(DMA2_CH3, 1, 3);
63 impl_dma_channel!(DMA2_CH4, 1, 4);
64 impl_dma_channel!(DMA2_CH5, 1, 5);
65 impl_dma_channel!(DMA2_CH6, 1, 6);
66 impl_dma_channel!(DMA2_CH7, 1, 7);
67 };
68);
69 */
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs
index 773cdc8b8..371741ffd 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -7,61 +7,24 @@ mod _version;
7#[allow(unused)] 7#[allow(unused)]
8pub use _version::*; 8pub use _version::*;
9 9
10use crate::pac; 10use core::future::Future;
11use crate::peripherals;
12 11
13pub(crate) mod sealed { 12pub trait WriteDma<T> {
14 use super::*; 13 type WriteDmaFuture<'a>: Future<Output = ()> + 'a
14 where
15 Self: 'a;
15 16
16 pub trait Channel { 17 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
17 fn num(&self) -> u8; 18 where
18 19 T: 'a;
19 fn dma_num(&self) -> u8 {
20 self.num() / 8
21 }
22 fn ch_num(&self) -> u8 {
23 self.num() % 8
24 }
25 fn regs(&self) -> pac::dma::Dma {
26 pac::DMA(self.num() as _)
27 }
28 }
29} 20}
30 21
31pub trait Channel: sealed::Channel + Sized {} 22pub trait ReadDma<T> {
23 type ReadDmaFuture<'a>: Future<Output = ()> + 'a
24 where
25 Self: 'a;
32 26
33macro_rules! impl_dma_channel { 27 fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a>
34 ($type:ident, $dma_num:expr, $ch_num:expr) => { 28 where
35 impl Channel for peripherals::$type {} 29 T: 'a;
36 impl sealed::Channel for peripherals::$type {
37 #[inline]
38 fn num(&self) -> u8 {
39 $dma_num * 8 + $ch_num
40 }
41 }
42 };
43} 30}
44
45crate::pac::peripherals!(
46 (dma,DMA1) => {
47 impl_dma_channel!(DMA1_CH0, 0, 0);
48 impl_dma_channel!(DMA1_CH1, 0, 1);
49 impl_dma_channel!(DMA1_CH2, 0, 2);
50 impl_dma_channel!(DMA1_CH3, 0, 3);
51 impl_dma_channel!(DMA1_CH4, 0, 4);
52 impl_dma_channel!(DMA1_CH5, 0, 5);
53 impl_dma_channel!(DMA1_CH6, 0, 6);
54 impl_dma_channel!(DMA1_CH7, 0, 7);
55 };
56
57 (dma,DMA2) => {
58 impl_dma_channel!(DMA2_CH0, 1, 0);
59 impl_dma_channel!(DMA2_CH1, 1, 1);
60 impl_dma_channel!(DMA2_CH2, 1, 2);
61 impl_dma_channel!(DMA2_CH3, 1, 3);
62 impl_dma_channel!(DMA2_CH4, 1, 4);
63 impl_dma_channel!(DMA2_CH5, 1, 5);
64 impl_dma_channel!(DMA2_CH6, 1, 6);
65 impl_dma_channel!(DMA2_CH7, 1, 7);
66 };
67);
diff --git a/embassy-stm32/src/dma/v2.rs b/embassy-stm32/src/dma/v2.rs
index e7bd69130..93b3cb869 100644
--- a/embassy-stm32/src/dma/v2.rs
+++ b/embassy-stm32/src/dma/v2.rs
@@ -9,9 +9,14 @@ use crate::interrupt;
9use crate::pac; 9use crate::pac;
10use crate::pac::dma::{regs, vals}; 10use crate::pac::dma::{regs, vals};
11 11
12const DMAS: [pac::dma::Dma; 2] = [pac::DMA1, pac::DMA2]; 12use crate::pac::dma_channels;
13use crate::pac::interrupts;
14use crate::pac::peripheral_count;
15use crate::pac::peripheral_dma_channels;
16use crate::pac::peripherals;
17use crate::peripherals;
13 18
14const CH_COUNT: usize = 16; 19const CH_COUNT: usize = peripheral_count!(DMA) * 8;
15const CH_STATUS_NONE: u8 = 0; 20const CH_STATUS_NONE: u8 = 0;
16const CH_STATUS_COMPLETED: u8 = 1; 21const CH_STATUS_COMPLETED: u8 = 1;
17const CH_STATUS_ERROR: u8 = 2; 22const CH_STATUS_ERROR: u8 = 2;
@@ -35,15 +40,60 @@ impl State {
35static STATE: State = State::new(); 40static STATE: State = State::new();
36 41
37#[allow(unused)] // Used by usart/v1.rs which may or may not be enabled 42#[allow(unused)] // Used by usart/v1.rs which may or may not be enabled
43pub(crate) async unsafe fn transfer_p2m(
44 ch: &mut impl Channel,
45 ch_func: u8,
46 src: *const u8,
47 dst: &mut [u8],
48) {
49 let n = ch.num();
50 let c = ch.regs();
51
52 // ndtr is max 16 bits.
53 assert!(dst.len() <= 0xFFFF);
54
55 // Reset status
56 STATE.ch_status[n].store(CH_STATUS_NONE, Ordering::Relaxed);
57
58 unsafe {
59 c.par().write_value(src as _);
60 c.m0ar().write_value(dst.as_ptr() as _);
61 c.ndtr().write_value(regs::Ndtr(dst.len() as _));
62 c.cr().write(|w| {
63 w.set_dir(vals::Dir::PERIPHERALTOMEMORY);
64 w.set_msize(vals::Size::BITS8);
65 w.set_psize(vals::Size::BITS8);
66 w.set_minc(vals::Inc::INCREMENTED);
67 w.set_pinc(vals::Inc::FIXED);
68 w.set_chsel(ch_func);
69 w.set_teie(true);
70 w.set_tcie(true);
71 w.set_en(true);
72 });
73 }
74
75 let res = poll_fn(|cx| {
76 STATE.ch_wakers[n].register(cx.waker());
77 match STATE.ch_status[n].load(Ordering::Acquire) {
78 CH_STATUS_NONE => Poll::Pending,
79 x => Poll::Ready(x),
80 }
81 })
82 .await;
83
84 // TODO handle error
85 assert!(res == CH_STATUS_COMPLETED);
86}
87
88#[allow(unused)] // Used by usart/v1.rs which may or may not be enabled
38pub(crate) async unsafe fn transfer_m2p( 89pub(crate) async unsafe fn transfer_m2p(
39 ch: &mut impl Channel, 90 ch: &mut impl Channel,
40 ch_func: u8, 91 ch_func: u8,
41 src: &[u8], 92 src: &[u8],
42 dst: *mut u8, 93 dst: *mut u8,
43) { 94) {
44 let n = ch.num() as usize; 95 let n = ch.num();
45 let r = ch.regs(); 96 let c = ch.regs();
46 let c = r.st(ch.ch_num() as _);
47 97
48 // ndtr is max 16 bits. 98 // ndtr is max 16 bits.
49 assert!(src.len() <= 0xFFFF); 99 assert!(src.len() <= 0xFFFF);
@@ -55,6 +105,7 @@ pub(crate) async unsafe fn transfer_m2p(
55 c.par().write_value(dst as _); 105 c.par().write_value(dst as _);
56 c.m0ar().write_value(src.as_ptr() as _); 106 c.m0ar().write_value(src.as_ptr() as _);
57 c.ndtr().write_value(regs::Ndtr(src.len() as _)); 107 c.ndtr().write_value(regs::Ndtr(src.len() as _));
108 compiler_fence(Ordering::AcqRel);
58 c.cr().write(|w| { 109 c.cr().write(|w| {
59 w.set_dir(vals::Dir::MEMORYTOPERIPHERAL); 110 w.set_dir(vals::Dir::MEMORYTOPERIPHERAL);
60 w.set_msize(vals::Size::BITS8); 111 w.set_msize(vals::Size::BITS8);
@@ -70,118 +121,211 @@ pub(crate) async unsafe fn transfer_m2p(
70 121
71 let res = poll_fn(|cx| { 122 let res = poll_fn(|cx| {
72 STATE.ch_wakers[n].register(cx.waker()); 123 STATE.ch_wakers[n].register(cx.waker());
73 match STATE.ch_status[n].load(Ordering::Relaxed) { 124 match STATE.ch_status[n].load(Ordering::Acquire) {
74 CH_STATUS_NONE => Poll::Pending, 125 CH_STATUS_NONE => {
126 let left = c.ndtr().read().ndt();
127 Poll::Pending
128 }
75 x => Poll::Ready(x), 129 x => Poll::Ready(x),
76 } 130 }
77 }) 131 })
78 .await; 132 .await;
79 133
134 compiler_fence(Ordering::AcqRel);
135
80 // TODO handle error 136 // TODO handle error
81 assert!(res == CH_STATUS_COMPLETED); 137 assert!(res == CH_STATUS_COMPLETED);
82} 138}
83 139
84unsafe fn on_irq() { 140unsafe fn on_irq() {
85 for (dman, &dma) in DMAS.iter().enumerate() { 141 peripherals! {
86 for isrn in 0..2 { 142 (dma, $dma:ident) => {
87 let isr = dma.isr(isrn).read(); 143 for isrn in 0..2 {
88 dma.ifcr(isrn).write_value(isr); 144 let isr = pac::$dma.isr(isrn).read();
89 145 pac::$dma.ifcr(isrn).write_value(isr);
90 for chn in 0..4 { 146 let dman = <peripherals::$dma as sealed::Dma>::num() as usize;
91 let n = dman * 8 + isrn * 4 + chn; 147
92 if isr.teif(chn) { 148 for chn in 0..4 {
93 STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed); 149 let n = dman * 8 + isrn * 4 + chn;
94 STATE.ch_wakers[n].wake(); 150 if isr.teif(chn) {
95 } else if isr.tcif(chn) { 151 STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Release);
96 STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed); 152 STATE.ch_wakers[n].wake();
97 STATE.ch_wakers[n].wake(); 153 } else if isr.tcif(chn) {
154 STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Release);
155 STATE.ch_wakers[n].wake();
156 }
98 } 157 }
99 } 158 }
100 } 159 };
101 } 160 }
102} 161}
103 162
104#[interrupt] 163/// safety: must be called only once
105unsafe fn DMA1_STREAM0() { 164pub(crate) unsafe fn init() {
106 on_irq() 165 interrupts! {
107} 166 (DMA, $irq:ident) => {
108#[interrupt] 167 interrupt::$irq::steal().enable();
109unsafe fn DMA1_STREAM1() { 168 };
110 on_irq() 169 }
111}
112#[interrupt]
113unsafe fn DMA1_STREAM2() {
114 on_irq()
115}
116#[interrupt]
117unsafe fn DMA1_STREAM3() {
118 on_irq()
119}
120#[interrupt]
121unsafe fn DMA1_STREAM4() {
122 on_irq()
123}
124#[interrupt]
125unsafe fn DMA1_STREAM5() {
126 on_irq()
127}
128#[interrupt]
129unsafe fn DMA1_STREAM6() {
130 on_irq()
131}
132#[interrupt]
133unsafe fn DMA1_STREAM7() {
134 on_irq()
135}
136#[interrupt]
137unsafe fn DMA2_STREAM0() {
138 on_irq()
139}
140#[interrupt]
141unsafe fn DMA2_STREAM1() {
142 on_irq()
143}
144#[interrupt]
145unsafe fn DMA2_STREAM2() {
146 on_irq()
147} 170}
148#[interrupt] 171
149unsafe fn DMA2_STREAM3() { 172pub(crate) mod sealed {
150 on_irq() 173 use super::*;
174
175 pub trait Dma {
176 fn num() -> u8;
177 fn regs() -> &'static pac::dma::Dma;
178 }
179
180 pub trait Channel {
181 fn dma_regs() -> &'static pac::dma::Dma;
182
183 fn num(&self) -> usize;
184
185 fn ch_num(&self) -> u8;
186
187 fn regs(&self) -> pac::dma::St {
188 Self::dma_regs().st(self.ch_num() as _)
189 }
190 }
191
192 pub trait PeripheralChannel<PERI, OP>: Channel {
193 fn request(&self) -> u8;
194 }
151} 195}
152#[interrupt] 196
153unsafe fn DMA2_STREAM4() { 197pub trait Dma: sealed::Dma + Sized {}
154 on_irq() 198pub trait Channel: sealed::Channel + Sized {}
199pub trait PeripheralChannel<PERI, OP>: sealed::PeripheralChannel<PERI, OP> + Sized {}
200
201macro_rules! impl_dma {
202 ($peri:ident, $num:expr) => {
203 impl Dma for peripherals::$peri {}
204 impl sealed::Dma for peripherals::$peri {
205 fn num() -> u8 {
206 $num
207 }
208 fn regs() -> &'static pac::dma::Dma {
209 &pac::$peri
210 }
211 }
212 };
155} 213}
156#[interrupt] 214
157unsafe fn DMA2_STREAM5() { 215macro_rules! impl_dma_channel {
158 on_irq() 216 ($channel_peri:ident, $dma_peri:ident, $dma_num:expr, $ch_num:expr) => {
217 impl Channel for peripherals::$channel_peri {}
218 impl sealed::Channel for peripherals::$channel_peri {
219 #[inline]
220 fn dma_regs() -> &'static pac::dma::Dma {
221 &crate::pac::$dma_peri
222 }
223
224 fn num(&self) -> usize {
225 ($dma_num * 8) + $ch_num
226 }
227
228 fn ch_num(&self) -> u8 {
229 $ch_num
230 }
231 }
232
233 impl<T> WriteDma<T> for peripherals::$channel_peri
234 where
235 Self: sealed::PeripheralChannel<T, M2P>,
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 let request = sealed::PeripheralChannel::<T, M2P>::request(self);
245 unsafe { transfer_m2p(self, request, buf, dst) }
246 }
247 }
248
249 impl<T> ReadDma<T> for peripherals::$channel_peri
250 where
251 Self: sealed::PeripheralChannel<T, P2M>,
252 T: 'static,
253 {
254 type ReadDmaFuture<'a> = impl Future<Output = ()>;
255
256 fn transfer<'a>(
257 &'a mut self,
258 src: *const u8,
259 buf: &'a mut [u8],
260 ) -> Self::ReadDmaFuture<'a>
261 where
262 T: 'a,
263 {
264 let request = sealed::PeripheralChannel::<T, P2M>::request(self);
265 unsafe { transfer_p2m(self, request, src, buf) }
266 }
267 }
268 };
159} 269}
160#[interrupt] 270
161unsafe fn DMA2_STREAM6() { 271peripherals! {
162 on_irq() 272 (dma, DMA1) => {
273 impl_dma!(DMA1, 0);
274 dma_channels! {
275 ($channel_peri:ident, DMA1, $channel_num:expr) => {
276 impl_dma_channel!($channel_peri, DMA1, 0, $channel_num);
277 };
278 }
279 };
280 (dma, DMA2) => {
281 impl_dma!(DMA2, 1);
282 dma_channels! {
283 ($channel_peri:ident, DMA2, $channel_num:expr) => {
284 impl_dma_channel!($channel_peri, DMA2, 1, $channel_num);
285 };
286 }
287 };
163} 288}
164#[interrupt] 289
165unsafe fn DMA2_STREAM7() { 290interrupts! {
166 on_irq() 291 (DMA, $irq:ident) => {
292 #[crate::interrupt]
293 unsafe fn $irq () {
294 on_irq()
295 }
296 };
167} 297}
168 298
169/// safety: must be called only once 299pub struct P2M;
170pub(crate) unsafe fn init() { 300pub struct M2P;
171 interrupt::DMA1_STREAM0::steal().enable(); 301
172 interrupt::DMA1_STREAM1::steal().enable(); 302#[cfg(usart)]
173 interrupt::DMA1_STREAM2::steal().enable(); 303use crate::usart;
174 interrupt::DMA1_STREAM3::steal().enable(); 304use atomic_polyfill::compiler_fence;
175 interrupt::DMA1_STREAM4::steal().enable(); 305peripheral_dma_channels! {
176 interrupt::DMA1_STREAM5::steal().enable(); 306 ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => {
177 interrupt::DMA1_STREAM6::steal().enable(); 307 impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
178 interrupt::DMA1_STREAM7::steal().enable(); 308 impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
179 interrupt::DMA2_STREAM0::steal().enable(); 309
180 interrupt::DMA2_STREAM1::steal().enable(); 310 impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri {
181 interrupt::DMA2_STREAM2::steal().enable(); 311 fn request(&self) -> u8 {
182 interrupt::DMA2_STREAM3::steal().enable(); 312 $event_num
183 interrupt::DMA2_STREAM4::steal().enable(); 313 }
184 interrupt::DMA2_STREAM5::steal().enable(); 314 }
185 interrupt::DMA2_STREAM6::steal().enable(); 315
186 interrupt::DMA2_STREAM7::steal().enable(); 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 };
187} 331}
diff --git a/embassy-stm32/src/rcc/f4/mod.rs b/embassy-stm32/src/rcc/f4/mod.rs
index 4b17bdf40..6000192b9 100644
--- a/embassy-stm32/src/rcc/f4/mod.rs
+++ b/embassy-stm32/src/rcc/f4/mod.rs
@@ -132,7 +132,7 @@ impl RccExt for RCC {
132 ClockSrc::HSI16 => { 132 ClockSrc::HSI16 => {
133 // Enable HSI16 133 // Enable HSI16
134 unsafe { 134 unsafe {
135 rcc.cr().write(|w| w.set_hsion(true)); 135 rcc.cr().modify(|w| w.set_hsion(true));
136 while !rcc.cr().read().hsirdy() {} 136 while !rcc.cr().read().hsirdy() {}
137 } 137 }
138 138
@@ -141,7 +141,7 @@ impl RccExt for RCC {
141 ClockSrc::HSE(freq) => { 141 ClockSrc::HSE(freq) => {
142 // Enable HSE 142 // Enable HSE
143 unsafe { 143 unsafe {
144 rcc.cr().write(|w| w.set_hseon(true)); 144 rcc.cr().modify(|w| w.set_hseon(true));
145 while !rcc.cr().read().hserdy() {} 145 while !rcc.cr().read().hserdy() {}
146 } 146 }
147 147
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index adf48c326..a75793f84 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -8,6 +8,7 @@ pub use _version::*;
8 8
9use crate::gpio::Pin; 9use crate::gpio::Pin;
10use crate::pac::usart::Usart; 10use crate::pac::usart::Usart;
11use crate::rcc::RccPeripheral;
11 12
12/// Serial error 13/// Serial error
13#[derive(Debug, Eq, PartialEq, Copy, Clone)] 14#[derive(Debug, Eq, PartialEq, Copy, Clone)]
@@ -26,6 +27,9 @@ pub enum Error {
26pub(crate) mod sealed { 27pub(crate) mod sealed {
27 use super::*; 28 use super::*;
28 29
30 #[cfg(dma)]
31 use crate::dma::WriteDma;
32
29 pub trait Instance { 33 pub trait Instance {
30 fn regs(&self) -> Usart; 34 fn regs(&self) -> Usart;
31 } 35 }
@@ -44,14 +48,26 @@ pub(crate) mod sealed {
44 pub trait CkPin<T: Instance>: Pin { 48 pub trait CkPin<T: Instance>: Pin {
45 fn af_num(&self) -> u8; 49 fn af_num(&self) -> u8;
46 } 50 }
51
52 #[cfg(dma)]
53 pub trait RxDma<T: Instance> {}
54
55 #[cfg(dma)]
56 pub trait TxDma<T: Instance>: WriteDma<T> {}
47} 57}
48pub trait Instance: sealed::Instance {} 58
59pub trait Instance: sealed::Instance + RccPeripheral {}
49pub trait RxPin<T: Instance>: sealed::RxPin<T> {} 60pub trait RxPin<T: Instance>: sealed::RxPin<T> {}
50pub trait TxPin<T: Instance>: sealed::TxPin<T> {} 61pub trait TxPin<T: Instance>: sealed::TxPin<T> {}
51pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {} 62pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {}
52pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {} 63pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {}
53pub trait CkPin<T: Instance>: sealed::CkPin<T> {} 64pub trait CkPin<T: Instance>: sealed::CkPin<T> {}
54 65
66#[cfg(dma)]
67pub trait RxDma<T: Instance>: sealed::RxDma<T> {}
68#[cfg(dma)]
69pub trait TxDma<T: Instance>: sealed::TxDma<T> {}
70
55crate::pac::peripherals!( 71crate::pac::peripherals!(
56 (usart, $inst:ident) => { 72 (usart, $inst:ident) => {
57 impl sealed::Instance for peripherals::$inst { 73 impl sealed::Instance for peripherals::$inst {
diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs
index 1ec1f5b30..6c5a12441 100644
--- a/embassy-stm32/src/usart/v1.rs
+++ b/embassy-stm32/src/usart/v1.rs
@@ -63,14 +63,14 @@ impl<'d, T: Instance> Uart<'d, T> {
63 rx: impl Unborrow<Target = impl RxPin<T>>, 63 rx: impl Unborrow<Target = impl RxPin<T>>,
64 tx: impl Unborrow<Target = impl TxPin<T>>, 64 tx: impl Unborrow<Target = impl TxPin<T>>,
65 config: Config, 65 config: Config,
66 pclk_freq: u32,
67 ) -> Self { 66 ) -> Self {
68 unborrow!(inner, rx, tx); 67 unborrow!(inner, rx, tx);
69 68
70 // TODO: enable in RCC 69 T::enable();
70 let pclk_freq = T::frequency();
71 71
72 // TODO: better calculation, including error checking and OVER8 if possible. 72 // TODO: better calculation, including error checking and OVER8 if possible.
73 let div = (pclk_freq + (config.baudrate / 2)) / config.baudrate; 73 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate;
74 74
75 let r = inner.regs(); 75 let r = inner.regs();
76 76
@@ -101,25 +101,16 @@ impl<'d, T: Instance> Uart<'d, T> {
101 } 101 }
102 } 102 }
103 103
104 #[cfg(dma_v2)] 104 #[cfg(dma)]
105 pub async fn write_dma( 105 pub async fn write_dma(&mut self, ch: &mut impl TxDma<T>, buffer: &[u8]) -> Result<(), Error> {
106 &mut self,
107 ch: &mut impl crate::dma::Channel,
108 buffer: &[u8],
109 ) -> Result<(), Error> {
110 let ch_func = 4; // USART3_TX
111 let r = self.inner.regs();
112
113 unsafe { 106 unsafe {
114 r.cr3().write(|w| { 107 self.inner.regs().cr3().modify(|reg| {
115 w.set_dmat(true); 108 reg.set_dmat(true);
116 }); 109 });
117
118 let dst = r.dr().ptr() as *mut u8;
119
120 crate::dma::transfer_m2p(ch, ch_func, buffer, dst).await;
121 } 110 }
122 111 let r = self.inner.regs();
112 let dst = r.dr().ptr() as *mut u8;
113 ch.transfer(buffer, dst).await;
123 Ok(()) 114 Ok(())
124 } 115 }
125 116
diff --git a/examples/stm32f4/src/bin/usart.rs b/examples/stm32f4/src/bin/usart.rs
index f7b66f86b..42f154b05 100644
--- a/examples/stm32f4/src/bin/usart.rs
+++ b/examples/stm32f4/src/bin/usart.rs
@@ -23,7 +23,7 @@ async fn main_task() {
23 let p = embassy_stm32::init(Default::default()); 23 let p = embassy_stm32::init(Default::default());
24 24
25 let config = Config::default(); 25 let config = Config::default();
26 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); 26 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config);
27 27
28 usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap(); 28 usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap();
29 info!("wrote Hello, starting echo"); 29 info!("wrote Hello, starting echo");
diff --git a/examples/stm32f4/src/bin/usart_dma.rs b/examples/stm32f4/src/bin/usart_dma.rs
index fae05b607..66ca6242b 100644
--- a/examples/stm32f4/src/bin/usart_dma.rs
+++ b/examples/stm32f4/src/bin/usart_dma.rs
@@ -23,14 +23,14 @@ async fn main_task() {
23 let mut p = embassy_stm32::init(Default::default()); 23 let mut p = embassy_stm32::init(Default::default());
24 24
25 let config = Config::default(); 25 let config = Config::default();
26 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); 26 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config);
27 27
28 for n in 0u32.. { 28 for n in 0u32.. {
29 let mut s: String<128> = String::new(); 29 let mut s: String<128> = String::new();
30 core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap(); 30 core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap();
31 31
32 usart 32 usart
33 .write_dma(&mut p.DMA1_CH3, s.as_bytes()) 33 .write_dma(&mut p.DMA1_3, s.as_bytes())
34 .await 34 .await
35 .unwrap(); 35 .unwrap();
36 info!("wrote DMA"); 36 info!("wrote DMA");
diff --git a/stm32-data b/stm32-data
Subproject eb76ee900ac67b51497196572250323e82666b4 Subproject 9856b11172ae27ffa60d339ac271d2d06c19075
diff --git a/stm32-metapac/Cargo.toml b/stm32-metapac/Cargo.toml
index bed772c81..79f1c3746 100644
--- a/stm32-metapac/Cargo.toml
+++ b/stm32-metapac/Cargo.toml
@@ -12,6 +12,7 @@ cortex-m-rt = { version = "0.6.8", optional = true }
12# These are removed when generating the pre-generated crate using the tool at gen/. 12# These are removed when generating the pre-generated crate using the tool at gen/.
13[build-dependencies] 13[build-dependencies]
14stm32-metapac-gen = { path = "./gen" } 14stm32-metapac-gen = { path = "./gen" }
15regex = "1.5.4"
15# END BUILD DEPENDENCIES 16# END BUILD DEPENDENCIES
16 17
17[features] 18[features]
diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs
index 9e7add452..a552c8cea 100644
--- a/stm32-metapac/gen/src/lib.rs
+++ b/stm32-metapac/gen/src/lib.rs
@@ -27,6 +27,7 @@ pub struct Core {
27 pub name: String, 27 pub name: String,
28 pub peripherals: HashMap<String, Peripheral>, 28 pub peripherals: HashMap<String, Peripheral>,
29 pub interrupts: HashMap<String, u32>, 29 pub interrupts: HashMap<String, u32>,
30 pub dma_channels: HashMap<String, DmaChannel>,
30} 31}
31 32
32#[derive(Debug, Eq, PartialEq, Clone, Deserialize)] 33#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
@@ -46,6 +47,10 @@ pub struct Peripheral {
46 pub clock: Option<String>, 47 pub clock: Option<String>,
47 #[serde(default)] 48 #[serde(default)]
48 pub pins: Vec<Pin>, 49 pub pins: Vec<Pin>,
50 #[serde(default)]
51 pub dma_channels: HashMap<String, Vec<PeripheralDmaChannel>>,
52 #[serde(default)]
53 pub dma_requests: HashMap<String, u32>,
49} 54}
50 55
51#[derive(Debug, Eq, PartialEq, Clone, Deserialize)] 56#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
@@ -55,6 +60,18 @@ pub struct Pin {
55 pub af: Option<String>, 60 pub af: Option<String>,
56} 61}
57 62
63#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
64pub struct DmaChannel {
65 pub dma: String,
66 pub channel: u32,
67}
68
69#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Hash)]
70pub struct PeripheralDmaChannel {
71 pub channel: String,
72 pub request: Option<u32>,
73}
74
58struct BlockInfo { 75struct BlockInfo {
59 /// usart_v1/USART -> usart 76 /// usart_v1/USART -> usart
60 module: String, 77 module: String,
@@ -110,6 +127,21 @@ fn find_reg_for_field<'c>(
110 }) 127 })
111} 128}
112 129
130fn make_peripheral_counts(out: &mut String, data: &HashMap<String, u8>) {
131 write!(out,
132 "#[macro_export]
133macro_rules! peripheral_count {{
134 ").unwrap();
135 for (name, count) in data {
136 write!(out,
137 "({}) => ({});\n",
138 name, count,
139 ).unwrap();
140 }
141 write!(out,
142 " }}\n").unwrap();
143}
144
113fn make_table(out: &mut String, name: &str, data: &Vec<Vec<String>>) { 145fn make_table(out: &mut String, name: &str, data: &Vec<Vec<String>>) {
114 write!( 146 write!(
115 out, 147 out,
@@ -123,7 +155,7 @@ macro_rules! {} {{
123", 155",
124 name, name 156 name, name
125 ) 157 )
126 .unwrap(); 158 .unwrap();
127 159
128 for row in data { 160 for row in data {
129 write!(out, " __{}_inner!(({}));\n", name, row.join(",")).unwrap(); 161 write!(out, " __{}_inner!(({}));\n", name, row.join(",")).unwrap();
@@ -134,7 +166,7 @@ macro_rules! {} {{
134 " }}; 166 " }};
135}}" 167}}"
136 ) 168 )
137 .unwrap(); 169 .unwrap();
138} 170}
139 171
140pub struct Options { 172pub struct Options {
@@ -220,6 +252,10 @@ pub fn gen(options: Options) {
220 let mut peripherals_table: Vec<Vec<String>> = Vec::new(); 252 let mut peripherals_table: Vec<Vec<String>> = Vec::new();
221 let mut peripheral_pins_table: Vec<Vec<String>> = Vec::new(); 253 let mut peripheral_pins_table: Vec<Vec<String>> = Vec::new();
222 let mut peripheral_rcc_table: Vec<Vec<String>> = Vec::new(); 254 let mut peripheral_rcc_table: Vec<Vec<String>> = Vec::new();
255 let mut dma_channels_table: Vec<Vec<String>> = Vec::new();
256 let mut dma_requests_table: Vec<Vec<String>> = Vec::new();
257 let mut peripheral_dma_channels_table: Vec<Vec<String>> = Vec::new();
258 let mut peripheral_counts: HashMap<String, u8> = HashMap::new();
223 259
224 let dma_base = core 260 let dma_base = core
225 .peripherals 261 .peripherals
@@ -231,7 +267,23 @@ pub fn gen(options: Options) {
231 let gpio_base = core.peripherals.get(&"GPIOA".to_string()).unwrap().address; 267 let gpio_base = core.peripherals.get(&"GPIOA".to_string()).unwrap().address;
232 let gpio_stride = 0x400; 268 let gpio_stride = 0x400;
233 269
270 for (id, channel_info) in &core.dma_channels {
271 let mut row = Vec::new();
272 row.push(id.clone());
273 row.push(channel_info.dma.clone());
274 row.push(channel_info.channel.to_string());
275 dma_channels_table.push(row);
276 }
277
278 let number_suffix_re = Regex::new("^(.*?)[0-9]*$").unwrap();
279
234 for (name, p) in &core.peripherals { 280 for (name, p) in &core.peripherals {
281 let captures = number_suffix_re.captures(&name).unwrap();
282 let root_peri_name = captures.get(1).unwrap().as_str().to_string();
283 peripheral_counts.insert(
284 root_peri_name.clone(),
285 peripheral_counts.get(&root_peri_name).map_or(1, |v| v + 1),
286 );
235 let mut ir_peri = ir::Peripheral { 287 let mut ir_peri = ir::Peripheral {
236 name: name.clone(), 288 name: name.clone(),
237 array: None, 289 array: None,
@@ -257,13 +309,38 @@ pub fn gen(options: Options) {
257 peripheral_pins_table.push(row); 309 peripheral_pins_table.push(row);
258 } 310 }
259 311
312 for dma_request in &p.dma_requests {
313 let mut row = Vec::new();
314 row.push(name.clone());
315 row.push(dma_request.0.clone());
316 row.push(dma_request.1.to_string());
317 dma_requests_table.push(row);
318 }
319
320 for (event, dma_channels) in &p.dma_channels {
321 for channel in dma_channels.iter() {
322 let mut row = Vec::new();
323 row.push(name.clone());
324 row.push(bi.module.clone());
325 row.push(bi.block.clone());
326 row.push(event.clone());
327 row.push(channel.channel.clone());
328 row.push(core.dma_channels[&channel.channel].dma.clone());
329 row.push(core.dma_channels[&channel.channel].channel.to_string());
330 if let Some(request) = channel.request {
331 row.push(request.to_string());
332 }
333 peripheral_dma_channels_table.push(row);
334 }
335 }
336
260 let mut peripheral_row = Vec::new(); 337 let mut peripheral_row = Vec::new();
261 peripheral_row.push(bi.module.clone()); 338 peripheral_row.push(bi.module.clone());
262 peripheral_row.push(name.clone()); 339 peripheral_row.push(name.clone());
263 peripherals_table.push(peripheral_row); 340 peripherals_table.push(peripheral_row);
264 341
265 if let Some(old_version) = 342 if let Some(old_version) =
266 peripheral_versions.insert(bi.module.clone(), bi.version.clone()) 343 peripheral_versions.insert(bi.module.clone(), bi.version.clone())
267 { 344 {
268 if old_version != bi.version { 345 if old_version != bi.version {
269 panic!( 346 panic!(
@@ -354,13 +431,13 @@ pub fn gen(options: Options) {
354 ]); 431 ]);
355 } 432 }
356 (None, Some(_)) => { 433 (None, Some(_)) => {
357 println!("Unable to find enable register for {}", name) 434 print!("Unable to find enable register for {}", name)
358 } 435 }
359 (Some(_), None) => { 436 (Some(_), None) => {
360 println!("Unable to find reset register for {}", name) 437 print!("Unable to find reset register for {}", name)
361 } 438 }
362 (None, None) => { 439 (None, None) => {
363 println!("Unable to find enable and reset register for {}", name) 440 print!("Unable to find enable and reset register for {}", name)
364 } 441 }
365 } 442 }
366 } 443 }
@@ -377,7 +454,17 @@ pub fn gen(options: Options) {
377 value: num, 454 value: num,
378 }); 455 });
379 456
380 interrupt_table.push(vec![name.to_ascii_uppercase()]); 457 let name = name.to_ascii_uppercase();
458
459 interrupt_table.push(vec![name.clone()]);
460
461 if name.starts_with("DMA") || name.contains("_DMA") {
462 interrupt_table.push(vec!["DMA".to_string(), name.clone()]);
463 }
464
465 if name.contains("EXTI") {
466 interrupt_table.push(vec!["EXTI".to_string(), name.clone()]);
467 }
381 } 468 }
382 469
383 ir.devices.insert("".to_string(), dev); 470 ir.devices.insert("".to_string(), dev);
@@ -385,11 +472,8 @@ pub fn gen(options: Options) {
385 let mut extra = format!( 472 let mut extra = format!(
386 "pub fn GPIO(n: usize) -> gpio::Gpio {{ 473 "pub fn GPIO(n: usize) -> gpio::Gpio {{
387 gpio::Gpio(({} + {}*n) as _) 474 gpio::Gpio(({} + {}*n) as _)
388 }}
389 pub fn DMA(n: usize) -> dma::Dma {{
390 dma::Dma(({} + {}*n) as _)
391 }}", 475 }}",
392 gpio_base, gpio_stride, dma_base, dma_stride, 476 gpio_base, gpio_stride,
393 ); 477 );
394 478
395 let peripheral_version_table = peripheral_versions 479 let peripheral_version_table = peripheral_versions
@@ -402,7 +486,11 @@ pub fn gen(options: Options) {
402 make_table(&mut extra, "peripherals", &peripherals_table); 486 make_table(&mut extra, "peripherals", &peripherals_table);
403 make_table(&mut extra, "peripheral_versions", &peripheral_version_table); 487 make_table(&mut extra, "peripheral_versions", &peripheral_version_table);
404 make_table(&mut extra, "peripheral_pins", &peripheral_pins_table); 488 make_table(&mut extra, "peripheral_pins", &peripheral_pins_table);
489 make_table(&mut extra, "peripheral_dma_channels", &peripheral_dma_channels_table);
405 make_table(&mut extra, "peripheral_rcc", &peripheral_rcc_table); 490 make_table(&mut extra, "peripheral_rcc", &peripheral_rcc_table);
491 make_table(&mut extra, "dma_channels", &dma_channels_table);
492 make_table(&mut extra, "dma_requests", &dma_requests_table);
493 make_peripheral_counts(&mut extra, &peripheral_counts);
406 494
407 for (module, version) in peripheral_versions { 495 for (module, version) in peripheral_versions {
408 all_peripheral_versions.insert((module.clone(), version.clone())); 496 all_peripheral_versions.insert((module.clone(), version.clone()));
@@ -411,7 +499,7 @@ pub fn gen(options: Options) {
411 "#[path=\"../../peripherals/{}_{}.rs\"] pub mod {};\n", 499 "#[path=\"../../peripherals/{}_{}.rs\"] pub mod {};\n",
412 module, version, module 500 module, version, module
413 ) 501 )
414 .unwrap(); 502 .unwrap();
415 } 503 }
416 504
417 // Cleanups! 505 // Cleanups!
@@ -449,7 +537,7 @@ pub fn gen(options: Options) {
449 "PROVIDE({} = DefaultHandler);\n", 537 "PROVIDE({} = DefaultHandler);\n",
450 name.to_ascii_uppercase() 538 name.to_ascii_uppercase()
451 ) 539 )
452 .unwrap(); 540 .unwrap();
453 } 541 }
454 542
455 File::create(chip_dir.join("device.x")) 543 File::create(chip_dir.join("device.x"))
@@ -477,7 +565,7 @@ pub fn gen(options: Options) {
477 transform::NameKind::Enum => format!("vals::{}", s), 565 transform::NameKind::Enum => format!("vals::{}", s),
478 _ => s.to_string(), 566 _ => s.to_string(),
479 }) 567 })
480 .unwrap(); 568 .unwrap();
481 569
482 transform::sort::Sort {}.run(&mut ir).unwrap(); 570 transform::sort::Sort {}.run(&mut ir).unwrap();
483 transform::Sanitize {}.run(&mut ir).unwrap(); 571 transform::Sanitize {}.run(&mut ir).unwrap();
@@ -488,7 +576,7 @@ pub fn gen(options: Options) {
488 .join("src/peripherals") 576 .join("src/peripherals")
489 .join(format!("{}_{}.rs", module, version)), 577 .join(format!("{}_{}.rs", module, version)),
490 ) 578 )
491 .unwrap(); 579 .unwrap();
492 let data = items.to_string().replace("] ", "]\n"); 580 let data = items.to_string().replace("] ", "]\n");
493 581
494 // Remove inner attributes like #![no_std] 582 // Remove inner attributes like #![no_std]
@@ -511,14 +599,14 @@ pub fn gen(options: Options) {
511 "#[cfg_attr(feature=\"{}_{}\", path = \"chips/{}_{}/pac.rs\")]", 599 "#[cfg_attr(feature=\"{}_{}\", path = \"chips/{}_{}/pac.rs\")]",
512 x, c, x, c 600 x, c, x, c
513 ) 601 )
514 .unwrap(); 602 .unwrap();
515 } else { 603 } else {
516 write!( 604 write!(
517 &mut paths, 605 &mut paths,
518 "#[cfg_attr(feature=\"{}\", path = \"chips/{}/pac.rs\")]", 606 "#[cfg_attr(feature=\"{}\", path = \"chips/{}/pac.rs\")]",
519 x, x 607 x, x
520 ) 608 )
521 .unwrap(); 609 .unwrap();
522 } 610 }
523 } 611 }
524 let mut contents: Vec<u8> = Vec::new(); 612 let mut contents: Vec<u8> = Vec::new();
@@ -541,7 +629,7 @@ pub fn gen(options: Options) {
541 out_dir.join("src").join("common.rs"), 629 out_dir.join("src").join("common.rs"),
542 generate::COMMON_MODULE, 630 generate::COMMON_MODULE,
543 ) 631 )
544 .unwrap(); 632 .unwrap();
545 633
546 // Generate Cargo.toml 634 // Generate Cargo.toml
547 const BUILDDEP_BEGIN: &[u8] = b"# BEGIN BUILD DEPENDENCIES"; 635 const BUILDDEP_BEGIN: &[u8] = b"# BEGIN BUILD DEPENDENCIES";