aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/Cargo.toml1
-rw-r--r--embassy-stm32/gen.py13
-rw-r--r--embassy-stm32/src/bdma/mod.rs69
-rw-r--r--embassy-stm32/src/dma/mod.rs65
-rw-r--r--embassy-stm32/src/dma/v2.rs259
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/usart/mod.rs11
-rw-r--r--embassy-stm32/src/usart/v1.rs10
-rw-r--r--stm32-metapac/Cargo.toml1
-rw-r--r--stm32-metapac/gen/src/lib.rs65
10 files changed, 325 insertions, 171 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 4e37c94fe..058d50124 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -28,6 +28,7 @@ stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt"
28vcell = { version = "0.1.3", optional = true } 28vcell = { version = "0.1.3", optional = true }
29 29
30cfg-if = "1.0.0" 30cfg-if = "1.0.0"
31paste = "1.0.5"
31 32
32[build-dependencies] 33[build-dependencies]
33stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false } 34stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false }
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..a8a22ce89 100644
--- a/embassy-stm32/src/dma/mod.rs
+++ b/embassy-stm32/src/dma/mod.rs
@@ -1,67 +1,22 @@
1#![macro_use] 1#![macro_use]
2 2
3#[cfg_attr(dma_v1, path = "v1.rs")] 3//#[cfg_attr(dma_v1, path = "v1.rs")]
4#[cfg_attr(dma_v2, path = "v2.rs")] 4#[cfg_attr(dma_v2, path = "v2.rs")]
5mod _version; 5mod _version;
6 6
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 {}
32
33macro_rules! impl_dma_channel {
34 ($type:ident, $dma_num:expr, $ch_num:expr) => {
35 impl Channel for peripherals::$type {}
36 impl sealed::Channel for peripherals::$type {
37 #[inline]
38 fn num(&self) -> u8 {
39 $dma_num * 8 + $ch_num
40 }
41 }
42 };
43}
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..6c6bbde23 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;
13 13use crate::pac::interrupts;
14const CH_COUNT: usize = 16; 14use crate::pac::peripheral_count;
15use crate::pac::peripheral_dma_channels;
16use crate::pac::peripherals;
17use crate::peripherals;
18
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;
@@ -41,9 +46,8 @@ pub(crate) async unsafe fn transfer_m2p(
41 src: &[u8], 46 src: &[u8],
42 dst: *mut u8, 47 dst: *mut u8,
43) { 48) {
44 let n = ch.num() as usize; 49 let n = ch.num();
45 let r = ch.regs(); 50 let c = ch.regs();
46 let c = r.st(ch.ch_num() as _);
47 51
48 // ndtr is max 16 bits. 52 // ndtr is max 16 bits.
49 assert!(src.len() <= 0xFFFF); 53 assert!(src.len() <= 0xFFFF);
@@ -82,106 +86,169 @@ pub(crate) async unsafe fn transfer_m2p(
82} 86}
83 87
84unsafe fn on_irq() { 88unsafe fn on_irq() {
85 for (dman, &dma) in DMAS.iter().enumerate() { 89 peripherals! {
86 for isrn in 0..2 { 90 (dma, $dma:ident) => {
87 let isr = dma.isr(isrn).read(); 91 for isrn in 0..2 {
88 dma.ifcr(isrn).write_value(isr); 92 let isr = pac::$dma.isr(isrn).read();
89 93 pac::$dma.ifcr(isrn).write_value(isr);
90 for chn in 0..4 { 94 let dman = <peripherals::$dma as sealed::Dma>::num() as usize;
91 let n = dman * 8 + isrn * 4 + chn; 95
92 if isr.teif(chn) { 96 for chn in 0..4 {
93 STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed); 97 let n = dman * 8 + isrn * 4 + chn;
94 STATE.ch_wakers[n].wake(); 98 if isr.teif(chn) {
95 } else if isr.tcif(chn) { 99 STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed);
96 STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed); 100 STATE.ch_wakers[n].wake();
97 STATE.ch_wakers[n].wake(); 101 } else if isr.tcif(chn) {
102 STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed);
103 STATE.ch_wakers[n].wake();
104 }
98 } 105 }
99 } 106 }
100 } 107 };
101 } 108 }
102} 109}
103 110
104#[interrupt] 111/// safety: must be called only once
105unsafe fn DMA1_STREAM0() { 112pub(crate) unsafe fn init() {
106 on_irq() 113 interrupts! {
107} 114 (DMA, $irq:ident) => {
108#[interrupt] 115 interrupt::$irq::steal().enable();
109unsafe fn DMA1_STREAM1() { 116 };
110 on_irq() 117 }
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} 118}
148#[interrupt] 119
149unsafe fn DMA2_STREAM3() { 120pub(crate) mod sealed {
150 on_irq() 121 use super::*;
122
123 pub trait Dma {
124 fn num() -> u8;
125 fn regs() -> &'static pac::dma::Dma;
126 }
127
128 pub trait Channel {
129 fn dma_regs() -> &'static pac::dma::Dma;
130
131 fn num(&self) -> usize;
132
133 fn ch_num(&self) -> u8;
134
135 fn regs(&self) -> pac::dma::St {
136 Self::dma_regs().st(self.ch_num() as _)
137 }
138 }
139
140 pub trait PeripheralChannel<PERI>: Channel {
141 fn request(&self) -> u8;
142 }
151} 143}
152#[interrupt] 144
153unsafe fn DMA2_STREAM4() { 145pub trait Dma: sealed::Dma + Sized {}
154 on_irq() 146pub trait Channel: sealed::Channel + Sized {}
147pub trait PeripheralChannel<PERI>: sealed::PeripheralChannel<PERI> + Sized {}
148
149macro_rules! impl_dma {
150 ($peri:ident, $num:expr) => {
151 impl Dma for peripherals::$peri {}
152 impl sealed::Dma for peripherals::$peri {
153 fn num() -> u8 {
154 $num
155 }
156 fn regs() -> &'static pac::dma::Dma {
157 &pac::$peri
158 }
159 }
160 };
155} 161}
156#[interrupt] 162
157unsafe fn DMA2_STREAM5() { 163macro_rules! impl_dma_channel {
158 on_irq() 164 ($channel_peri:ident, $dma_peri:ident, $dma_num:expr, $ch_num:expr) => {
165 impl Channel for peripherals::$channel_peri {}
166 impl sealed::Channel for peripherals::$channel_peri {
167 #[inline]
168 fn dma_regs() -> &'static pac::dma::Dma {
169 &crate::pac::$dma_peri
170 }
171
172 fn num(&self) -> usize {
173 ($dma_num * 8) + $ch_num
174 }
175
176 fn ch_num(&self) -> u8 {
177 $ch_num
178 }
179 }
180
181 impl<T> WriteDma<T> for peripherals::$channel_peri
182 where
183 Self: sealed::PeripheralChannel<T>,
184 T: 'static,
185 {
186 type WriteDmaFuture<'a> = impl Future<Output = ()>;
187
188 fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a>
189 where
190 T: 'a,
191 {
192 let request = sealed::PeripheralChannel::<T>::request(self);
193 unsafe { transfer_m2p(self, request, buf, dst) }
194 }
195 }
196 };
159} 197}
160#[interrupt] 198
161unsafe fn DMA2_STREAM6() { 199peripherals! {
162 on_irq() 200 (dma, DMA1) => {
201 impl_dma!(DMA1, 0);
202 dma_channels! {
203 ($channel_peri:ident, DMA1, $channel_num:expr) => {
204 impl_dma_channel!($channel_peri, DMA1, 0, $channel_num);
205 };
206 }
207 };
208 (dma, DMA2) => {
209 impl_dma!(DMA2, 1);
210 dma_channels! {
211 ($channel_peri:ident, DMA2, $channel_num:expr) => {
212 impl_dma_channel!($channel_peri, DMA2, 1, $channel_num);
213 };
214 }
215 };
163} 216}
164#[interrupt] 217
165unsafe fn DMA2_STREAM7() { 218interrupts! {
166 on_irq() 219 (DMA, $irq:ident) => {
220 unsafe fn $irq () {
221 on_irq()
222 }
223 };
167} 224}
168 225
169/// safety: must be called only once 226#[cfg(usart)]
170pub(crate) unsafe fn init() { 227use crate::usart;
171 interrupt::DMA1_STREAM0::steal().enable(); 228peripheral_dma_channels! {
172 interrupt::DMA1_STREAM1::steal().enable(); 229 ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => {
173 interrupt::DMA1_STREAM2::steal().enable(); 230 impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
174 interrupt::DMA1_STREAM3::steal().enable(); 231 impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { }
175 interrupt::DMA1_STREAM4::steal().enable(); 232
176 interrupt::DMA1_STREAM5::steal().enable(); 233 impl sealed::PeripheralChannel<peripherals::$peri> for peripherals::$channel_peri {
177 interrupt::DMA1_STREAM6::steal().enable(); 234 fn request(&self) -> u8 {
178 interrupt::DMA1_STREAM7::steal().enable(); 235 $event_num
179 interrupt::DMA2_STREAM0::steal().enable(); 236 }
180 interrupt::DMA2_STREAM1::steal().enable(); 237 }
181 interrupt::DMA2_STREAM2::steal().enable(); 238
182 interrupt::DMA2_STREAM3::steal().enable(); 239 impl PeripheralChannel<peripherals::$peri> for peripherals::$channel_peri { }
183 interrupt::DMA2_STREAM4::steal().enable(); 240 };
184 interrupt::DMA2_STREAM5::steal().enable(); 241
185 interrupt::DMA2_STREAM6::steal().enable(); 242 ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => {
186 interrupt::DMA2_STREAM7::steal().enable(); 243 impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
244 impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { }
245
246 impl sealed::PeripheralChannel<peripherals::$peri> for peripherals::$channel_peri {
247 fn request(&self) -> u8 {
248 $event_num
249 }
250 }
251
252 impl PeripheralChannel<peripherals::$peri> for peripherals::$channel_peri { }
253 };
187} 254}
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 9ba7bbe4c..813c58cd7 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -22,6 +22,8 @@ pub mod rcc;
22// Sometimes-present hardware 22// Sometimes-present hardware
23#[cfg(adc)] 23#[cfg(adc)]
24pub mod adc; 24pub mod adc;
25#[cfg(bdma)]
26pub mod bdma;
25#[cfg(timer)] 27#[cfg(timer)]
26pub mod clock; 28pub mod clock;
27#[cfg(dac)] 29#[cfg(dac)]
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index adf48c326..24793b6b1 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -1,7 +1,7 @@
1#![macro_use] 1#![macro_use]
2 2
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::peripherals;
7pub use _version::*; 7pub use _version::*;
@@ -25,6 +25,7 @@ pub enum Error {
25 25
26pub(crate) mod sealed { 26pub(crate) mod sealed {
27 use super::*; 27 use super::*;
28 use crate::dma::WriteDma;
28 29
29 pub trait Instance { 30 pub trait Instance {
30 fn regs(&self) -> Usart; 31 fn regs(&self) -> Usart;
@@ -44,7 +45,12 @@ pub(crate) mod sealed {
44 pub trait CkPin<T: Instance>: Pin { 45 pub trait CkPin<T: Instance>: Pin {
45 fn af_num(&self) -> u8; 46 fn af_num(&self) -> u8;
46 } 47 }
48
49 pub trait RxDma<T: Instance> {}
50
51 pub trait TxDma<T: Instance>: WriteDma<T> {}
47} 52}
53
48pub trait Instance: sealed::Instance {} 54pub trait Instance: sealed::Instance {}
49pub trait RxPin<T: Instance>: sealed::RxPin<T> {} 55pub trait RxPin<T: Instance>: sealed::RxPin<T> {}
50pub trait TxPin<T: Instance>: sealed::TxPin<T> {} 56pub trait TxPin<T: Instance>: sealed::TxPin<T> {}
@@ -52,6 +58,9 @@ pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {}
52pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {} 58pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {}
53pub trait CkPin<T: Instance>: sealed::CkPin<T> {} 59pub trait CkPin<T: Instance>: sealed::CkPin<T> {}
54 60
61pub trait RxDma<T: Instance>: sealed::RxDma<T> {}
62pub trait TxDma<T: Instance>: sealed::TxDma<T> {}
63
55crate::pac::peripherals!( 64crate::pac::peripherals!(
56 (usart, $inst:ident) => { 65 (usart, $inst:ident) => {
57 impl sealed::Instance for peripherals::$inst { 66 impl sealed::Instance for peripherals::$inst {
diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs
index 1ec1f5b30..a721e89a6 100644
--- a/embassy-stm32/src/usart/v1.rs
+++ b/embassy-stm32/src/usart/v1.rs
@@ -104,11 +104,16 @@ impl<'d, T: Instance> Uart<'d, T> {
104 #[cfg(dma_v2)] 104 #[cfg(dma_v2)]
105 pub async fn write_dma( 105 pub async fn write_dma(
106 &mut self, 106 &mut self,
107 ch: &mut impl crate::dma::Channel, 107 //ch: &mut impl crate::dma::Channel,
108 ch: &mut impl TxDma<T>,
108 buffer: &[u8], 109 buffer: &[u8],
109 ) -> Result<(), Error> { 110 ) -> Result<(), Error> {
110 let ch_func = 4; // USART3_TX
111 let r = self.inner.regs(); 111 let r = self.inner.regs();
112 let dst = r.dr().ptr() as *mut u8;
113 ch.transfer(buffer, dst).await;
114 Ok(())
115 /*
116 let ch_func = 4; // USART3_TX
112 117
113 unsafe { 118 unsafe {
114 r.cr3().write(|w| { 119 r.cr3().write(|w| {
@@ -121,6 +126,7 @@ impl<'d, T: Instance> Uart<'d, T> {
121 } 126 }
122 127
123 Ok(()) 128 Ok(())
129 */
124 } 130 }
125 131
126 pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 132 pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
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 408865e31..00e122e90 100644
--- a/stm32-metapac/gen/src/lib.rs
+++ b/stm32-metapac/gen/src/lib.rs
@@ -48,7 +48,7 @@ pub struct Peripheral {
48 #[serde(default)] 48 #[serde(default)]
49 pub pins: Vec<Pin>, 49 pub pins: Vec<Pin>,
50 #[serde(default)] 50 #[serde(default)]
51 pub dma_channels: HashMap<String, Vec<String>>, 51 pub dma_channels: HashMap<String, Vec<PeripheralDmaChannel>>,
52 #[serde(default)] 52 #[serde(default)]
53 pub dma_requests: HashMap<String, u32>, 53 pub dma_requests: HashMap<String, u32>,
54} 54}
@@ -66,6 +66,12 @@ pub struct DmaChannel {
66 pub channel: u32, 66 pub channel: u32,
67} 67}
68 68
69#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Hash)]
70pub struct PeripheralDmaChannel {
71 pub channel: String,
72 pub request: Option<u32>,
73}
74
69struct BlockInfo { 75struct BlockInfo {
70 /// usart_v1/USART -> usart 76 /// usart_v1/USART -> usart
71 module: String, 77 module: String,
@@ -121,6 +127,21 @@ fn find_reg_for_field<'c>(
121 }) 127 })
122} 128}
123 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
124fn make_table(out: &mut String, name: &str, data: &Vec<Vec<String>>) { 145fn make_table(out: &mut String, name: &str, data: &Vec<Vec<String>>) {
125 write!( 146 write!(
126 out, 147 out,
@@ -234,6 +255,7 @@ pub fn gen(options: Options) {
234 let mut dma_channels_table: Vec<Vec<String>> = Vec::new(); 255 let mut dma_channels_table: Vec<Vec<String>> = Vec::new();
235 let mut dma_requests_table: Vec<Vec<String>> = Vec::new(); 256 let mut dma_requests_table: Vec<Vec<String>> = Vec::new();
236 let mut peripheral_dma_channels_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();
237 259
238 let dma_base = core 260 let dma_base = core
239 .peripherals 261 .peripherals
@@ -248,12 +270,20 @@ pub fn gen(options: Options) {
248 for (id, channel_info) in &core.dma_channels { 270 for (id, channel_info) in &core.dma_channels {
249 let mut row = Vec::new(); 271 let mut row = Vec::new();
250 row.push(id.clone()); 272 row.push(id.clone());
251 row.push(channel_info.dma.clone() ); 273 row.push(channel_info.dma.clone());
252 row.push(channel_info.channel.to_string()); 274 row.push(channel_info.channel.to_string());
253 dma_channels_table.push(row); 275 dma_channels_table.push(row);
254 } 276 }
255 277
278 let number_suffix_re = Regex::new("^(.*?)[0-9]*$").unwrap();
279
256 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 );
257 let mut ir_peri = ir::Peripheral { 287 let mut ir_peri = ir::Peripheral {
258 name: name.clone(), 288 name: name.clone(),
259 array: None, 289 array: None,
@@ -291,12 +321,15 @@ pub fn gen(options: Options) {
291 for channel in dma_channels.iter() { 321 for channel in dma_channels.iter() {
292 let mut row = Vec::new(); 322 let mut row = Vec::new();
293 row.push(name.clone()); 323 row.push(name.clone());
294 row.push( bi.module.clone() ); 324 row.push(bi.module.clone());
295 row.push( bi.block.clone() ); 325 row.push(bi.block.clone());
296 row.push(event.clone()); 326 row.push(event.clone());
297 row.push( channel.clone() ); 327 row.push(channel.channel.clone());
298 row.push( core.dma_channels[channel].dma.clone() ); 328 row.push(core.dma_channels[&channel.channel].dma.clone());
299 row.push( core.dma_channels[channel].channel.to_string() ); 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 }
300 peripheral_dma_channels_table.push(row); 333 peripheral_dma_channels_table.push(row);
301 } 334 }
302 } 335 }
@@ -421,7 +454,17 @@ pub fn gen(options: Options) {
421 value: num, 454 value: num,
422 }); 455 });
423 456
424 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 }
425 } 468 }
426 469
427 ir.devices.insert("".to_string(), dev); 470 ir.devices.insert("".to_string(), dev);
@@ -429,11 +472,8 @@ pub fn gen(options: Options) {
429 let mut extra = format!( 472 let mut extra = format!(
430 "pub fn GPIO(n: usize) -> gpio::Gpio {{ 473 "pub fn GPIO(n: usize) -> gpio::Gpio {{
431 gpio::Gpio(({} + {}*n) as _) 474 gpio::Gpio(({} + {}*n) as _)
432 }}
433 pub fn DMA(n: usize) -> dma::Dma {{
434 dma::Dma(({} + {}*n) as _)
435 }}", 475 }}",
436 gpio_base, gpio_stride, dma_base, dma_stride, 476 gpio_base, gpio_stride,
437 ); 477 );
438 478
439 let peripheral_version_table = peripheral_versions 479 let peripheral_version_table = peripheral_versions
@@ -450,6 +490,7 @@ pub fn gen(options: Options) {
450 make_table(&mut extra, "peripheral_rcc", &peripheral_rcc_table); 490 make_table(&mut extra, "peripheral_rcc", &peripheral_rcc_table);
451 make_table(&mut extra, "dma_channels", &dma_channels_table); 491 make_table(&mut extra, "dma_channels", &dma_channels_table);
452 make_table(&mut extra, "dma_requests", &dma_requests_table); 492 make_table(&mut extra, "dma_requests", &dma_requests_table);
493 make_peripheral_counts(&mut extra, &peripheral_counts);
453 494
454 for (module, version) in peripheral_versions { 495 for (module, version) in peripheral_versions {
455 all_peripheral_versions.insert((module.clone(), version.clone())); 496 all_peripheral_versions.insert((module.clone(), version.clone()));