aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci.sh1
-rw-r--r--embassy-stm32/Cargo.toml69
-rw-r--r--embassy-stm32/src/pwr/f3.rs1
-rw-r--r--embassy-stm32/src/pwr/mod.rs1
-rw-r--r--embassy-stm32/src/rcc/f3/mod.rs374
-rw-r--r--embassy-stm32/src/rcc/mod.rs5
-rw-r--r--examples/stm32f3/.cargo/config.toml6
-rw-r--r--examples/stm32f3/Cargo.toml22
-rw-r--r--examples/stm32f3/build.rs5
-rw-r--r--examples/stm32f3/src/bin/blinky.rs30
-rw-r--r--examples/stm32f3/src/bin/button.rs33
-rw-r--r--examples/stm32f3/src/bin/button_exti.rs29
-rw-r--r--examples/stm32f3/src/bin/hello.rs28
-rw-r--r--examples/stm32f3/src/bin/spi_dma.rs41
-rw-r--r--examples/stm32f3/src/bin/usart_dma.rs30
-rw-r--r--examples/stm32f3/src/example_common.rs19
m---------stm32-data0
-rw-r--r--stm32-gen-features/src/lib.rs1
18 files changed, 694 insertions, 1 deletions
diff --git a/ci.sh b/ci.sh
index 2259d5b5f..ccd7e2559 100755
--- a/ci.sh
+++ b/ci.sh
@@ -54,6 +54,7 @@ cargo batch \
54 --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \ 54 --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \
55 --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \ 55 --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \
56 --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \ 56 --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \
57 --- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f3 \
57 --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \ 58 --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \
58 --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \ 59 --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \
59 --- build --release --manifest-path examples/stm32g0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32g0 \ 60 --- build --release --manifest-path examples/stm32g0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32g0 \
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 74903de0b..135f9a918 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -223,6 +223,75 @@ stm32f107rb = [ "stm32-metapac/stm32f107rb" ]
223stm32f107rc = [ "stm32-metapac/stm32f107rc" ] 223stm32f107rc = [ "stm32-metapac/stm32f107rc" ]
224stm32f107vb = [ "stm32-metapac/stm32f107vb" ] 224stm32f107vb = [ "stm32-metapac/stm32f107vb" ]
225stm32f107vc = [ "stm32-metapac/stm32f107vc" ] 225stm32f107vc = [ "stm32-metapac/stm32f107vc" ]
226stm32f301c6 = [ "stm32-metapac/stm32f301c6" ]
227stm32f301c8 = [ "stm32-metapac/stm32f301c8" ]
228stm32f301k6 = [ "stm32-metapac/stm32f301k6" ]
229stm32f301k8 = [ "stm32-metapac/stm32f301k8" ]
230stm32f301r6 = [ "stm32-metapac/stm32f301r6" ]
231stm32f301r8 = [ "stm32-metapac/stm32f301r8" ]
232stm32f302c6 = [ "stm32-metapac/stm32f302c6" ]
233stm32f302c8 = [ "stm32-metapac/stm32f302c8" ]
234stm32f302cb = [ "stm32-metapac/stm32f302cb" ]
235stm32f302cc = [ "stm32-metapac/stm32f302cc" ]
236stm32f302k6 = [ "stm32-metapac/stm32f302k6" ]
237stm32f302k8 = [ "stm32-metapac/stm32f302k8" ]
238stm32f302r6 = [ "stm32-metapac/stm32f302r6" ]
239stm32f302r8 = [ "stm32-metapac/stm32f302r8" ]
240stm32f302rb = [ "stm32-metapac/stm32f302rb" ]
241stm32f302rc = [ "stm32-metapac/stm32f302rc" ]
242stm32f302rd = [ "stm32-metapac/stm32f302rd" ]
243stm32f302re = [ "stm32-metapac/stm32f302re" ]
244stm32f302vb = [ "stm32-metapac/stm32f302vb" ]
245stm32f302vc = [ "stm32-metapac/stm32f302vc" ]
246stm32f302vd = [ "stm32-metapac/stm32f302vd" ]
247stm32f302ve = [ "stm32-metapac/stm32f302ve" ]
248stm32f302zd = [ "stm32-metapac/stm32f302zd" ]
249stm32f302ze = [ "stm32-metapac/stm32f302ze" ]
250stm32f303c6 = [ "stm32-metapac/stm32f303c6" ]
251stm32f303c8 = [ "stm32-metapac/stm32f303c8" ]
252stm32f303cb = [ "stm32-metapac/stm32f303cb" ]
253stm32f303cc = [ "stm32-metapac/stm32f303cc" ]
254stm32f303k6 = [ "stm32-metapac/stm32f303k6" ]
255stm32f303k8 = [ "stm32-metapac/stm32f303k8" ]
256stm32f303r6 = [ "stm32-metapac/stm32f303r6" ]
257stm32f303r8 = [ "stm32-metapac/stm32f303r8" ]
258stm32f303rb = [ "stm32-metapac/stm32f303rb" ]
259stm32f303rc = [ "stm32-metapac/stm32f303rc" ]
260stm32f303rd = [ "stm32-metapac/stm32f303rd" ]
261stm32f303re = [ "stm32-metapac/stm32f303re" ]
262stm32f303vb = [ "stm32-metapac/stm32f303vb" ]
263stm32f303vc = [ "stm32-metapac/stm32f303vc" ]
264stm32f303vd = [ "stm32-metapac/stm32f303vd" ]
265stm32f303ve = [ "stm32-metapac/stm32f303ve" ]
266stm32f303zd = [ "stm32-metapac/stm32f303zd" ]
267stm32f303ze = [ "stm32-metapac/stm32f303ze" ]
268stm32f318c8 = [ "stm32-metapac/stm32f318c8" ]
269stm32f318k8 = [ "stm32-metapac/stm32f318k8" ]
270stm32f328c8 = [ "stm32-metapac/stm32f328c8" ]
271stm32f334c4 = [ "stm32-metapac/stm32f334c4" ]
272stm32f334c6 = [ "stm32-metapac/stm32f334c6" ]
273stm32f334c8 = [ "stm32-metapac/stm32f334c8" ]
274stm32f334k4 = [ "stm32-metapac/stm32f334k4" ]
275stm32f334k6 = [ "stm32-metapac/stm32f334k6" ]
276stm32f334k8 = [ "stm32-metapac/stm32f334k8" ]
277stm32f334r6 = [ "stm32-metapac/stm32f334r6" ]
278stm32f334r8 = [ "stm32-metapac/stm32f334r8" ]
279stm32f358cc = [ "stm32-metapac/stm32f358cc" ]
280stm32f358rc = [ "stm32-metapac/stm32f358rc" ]
281stm32f358vc = [ "stm32-metapac/stm32f358vc" ]
282stm32f373c8 = [ "stm32-metapac/stm32f373c8" ]
283stm32f373cb = [ "stm32-metapac/stm32f373cb" ]
284stm32f373cc = [ "stm32-metapac/stm32f373cc" ]
285stm32f373r8 = [ "stm32-metapac/stm32f373r8" ]
286stm32f373rb = [ "stm32-metapac/stm32f373rb" ]
287stm32f373rc = [ "stm32-metapac/stm32f373rc" ]
288stm32f373v8 = [ "stm32-metapac/stm32f373v8" ]
289stm32f373vb = [ "stm32-metapac/stm32f373vb" ]
290stm32f373vc = [ "stm32-metapac/stm32f373vc" ]
291stm32f378cc = [ "stm32-metapac/stm32f378cc" ]
292stm32f378rc = [ "stm32-metapac/stm32f378rc" ]
293stm32f378vc = [ "stm32-metapac/stm32f378vc" ]
294stm32f398ve = [ "stm32-metapac/stm32f398ve" ]
226stm32f401cb = [ "stm32-metapac/stm32f401cb" ] 295stm32f401cb = [ "stm32-metapac/stm32f401cb" ]
227stm32f401cc = [ "stm32-metapac/stm32f401cc" ] 296stm32f401cc = [ "stm32-metapac/stm32f401cc" ]
228stm32f401cd = [ "stm32-metapac/stm32f401cd" ] 297stm32f401cd = [ "stm32-metapac/stm32f401cd" ]
diff --git a/embassy-stm32/src/pwr/f3.rs b/embassy-stm32/src/pwr/f3.rs
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/embassy-stm32/src/pwr/f3.rs
@@ -0,0 +1 @@
diff --git a/embassy-stm32/src/pwr/mod.rs b/embassy-stm32/src/pwr/mod.rs
index a71ce8f3c..18f462bd2 100644
--- a/embassy-stm32/src/pwr/mod.rs
+++ b/embassy-stm32/src/pwr/mod.rs
@@ -1,4 +1,5 @@
1#[cfg_attr(any(pwr_h7, pwr_h7smps), path = "h7.rs")] 1#[cfg_attr(any(pwr_h7, pwr_h7smps), path = "h7.rs")]
2#[cfg_attr(pwr_f3, path = "f3.rs")]
2#[cfg_attr(pwr_f4, path = "f4.rs")] 3#[cfg_attr(pwr_f4, path = "f4.rs")]
3#[cfg_attr(pwr_f7, path = "f7.rs")] 4#[cfg_attr(pwr_f7, path = "f7.rs")]
4#[cfg_attr(pwr_wl5, path = "wl5.rs")] 5#[cfg_attr(pwr_wl5, path = "wl5.rs")]
diff --git a/embassy-stm32/src/rcc/f3/mod.rs b/embassy-stm32/src/rcc/f3/mod.rs
new file mode 100644
index 000000000..ab1bd7607
--- /dev/null
+++ b/embassy-stm32/src/rcc/f3/mod.rs
@@ -0,0 +1,374 @@
1use core::marker::PhantomData;
2use embassy::util::Unborrow;
3
4use crate::pac::{
5 flash::vals::Latency,
6 rcc::vals::{Hpre, Hsebyp, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre},
7 FLASH, RCC,
8};
9use crate::peripherals;
10use crate::rcc::{set_freqs, Clocks};
11use crate::time::Hertz;
12
13const HSI: u32 = 8_000_000;
14
15/// RCC peripheral
16pub struct Rcc<'d> {
17 config: Config,
18 phantom: PhantomData<&'d mut peripherals::RCC>,
19}
20
21/// Clocks configutation
22#[non_exhaustive]
23#[derive(Default)]
24pub struct Config {
25 /// Frequency of HSE oscillator
26 /// 4MHz to 32MHz
27 pub hse: Option<Hertz>,
28 /// Bypass HSE for an external clock
29 pub bypass_hse: bool,
30 /// Frequency of the System Clock
31 pub sysclk: Option<Hertz>,
32 /// Frequency of AHB bus
33 pub hclk: Option<Hertz>,
34 /// Frequency of APB1 bus
35 /// - Max frequency 36MHz
36 pub pclk1: Option<Hertz>,
37 /// Frequency of APB2 bus
38 /// - Max frequency with HSE is 72MHz
39 /// - Max frequency without HSE is 64MHz
40 pub pclk2: Option<Hertz>,
41 /// USB clock setup
42 /// It is valid only when,
43 /// - HSE is enabled,
44 /// - The System clock frequency is either 48MHz or 72MHz
45 /// - APB1 clock has a minimum frequency of 10MHz
46 pub pll48: bool,
47}
48
49// Information required to setup the PLL clock
50struct PllConfig {
51 pll_src: Pllsrc,
52 pll_mul: Pllmul,
53 pll_div: Option<Prediv>,
54}
55
56/// Initialize and Set the clock frequencies
57pub unsafe fn init(config: Config) {
58 let r = <peripherals::RCC as embassy::util::Steal>::steal();
59 let clocks = Rcc::new(r, config).freeze();
60 set_freqs(clocks);
61}
62
63impl<'d> Rcc<'d> {
64 pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self {
65 Self {
66 config,
67 phantom: PhantomData,
68 }
69 }
70
71 fn freeze(self) -> Clocks {
72 // Calculate the real System clock, and PLL configuration if applicable
73 let (Hertz(sysclk), pll_config) = self.get_sysclk();
74 assert!(sysclk <= 72_000_000);
75
76 // Calculate real AHB clock
77 let hclk = self.config.hclk.map(|h| h.0).unwrap_or(sysclk);
78 let (hpre_bits, hpre_div) = match sysclk / hclk {
79 0 => unreachable!(),
80 1 => (Hpre::DIV1, 1),
81 2 => (Hpre::DIV2, 2),
82 3..=5 => (Hpre::DIV4, 4),
83 6..=11 => (Hpre::DIV8, 8),
84 12..=39 => (Hpre::DIV16, 16),
85 40..=95 => (Hpre::DIV64, 64),
86 96..=191 => (Hpre::DIV128, 128),
87 192..=383 => (Hpre::DIV256, 256),
88 _ => (Hpre::DIV512, 512),
89 };
90 let hclk = sysclk / hpre_div;
91 assert!(hclk <= 72_000_000);
92
93 // Calculate real APB1 clock
94 let pclk1 = self.config.pclk1.map(|p| p.0).unwrap_or(hclk);
95 let (ppre1_bits, ppre1) = match hclk / pclk1 {
96 0 => unreachable!(),
97 1 => (Ppre::DIV1, 1),
98 2 => (Ppre::DIV2, 2),
99 3..=5 => (Ppre::DIV4, 4),
100 6..=11 => (Ppre::DIV8, 8),
101 _ => (Ppre::DIV16, 16),
102 };
103 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
104 let pclk1 = hclk / ppre1;
105 assert!(pclk1 <= 36_000_000);
106
107 // Calculate real APB2 clock
108 let pclk2 = self.config.pclk2.map(|p| p.0).unwrap_or(hclk);
109 let (ppre2_bits, ppre2) = match hclk / pclk2 {
110 0 => unreachable!(),
111 1 => (Ppre::DIV1, 1),
112 2 => (Ppre::DIV2, 2),
113 3..=5 => (Ppre::DIV4, 4),
114 6..=11 => (Ppre::DIV8, 8),
115 _ => (Ppre::DIV16, 16),
116 };
117 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
118 let pclk2 = hclk / ppre2;
119 assert!(pclk2 <= 72_000_000);
120
121 // Set latency based on HCLK frquency
122 // NOTE(safety) Atomic write
123 unsafe {
124 FLASH.acr().write(|w| {
125 w.set_latency(if hclk <= 24_000_000 {
126 Latency::WS0
127 } else if hclk <= 48_000_000 {
128 Latency::WS1
129 } else {
130 Latency::WS2
131 });
132 })
133 }
134
135 // Enable HSE
136 if self.config.hse.is_some() {
137 // NOTE(unsafe) We own the peripheral block
138 unsafe {
139 RCC.cr().write(|w| {
140 w.set_hsebyp(if self.config.bypass_hse {
141 Hsebyp::BYPASSED
142 } else {
143 Hsebyp::NOTBYPASSED
144 });
145 // We turn on clock security to switch to HSI when HSE fails
146 w.set_csson(true);
147 w.set_hseon(true);
148 });
149 while !RCC.cr().read().hserdy() {}
150 }
151 }
152
153 // Enable PLL
154 if let Some(ref pll_config) = pll_config {
155 // NOTE(unsafe) We own the peripheral block
156 unsafe {
157 RCC.cfgr().write(|w| {
158 w.set_pllmul(pll_config.pll_mul);
159 w.set_pllsrc(pll_config.pll_src);
160 });
161 if let Some(pll_div) = pll_config.pll_div {
162 RCC.cfgr2().write(|w| w.set_prediv(pll_div));
163 }
164 RCC.cr().modify(|w| w.set_pllon(true));
165 while !RCC.cr().read().pllrdy() {}
166 }
167 }
168
169 if self.config.pll48 {
170 let usb_pre = self.get_usb_pre(sysclk, pclk1, &pll_config);
171 // NOTE(unsafe) We own the peripheral block
172 unsafe {
173 RCC.cfgr().write(|w| {
174 w.set_usbpre(usb_pre);
175 });
176 }
177 }
178
179 // Set prescalers
180 unsafe {
181 // NOTE(unsafe) We own the peripheral block
182 RCC.cfgr().write(|w| {
183 w.set_ppre2(ppre2_bits);
184 w.set_ppre1(ppre1_bits);
185 w.set_hpre(hpre_bits);
186 });
187
188 // Wait for the new prescalers to kick in
189 // "The clocks are divided with the new prescaler factor from
190 // 1 to 16 AHB cycles after write"
191 cortex_m::asm::delay(16);
192
193 // NOTE(unsafe) We own the peripheral block
194 RCC.cfgr().write(|w| {
195 w.set_sw(match (pll_config, self.config.hse) {
196 (Some(_), _) => Sw::PLL,
197 (None, Some(_)) => Sw::HSE,
198 (None, None) => Sw::HSI,
199 })
200 });
201 }
202
203 Clocks {
204 sys: Hertz(sysclk),
205 apb1: Hertz(pclk1),
206 apb2: Hertz(pclk2),
207 apb1_tim: Hertz(pclk1 * timer_mul1),
208 apb2_tim: Hertz(pclk2 * timer_mul2),
209 ahb: Hertz(hclk),
210 }
211 }
212
213 #[inline]
214 fn get_sysclk(&self) -> (Hertz, Option<PllConfig>) {
215 match (self.config.sysclk, self.config.hse) {
216 (Some(sysclk), Some(hse)) if sysclk == hse => (hse, None),
217 (Some(sysclk), None) if sysclk.0 == HSI => (Hertz(HSI), None),
218 // If the user selected System clock is different from HSI or HSE
219 // we will have to setup PLL clock source
220 (Some(sysclk), _) => {
221 let (sysclk, pll_config) = self.calc_pll(sysclk);
222 (sysclk, Some(pll_config))
223 }
224 (None, Some(hse)) => (hse, None),
225 (None, None) => (Hertz(HSI), None),
226 }
227 }
228
229 #[inline]
230 fn calc_pll(&self, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) {
231 // Calculates the Multiplier and the Divisor to arrive at
232 // the required System clock from PLL source frequency
233 let get_mul_div = |sysclk, pllsrcclk| {
234 let common_div = gcd(sysclk, pllsrcclk);
235 let mut multiplier = sysclk / common_div;
236 let mut divisor = pllsrcclk / common_div;
237 // Minimum PLL multiplier is two
238 if multiplier == 1 {
239 multiplier *= 2;
240 divisor *= 2;
241 }
242 assert!(multiplier <= 16);
243 assert!(divisor <= 16);
244 (multiplier, divisor)
245 };
246 // Based on the source of Pll, we calculate the actual system clock
247 // frequency, PLL's source identifier, multiplier and divisor
248 let (act_sysclk, pll_src, pll_mul, pll_div) = match self.config.hse {
249 Some(Hertz(hse)) => {
250 let (multiplier, divisor) = get_mul_div(sysclk, hse);
251 (
252 Hertz((hse / divisor) * multiplier),
253 Pllsrc::HSE_DIV_PREDIV,
254 into_pll_mul(multiplier),
255 Some(into_pre_div(divisor)),
256 )
257 }
258 None => {
259 cfg_if::cfg_if! {
260 // For some chips PREDIV is always two, and cannot be changed
261 if #[cfg(any(
262 feature="stm32f302xd", feature="stm32f302xe", feature="stm32f303xd",
263 feature="stm32f303xe", feature="stm32f398xe"
264 ))] {
265 let (multiplier, divisor) = get_mul_div(sysclk, HSI);
266 (
267 Hertz((hse / divisor) * multiplier),
268 Pllsrc::HSI_DIV_PREDIV,
269 into_pll_mul(multiplier),
270 Some(into_pre_div(divisor)),
271 )
272 } else {
273 let pllsrcclk = HSI / 2;
274 let multiplier = sysclk / pllsrcclk;
275 assert!(multiplier <= 16);
276 (
277 Hertz(pllsrcclk * multiplier),
278 Pllsrc::HSI_DIV2,
279 into_pll_mul(multiplier),
280 None,
281 )
282 }
283 }
284 }
285 };
286 (
287 act_sysclk,
288 PllConfig {
289 pll_src,
290 pll_mul,
291 pll_div,
292 },
293 )
294 }
295
296 #[inline]
297 fn get_usb_pre(&self, sysclk: u32, pclk1: u32, pll_config: &Option<PllConfig>) -> Usbpre {
298 cfg_if::cfg_if! {
299 // Some chips do not have USB
300 if #[cfg(any(stm32f301, stm32f318, stm32f334))] {
301 panic!("USB clock not supported by the chip");
302 } else {
303 let usb_ok = self.config.hse.is_some() && pll_config.is_some() && (pclk1 >= 10_000_000);
304 match (usb_ok, sysclk) {
305 (true, 72_000_000) => Usbpre::DIV1_5,
306 (true, 48_000_000) => Usbpre::DIV1,
307 _ => panic!(
308 "USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz"
309 ),
310 }
311 }
312 }
313 }
314}
315
316// This function assumes cases when multiplier is one and it
317// being greater than 16 is made impossible
318#[inline]
319fn into_pll_mul(multiplier: u32) -> Pllmul {
320 match multiplier {
321 2 => Pllmul::MUL2,
322 3 => Pllmul::MUL3,
323 4 => Pllmul::MUL4,
324 5 => Pllmul::MUL5,
325 6 => Pllmul::MUL6,
326 7 => Pllmul::MUL7,
327 8 => Pllmul::MUL8,
328 9 => Pllmul::MUL9,
329 10 => Pllmul::MUL10,
330 11 => Pllmul::MUL11,
331 12 => Pllmul::MUL12,
332 13 => Pllmul::MUL13,
333 14 => Pllmul::MUL14,
334 15 => Pllmul::MUL15,
335 16 => Pllmul::MUL16,
336 _ => unreachable!(),
337 }
338}
339
340// This function assumes the incoming divisor cannot be greater
341// than 16
342#[inline]
343fn into_pre_div(divisor: u32) -> Prediv {
344 match divisor {
345 1 => Prediv::DIV1,
346 2 => Prediv::DIV2,
347 3 => Prediv::DIV3,
348 4 => Prediv::DIV4,
349 5 => Prediv::DIV5,
350 6 => Prediv::DIV6,
351 7 => Prediv::DIV7,
352 8 => Prediv::DIV8,
353 9 => Prediv::DIV9,
354 10 => Prediv::DIV10,
355 11 => Prediv::DIV11,
356 12 => Prediv::DIV12,
357 13 => Prediv::DIV13,
358 14 => Prediv::DIV14,
359 15 => Prediv::DIV15,
360 16 => Prediv::DIV16,
361 _ => unreachable!(),
362 }
363}
364
365// Determine GCD using Euclidean algorithm
366#[inline]
367fn gcd(mut a: u32, mut b: u32) -> u32 {
368 while b != 0 {
369 let r = a % b;
370 a = b;
371 b = r;
372 }
373 a
374}
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 9883543df..619316df8 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -26,7 +26,7 @@ pub struct Clocks {
26 #[cfg(any(rcc_wl5, rcc_u5))] 26 #[cfg(any(rcc_wl5, rcc_u5))]
27 pub apb3: Hertz, 27 pub apb3: Hertz,
28 28
29 #[cfg(any(rcc_l0, rcc_l1, rcc_f0, rcc_f1, rcc_f0x0, rcc_g0))] 29 #[cfg(any(rcc_l0, rcc_l1, rcc_f0, rcc_f1, rcc_f3, rcc_f0x0, rcc_g0))]
30 pub ahb: Hertz, 30 pub ahb: Hertz,
31 31
32 #[cfg(any(rcc_l4, rcc_f4, rcc_f7, rcc_h7, rcc_g4, rcc_u5, rcc_wb, rcc_wl5))] 32 #[cfg(any(rcc_l4, rcc_f4, rcc_f7, rcc_h7, rcc_g4, rcc_u5, rcc_wb, rcc_wl5))]
@@ -81,6 +81,9 @@ cfg_if::cfg_if! {
81 } else if #[cfg(rcc_f1)] { 81 } else if #[cfg(rcc_f1)] {
82 mod f1; 82 mod f1;
83 pub use f1::*; 83 pub use f1::*;
84 } else if #[cfg(rcc_f3)] {
85 mod f3;
86 pub use f3::*;
84 } else if #[cfg(rcc_f4)] { 87 } else if #[cfg(rcc_f4)] {
85 mod f4; 88 mod f4;
86 pub use f4::*; 89 pub use f4::*;
diff --git a/examples/stm32f3/.cargo/config.toml b/examples/stm32f3/.cargo/config.toml
new file mode 100644
index 000000000..eb8a8b335
--- /dev/null
+++ b/examples/stm32f3/.cargo/config.toml
@@ -0,0 +1,6 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace STM32F429ZITx with your chip as listed in `probe-run --list-chips`
3runner = "probe-run --chip STM32F303VCTx"
4
5[build]
6target = "thumbv7em-none-eabihf"
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
new file mode 100644
index 000000000..cd9cd3a8f
--- /dev/null
+++ b/examples/stm32f3/Cargo.toml
@@ -0,0 +1,22 @@
1[package]
2authors = ["Dario Nieuwenhuis <[email protected]>"]
3edition = "2018"
4name = "embassy-stm32f3-examples"
5version = "0.1.0"
6resolver = "2"
7
8[dependencies]
9embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] }
10embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] }
11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32f303vc", "unstable-pac", "memory-x", "time-driver-tim2"] }
12
13defmt = "0.3"
14defmt-rtt = "0.3"
15
16cortex-m = "0.7.3"
17cortex-m-rt = "0.7.0"
18embedded-hal = "0.2.6"
19panic-probe = { version = "0.3", features = ["print-defmt"] }
20futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
21heapless = { version = "0.7.5", default-features = false }
22nb = "1.0.0"
diff --git a/examples/stm32f3/build.rs b/examples/stm32f3/build.rs
new file mode 100644
index 000000000..8cd32d7ed
--- /dev/null
+++ b/examples/stm32f3/build.rs
@@ -0,0 +1,5 @@
1fn main() {
2 println!("cargo:rustc-link-arg-bins=--nmagic");
3 println!("cargo:rustc-link-arg-bins=-Tlink.x");
4 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
5}
diff --git a/examples/stm32f3/src/bin/blinky.rs b/examples/stm32f3/src/bin/blinky.rs
new file mode 100644
index 000000000..321643557
--- /dev/null
+++ b/examples/stm32f3/src/bin/blinky.rs
@@ -0,0 +1,30 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7
8use embassy::executor::Spawner;
9use embassy::time::{Duration, Timer};
10use embassy_stm32::gpio::{Level, Output, Speed};
11use embassy_stm32::Peripherals;
12use embedded_hal::digital::v2::OutputPin;
13use example_common::*;
14
15#[embassy::main]
16async fn main(_spawner: Spawner, p: Peripherals) {
17 info!("Hello World!");
18
19 let mut led = Output::new(p.PE12, Level::High, Speed::Low);
20
21 loop {
22 info!("high");
23 unwrap!(led.set_high());
24 Timer::after(Duration::from_millis(1000)).await;
25
26 info!("low");
27 unwrap!(led.set_low());
28 Timer::after(Duration::from_millis(1000)).await;
29 }
30}
diff --git a/examples/stm32f3/src/bin/button.rs b/examples/stm32f3/src/bin/button.rs
new file mode 100644
index 000000000..c5fab138b
--- /dev/null
+++ b/examples/stm32f3/src/bin/button.rs
@@ -0,0 +1,33 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7use cortex_m_rt::entry;
8use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
9use embedded_hal::digital::v2::{InputPin, OutputPin};
10use example_common::*;
11
12#[entry]
13fn main() -> ! {
14 info!("Hello World!");
15
16 let p = embassy_stm32::init(Default::default());
17
18 let button = Input::new(p.PA0, Pull::Down);
19 let mut led1 = Output::new(p.PE9, Level::High, Speed::Low);
20 let mut led2 = Output::new(p.PE15, Level::High, Speed::Low);
21
22 loop {
23 if unwrap!(button.is_high()) {
24 info!("high");
25 unwrap!(led1.set_high());
26 unwrap!(led2.set_low());
27 } else {
28 info!("low");
29 unwrap!(led1.set_low());
30 unwrap!(led2.set_high());
31 }
32 }
33}
diff --git a/examples/stm32f3/src/bin/button_exti.rs b/examples/stm32f3/src/bin/button_exti.rs
new file mode 100644
index 000000000..d45e4365b
--- /dev/null
+++ b/examples/stm32f3/src/bin/button_exti.rs
@@ -0,0 +1,29 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7use embassy::executor::Spawner;
8use embassy_stm32::exti::ExtiInput;
9use embassy_stm32::gpio::{Input, Pull};
10use embassy_stm32::Peripherals;
11use embassy_traits::gpio::{WaitForFallingEdge, WaitForRisingEdge};
12use example_common::*;
13
14#[embassy::main]
15async fn main(_spawner: Spawner, p: Peripherals) {
16 info!("Hello World!");
17
18 let button = Input::new(p.PA0, Pull::Down);
19 let mut button = ExtiInput::new(button, p.EXTI0);
20
21 info!("Press the USER button...");
22
23 loop {
24 button.wait_for_rising_edge().await;
25 info!("Pressed!");
26 button.wait_for_falling_edge().await;
27 info!("Released!");
28 }
29}
diff --git a/examples/stm32f3/src/bin/hello.rs b/examples/stm32f3/src/bin/hello.rs
new file mode 100644
index 000000000..9a67419fb
--- /dev/null
+++ b/examples/stm32f3/src/bin/hello.rs
@@ -0,0 +1,28 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::info;
6use embassy::executor::Spawner;
7use embassy::time::{Duration, Timer};
8use embassy_stm32::time::Hertz;
9use embassy_stm32::Config;
10use embassy_stm32::Peripherals;
11
12#[path = "../example_common.rs"]
13mod example_common;
14
15fn config() -> Config {
16 let mut config = Config::default();
17 config.rcc.hse = Some(Hertz(8_000_000));
18 config.rcc.sysclk = Some(Hertz(16_000_000));
19 config
20}
21
22#[embassy::main(config = "config()")]
23async fn main(_spawner: Spawner, _p: Peripherals) -> ! {
24 loop {
25 info!("Hello World!");
26 Timer::after(Duration::from_secs(1)).await;
27 }
28}
diff --git a/examples/stm32f3/src/bin/spi_dma.rs b/examples/stm32f3/src/bin/spi_dma.rs
new file mode 100644
index 000000000..a87a36f73
--- /dev/null
+++ b/examples/stm32f3/src/bin/spi_dma.rs
@@ -0,0 +1,41 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7use core::fmt::Write;
8use core::str::from_utf8;
9use embassy::executor::Spawner;
10use embassy_stm32::spi::{Config, Spi};
11use embassy_stm32::time::Hertz;
12use embassy_stm32::Peripherals;
13use embassy_traits::spi::FullDuplex;
14use example_common::*;
15use heapless::String;
16
17#[embassy::main]
18async fn main(_spawner: Spawner, p: Peripherals) {
19 info!("Hello World!");
20
21 let mut spi = Spi::new(
22 p.SPI1,
23 p.PB3,
24 p.PB5,
25 p.PB4,
26 p.DMA1_CH3,
27 p.DMA1_CH2,
28 Hertz(1_000_000),
29 Config::default(),
30 );
31
32 for n in 0u32.. {
33 let mut write: String<128> = String::new();
34 let mut read = [0; 128];
35 core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap();
36 spi.read_write(&mut read[0..write.len()], write.as_bytes())
37 .await
38 .ok();
39 info!("read via spi+dma: {}", from_utf8(&read).unwrap());
40 }
41}
diff --git a/examples/stm32f3/src/bin/usart_dma.rs b/examples/stm32f3/src/bin/usart_dma.rs
new file mode 100644
index 000000000..99530b5c0
--- /dev/null
+++ b/examples/stm32f3/src/bin/usart_dma.rs
@@ -0,0 +1,30 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7use core::fmt::Write;
8use embassy::executor::Spawner;
9use embassy_stm32::dma::NoDma;
10use embassy_stm32::usart::{Config, Uart};
11use embassy_stm32::Peripherals;
12use embassy_traits::uart::Write as _;
13use example_common::*;
14use heapless::String;
15
16#[embassy::main]
17async fn main(_spawner: Spawner, p: Peripherals) {
18 info!("Hello World!");
19
20 let config = Config::default();
21 let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, p.DMA1_CH4, NoDma, config);
22
23 for n in 0u32.. {
24 let mut s: String<128> = String::new();
25 core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap();
26
27 unwrap!(usart.write(s.as_bytes()).await);
28 info!("wrote DMA");
29 }
30}
diff --git a/examples/stm32f3/src/example_common.rs b/examples/stm32f3/src/example_common.rs
new file mode 100644
index 000000000..e14517033
--- /dev/null
+++ b/examples/stm32f3/src/example_common.rs
@@ -0,0 +1,19 @@
1#![macro_use]
2
3use defmt_rtt as _; // global logger
4use panic_probe as _;
5
6pub use defmt::*;
7
8use core::sync::atomic::{AtomicUsize, Ordering};
9
10defmt::timestamp! {
11 "{=u64}",
12 {
13 static COUNT: AtomicUsize = AtomicUsize::new(0);
14 // NOTE(no-CAS) `timestamps` runs with interrupts disabled
15 let n = COUNT.load(Ordering::Relaxed);
16 COUNT.store(n + 1, Ordering::Relaxed);
17 n as u64
18 }
19}
diff --git a/stm32-data b/stm32-data
Subproject 5506d27471c7e3297450127c3279f3dab96c94f Subproject f275c3f5ef23339e068f38e1790584277a24623
diff --git a/stm32-gen-features/src/lib.rs b/stm32-gen-features/src/lib.rs
index 50c334852..1ab4865a4 100644
--- a/stm32-gen-features/src/lib.rs
+++ b/stm32-gen-features/src/lib.rs
@@ -5,6 +5,7 @@ use std::{iter::FilterMap, path::Path, slice::Iter};
5const SUPPORTED_FAMILIES: &[&str] = &[ 5const SUPPORTED_FAMILIES: &[&str] = &[
6 "stm32f0", 6 "stm32f0",
7 "stm32f1", 7 "stm32f1",
8 "stm32f3",
8 "stm32f4", 9 "stm32f4",
9 "stm32f7", 10 "stm32f7",
10 "stm32g0", 11 "stm32g0",