aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-03-27 17:18:30 +0000
committerGitHub <[email protected]>2022-03-27 17:18:30 +0000
commita211003021dee1cf1035557706e2e55d2c3608c9 (patch)
treed841b2c4d87e851fa2951e3b7039b72c305e1244
parent5c68f0bae7c4091ad34fb2a671e08a614d9beb9a (diff)
parent55a9bf98c56e3a03cdd79e9607fc964e78badf62 (diff)
Merge #678
678: Add minimal F2 family support r=Dirbaio a=Gekkio Here's the bare minimum to support F2 family (207/217/205/215). A lot is missing in RCC (e.g. PLL support), but this is enough to have a working blinky example. The example is set up for a NUCLEO-F207ZG board which I don't have, but I've tested it on my custom board with a F215 and different pinout :sweat_smile: After looking at other RCC implementation, I noticed there's two main API styles: a "low-level" API (e.g. L0) where the `Config` struct has dividers and other low-level "knobs", and a "high-level" API (e.g. F0) where it has desired clock frequencies and the RCC implementation figures out how to achieve them. Which one is preferred? Personally I like the low-level API slightly more, because it gives you the most control and it would be easy to also provide some functions to calculate the required parameters based on desired clock frequencies. F2 has a nasty errata: a delay or DSB instruction must be added after every RCC peripheral clock enable. I've added this workaround to build.rs, but am not sure if this is the best approach. Any comments? I'm planning to add PLL support too once I know which kind of API is preferred. Would you prefer a separate pull request for that, or should I continue working on this one? Co-authored-by: Joonas Javanainen <[email protected]>
-rwxr-xr-xci.sh2
-rwxr-xr-xci_stable.sh2
-rw-r--r--embassy-stm32/Cargo.toml38
-rw-r--r--embassy-stm32/build.rs12
-rw-r--r--embassy-stm32/src/rcc/f2.rs303
-rw-r--r--embassy-stm32/src/rcc/mod.rs5
-rw-r--r--examples/stm32f2/.cargo/config6
-rw-r--r--examples/stm32f2/Cargo.toml21
-rw-r--r--examples/stm32f2/build.rs5
-rw-r--r--examples/stm32f2/src/bin/blinky.rs29
-rw-r--r--examples/stm32f2/src/example_common.rs19
-rw-r--r--stm32-gen-features/src/lib.rs3
12 files changed, 441 insertions, 4 deletions
diff --git a/ci.sh b/ci.sh
index b3429a0a3..deb64870f 100755
--- a/ci.sh
+++ b/ci.sh
@@ -53,6 +53,7 @@ cargo batch \
53 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits \ 53 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits \
54 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f398ve,defmt,exti,time-driver-any,unstable-traits \ 54 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f398ve,defmt,exti,time-driver-any,unstable-traits \
55 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32g0c1ve,defmt,exti,time-driver-any,unstable-traits \ 55 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32g0c1ve,defmt,exti,time-driver-any,unstable-traits \
56 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f217zg,defmt,exti,time-driver-any,unstable-traits \
56 --- build --release --manifest-path docs/modules/ROOT/examples/basic/Cargo.toml --target thumbv7em-none-eabi \ 57 --- build --release --manifest-path docs/modules/ROOT/examples/basic/Cargo.toml --target thumbv7em-none-eabi \
57 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-pac/Cargo.toml --target thumbv7em-none-eabi \ 58 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-pac/Cargo.toml --target thumbv7em-none-eabi \
58 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-hal/Cargo.toml --target thumbv7em-none-eabi \ 59 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-hal/Cargo.toml --target thumbv7em-none-eabi \
@@ -63,6 +64,7 @@ cargo batch \
63 --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \ 64 --- build --release --manifest-path examples/rp/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/rp \
64 --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \ 65 --- build --release --manifest-path examples/stm32f0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32f0 \
65 --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \ 66 --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \
67 --- build --release --manifest-path examples/stm32f2/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f2 \
66 --- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f3 \ 68 --- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f3 \
67 --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \ 69 --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \
68 --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \ 70 --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \
diff --git a/ci_stable.sh b/ci_stable.sh
index a1c6bd26e..4f604057d 100755
--- a/ci_stable.sh
+++ b/ci_stable.sh
@@ -58,5 +58,7 @@ cargo batch \
58 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,unstable-traits \ 58 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32l072cz,defmt,exti,time-driver-any,unstable-traits \
59 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any \ 59 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any \
60 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits \ 60 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32l151cb-a,defmt,exti,time-driver-any,unstable-traits \
61 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any \
62 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f217zg,defmt,exti,time-driver-any,unstable-traits \
61 --- build --release --manifest-path examples/nrf/Cargo.toml --target thumbv7em-none-eabi --no-default-features --out-dir out/examples/nrf --bin raw_spawn \ 63 --- build --release --manifest-path examples/nrf/Cargo.toml --target thumbv7em-none-eabi --no-default-features --out-dir out/examples/nrf --bin raw_spawn \
62 --- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --no-default-features --out-dir out/examples/stm32l0 --bin raw_spawn \ 64 --- build --release --manifest-path examples/stm32l0/Cargo.toml --target thumbv6m-none-eabi --no-default-features --out-dir out/examples/stm32l0 --bin raw_spawn \
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 44c78dfef..8efa9a810 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -265,6 +265,44 @@ stm32f107rb = [ "stm32-metapac/stm32f107rb" ]
265stm32f107rc = [ "stm32-metapac/stm32f107rc" ] 265stm32f107rc = [ "stm32-metapac/stm32f107rc" ]
266stm32f107vb = [ "stm32-metapac/stm32f107vb" ] 266stm32f107vb = [ "stm32-metapac/stm32f107vb" ]
267stm32f107vc = [ "stm32-metapac/stm32f107vc" ] 267stm32f107vc = [ "stm32-metapac/stm32f107vc" ]
268stm32f205rb = [ "stm32-metapac/stm32f205rb" ]
269stm32f205rc = [ "stm32-metapac/stm32f205rc" ]
270stm32f205re = [ "stm32-metapac/stm32f205re" ]
271stm32f205rf = [ "stm32-metapac/stm32f205rf" ]
272stm32f205rg = [ "stm32-metapac/stm32f205rg" ]
273stm32f205vb = [ "stm32-metapac/stm32f205vb" ]
274stm32f205vc = [ "stm32-metapac/stm32f205vc" ]
275stm32f205ve = [ "stm32-metapac/stm32f205ve" ]
276stm32f205vf = [ "stm32-metapac/stm32f205vf" ]
277stm32f205vg = [ "stm32-metapac/stm32f205vg" ]
278stm32f205zc = [ "stm32-metapac/stm32f205zc" ]
279stm32f205ze = [ "stm32-metapac/stm32f205ze" ]
280stm32f205zf = [ "stm32-metapac/stm32f205zf" ]
281stm32f205zg = [ "stm32-metapac/stm32f205zg" ]
282stm32f207ic = [ "stm32-metapac/stm32f207ic" ]
283stm32f207ie = [ "stm32-metapac/stm32f207ie" ]
284stm32f207if = [ "stm32-metapac/stm32f207if" ]
285stm32f207ig = [ "stm32-metapac/stm32f207ig" ]
286stm32f207vc = [ "stm32-metapac/stm32f207vc" ]
287stm32f207ve = [ "stm32-metapac/stm32f207ve" ]
288stm32f207vf = [ "stm32-metapac/stm32f207vf" ]
289stm32f207vg = [ "stm32-metapac/stm32f207vg" ]
290stm32f207zc = [ "stm32-metapac/stm32f207zc" ]
291stm32f207ze = [ "stm32-metapac/stm32f207ze" ]
292stm32f207zf = [ "stm32-metapac/stm32f207zf" ]
293stm32f207zg = [ "stm32-metapac/stm32f207zg" ]
294stm32f215re = [ "stm32-metapac/stm32f215re" ]
295stm32f215rg = [ "stm32-metapac/stm32f215rg" ]
296stm32f215ve = [ "stm32-metapac/stm32f215ve" ]
297stm32f215vg = [ "stm32-metapac/stm32f215vg" ]
298stm32f215ze = [ "stm32-metapac/stm32f215ze" ]
299stm32f215zg = [ "stm32-metapac/stm32f215zg" ]
300stm32f217ie = [ "stm32-metapac/stm32f217ie" ]
301stm32f217ig = [ "stm32-metapac/stm32f217ig" ]
302stm32f217ve = [ "stm32-metapac/stm32f217ve" ]
303stm32f217vg = [ "stm32-metapac/stm32f217vg" ]
304stm32f217ze = [ "stm32-metapac/stm32f217ze" ]
305stm32f217zg = [ "stm32-metapac/stm32f217zg" ]
268stm32f301c6 = [ "stm32-metapac/stm32f301c6" ] 306stm32f301c6 = [ "stm32-metapac/stm32f301c6" ]
269stm32f301c8 = [ "stm32-metapac/stm32f301c8" ] 307stm32f301c8 = [ "stm32-metapac/stm32f301c8" ]
270stm32f301k6 = [ "stm32-metapac/stm32f301k6" ] 308stm32f301k6 = [ "stm32-metapac/stm32f301k6" ]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 4cba1c669..2c8409a35 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -166,6 +166,15 @@ fn main() {
166 None => TokenStream::new(), 166 None => TokenStream::new(),
167 }; 167 };
168 168
169 let after_enable = if chip_name.starts_with("stm32f2") {
170 // Errata: ES0005 - 2.1.11 Delay after an RCC peripheral clock enabling
171 quote! {
172 cortex_m::asm::dsb();
173 }
174 } else {
175 TokenStream::new()
176 };
177
169 let pname = format_ident!("{}", p.name); 178 let pname = format_ident!("{}", p.name);
170 let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase()); 179 let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase());
171 let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); 180 let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
@@ -180,7 +189,8 @@ fn main() {
180 } 189 }
181 fn enable() { 190 fn enable() {
182 critical_section::with(|_| unsafe { 191 critical_section::with(|_| unsafe {
183 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)) 192 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
193 #after_enable
184 }) 194 })
185 } 195 }
186 fn disable() { 196 fn disable() {
diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs
new file mode 100644
index 000000000..bece046f8
--- /dev/null
+++ b/embassy-stm32/src/rcc/f2.rs
@@ -0,0 +1,303 @@
1use core::ops::Div;
2
3use crate::pac::flash::vals::Latency;
4use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
5use crate::pac::{FLASH, RCC};
6use crate::rcc::{set_freqs, Clocks};
7use crate::time::Hertz;
8
9/// HSI speed
10pub const HSI: Hertz = Hertz(16_000_000);
11
12/// System clock mux source
13#[derive(Clone, Copy)]
14pub enum ClockSrc {
15 HSE(Hertz, HSESrc),
16 HSI,
17}
18
19/// HSE clock source
20#[derive(Clone, Copy)]
21pub enum HSESrc {
22 /// Crystal/ceramic resonator
23 Crystal,
24 /// External clock source, HSE bypassed
25 Bypass,
26}
27
28/// AHB prescaler
29#[derive(Clone, Copy, PartialEq)]
30pub enum AHBPrescaler {
31 NotDivided,
32 Div2,
33 Div4,
34 Div8,
35 Div16,
36 Div64,
37 Div128,
38 Div256,
39 Div512,
40}
41
42impl Div<AHBPrescaler> for Hertz {
43 type Output = Hertz;
44
45 fn div(self, rhs: AHBPrescaler) -> Self::Output {
46 let divisor = match rhs {
47 AHBPrescaler::NotDivided => 1,
48 AHBPrescaler::Div2 => 2,
49 AHBPrescaler::Div4 => 4,
50 AHBPrescaler::Div8 => 8,
51 AHBPrescaler::Div16 => 16,
52 AHBPrescaler::Div64 => 64,
53 AHBPrescaler::Div128 => 128,
54 AHBPrescaler::Div256 => 256,
55 AHBPrescaler::Div512 => 512,
56 };
57 Hertz(self.0 / divisor)
58 }
59}
60
61/// APB prescaler
62#[derive(Clone, Copy)]
63pub enum APBPrescaler {
64 NotDivided,
65 Div2,
66 Div4,
67 Div8,
68 Div16,
69}
70
71impl Div<APBPrescaler> for Hertz {
72 type Output = Hertz;
73
74 fn div(self, rhs: APBPrescaler) -> Self::Output {
75 let divisor = match rhs {
76 APBPrescaler::NotDivided => 1,
77 APBPrescaler::Div2 => 2,
78 APBPrescaler::Div4 => 4,
79 APBPrescaler::Div8 => 8,
80 APBPrescaler::Div16 => 16,
81 };
82 Hertz(self.0 / divisor)
83 }
84}
85
86impl Into<Ppre> for APBPrescaler {
87 fn into(self) -> Ppre {
88 match self {
89 APBPrescaler::NotDivided => Ppre::DIV1,
90 APBPrescaler::Div2 => Ppre::DIV2,
91 APBPrescaler::Div4 => Ppre::DIV4,
92 APBPrescaler::Div8 => Ppre::DIV8,
93 APBPrescaler::Div16 => Ppre::DIV16,
94 }
95 }
96}
97
98impl Into<Hpre> for AHBPrescaler {
99 fn into(self) -> Hpre {
100 match self {
101 AHBPrescaler::NotDivided => Hpre::DIV1,
102 AHBPrescaler::Div2 => Hpre::DIV2,
103 AHBPrescaler::Div4 => Hpre::DIV4,
104 AHBPrescaler::Div8 => Hpre::DIV8,
105 AHBPrescaler::Div16 => Hpre::DIV16,
106 AHBPrescaler::Div64 => Hpre::DIV64,
107 AHBPrescaler::Div128 => Hpre::DIV128,
108 AHBPrescaler::Div256 => Hpre::DIV256,
109 AHBPrescaler::Div512 => Hpre::DIV512,
110 }
111 }
112}
113
114/// Voltage Range
115///
116/// Represents the system supply voltage range
117#[derive(Copy, Clone, PartialEq)]
118pub enum VoltageRange {
119 /// 1.8 to 3.6 V
120 Min1V8,
121 /// 2.1 to 3.6 V
122 Min2V1,
123 /// 2.4 to 3.6 V
124 Min2V4,
125 /// 2.7 to 3.6 V
126 Min2V7,
127}
128
129impl VoltageRange {
130 const fn wait_states(&self, ahb_freq: Hertz) -> Option<Latency> {
131 let ahb_freq = ahb_freq.0;
132 // Reference: RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock
133 // frequency
134 match self {
135 VoltageRange::Min1V8 => {
136 if ahb_freq <= 16_000_000 {
137 Some(Latency::WS0)
138 } else if ahb_freq <= 32_000_000 {
139 Some(Latency::WS1)
140 } else if ahb_freq <= 48_000_000 {
141 Some(Latency::WS2)
142 } else if ahb_freq <= 64_000_000 {
143 Some(Latency::WS3)
144 } else if ahb_freq <= 80_000_000 {
145 Some(Latency::WS4)
146 } else if ahb_freq <= 96_000_000 {
147 Some(Latency::WS5)
148 } else if ahb_freq <= 112_000_000 {
149 Some(Latency::WS6)
150 } else if ahb_freq <= 120_000_000 {
151 Some(Latency::WS7)
152 } else {
153 None
154 }
155 }
156 VoltageRange::Min2V1 => {
157 if ahb_freq <= 18_000_000 {
158 Some(Latency::WS0)
159 } else if ahb_freq <= 36_000_000 {
160 Some(Latency::WS1)
161 } else if ahb_freq <= 54_000_000 {
162 Some(Latency::WS2)
163 } else if ahb_freq <= 72_000_000 {
164 Some(Latency::WS3)
165 } else if ahb_freq <= 90_000_000 {
166 Some(Latency::WS4)
167 } else if ahb_freq <= 108_000_000 {
168 Some(Latency::WS5)
169 } else if ahb_freq <= 120_000_000 {
170 Some(Latency::WS6)
171 } else {
172 None
173 }
174 }
175 VoltageRange::Min2V4 => {
176 if ahb_freq <= 24_000_000 {
177 Some(Latency::WS0)
178 } else if ahb_freq <= 48_000_000 {
179 Some(Latency::WS1)
180 } else if ahb_freq <= 72_000_000 {
181 Some(Latency::WS2)
182 } else if ahb_freq <= 96_000_000 {
183 Some(Latency::WS3)
184 } else if ahb_freq <= 120_000_000 {
185 Some(Latency::WS4)
186 } else {
187 None
188 }
189 }
190 VoltageRange::Min2V7 => {
191 if ahb_freq <= 30_000_000 {
192 Some(Latency::WS0)
193 } else if ahb_freq <= 60_000_000 {
194 Some(Latency::WS1)
195 } else if ahb_freq <= 90_000_000 {
196 Some(Latency::WS2)
197 } else if ahb_freq <= 120_000_000 {
198 Some(Latency::WS3)
199 } else {
200 None
201 }
202 }
203 }
204 }
205}
206
207/// Clocks configuration
208pub struct Config {
209 pub mux: ClockSrc,
210 pub voltage: VoltageRange,
211 pub ahb_pre: AHBPrescaler,
212 pub apb1_pre: APBPrescaler,
213 pub apb2_pre: APBPrescaler,
214}
215
216impl Default for Config {
217 #[inline]
218 fn default() -> Config {
219 Config {
220 voltage: VoltageRange::Min1V8,
221 mux: ClockSrc::HSI,
222 ahb_pre: AHBPrescaler::NotDivided,
223 apb1_pre: APBPrescaler::NotDivided,
224 apb2_pre: APBPrescaler::NotDivided,
225 }
226 }
227}
228
229#[inline]
230unsafe fn enable_hse(source: HSESrc) {
231 RCC.cr().write(|w| {
232 w.set_hsebyp(match source {
233 HSESrc::Bypass => true,
234 HSESrc::Crystal => false,
235 });
236 w.set_hseon(true)
237 });
238 while !RCC.cr().read().hserdy() {}
239}
240
241pub(crate) unsafe fn init(config: Config) {
242 let (sys_clk, sw) = match config.mux {
243 ClockSrc::HSI => {
244 // Enable HSI
245 RCC.cr().write(|w| w.set_hsion(true));
246 while !RCC.cr().read().hsirdy() {}
247
248 (HSI, Sw::HSI)
249 }
250 ClockSrc::HSE(freq, source) => {
251 enable_hse(source);
252 (freq, Sw::HSE)
253 }
254 };
255 // RM0033 Figure 9. Clock tree suggests max SYSCLK/HCLK is 168 MHz, but datasheet specifies PLL
256 // max output to be 120 MHz, so there's no way to get higher frequencies
257 assert!(sys_clk <= Hertz(120_000_000));
258
259 let ahb_freq = sys_clk / config.ahb_pre;
260 // Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
261 assert!(ahb_freq <= Hertz(120_000_000));
262
263 let flash_ws = config.voltage.wait_states(ahb_freq).expect("Invalid HCLK");
264 FLASH.acr().modify(|w| w.set_latency(flash_ws));
265
266 RCC.cfgr().modify(|w| {
267 w.set_sw(sw.into());
268 w.set_hpre(config.ahb_pre.into());
269 w.set_ppre1(config.apb1_pre.into());
270 w.set_ppre2(config.apb2_pre.into());
271 });
272
273 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
274 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
275 pre => {
276 let freq = ahb_freq / pre;
277 (freq, Hertz(freq.0 * 2))
278 }
279 };
280 // Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
281 assert!(apb1_freq <= Hertz(30_000_000));
282
283 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
284 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
285 pre => {
286 let freq = ahb_freq / pre;
287 (freq, Hertz(freq.0 * 2))
288 }
289 };
290 // Reference: STM32F215xx/217xx datasheet Table 13. General operating conditions
291 assert!(apb2_freq <= Hertz(60_000_000));
292
293 set_freqs(Clocks {
294 sys: sys_clk,
295 ahb1: ahb_freq,
296 ahb2: ahb_freq,
297 ahb3: ahb_freq,
298 apb1: apb1_freq,
299 apb1_tim: apb1_tim_freq,
300 apb2: apb2_freq,
301 apb2_tim: apb2_tim_freq,
302 });
303}
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 01c66f76f..3090b416c 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -5,6 +5,7 @@ use core::mem::MaybeUninit;
5 5
6#[cfg_attr(rcc_f0, path = "f0.rs")] 6#[cfg_attr(rcc_f0, path = "f0.rs")]
7#[cfg_attr(rcc_f1, path = "f1.rs")] 7#[cfg_attr(rcc_f1, path = "f1.rs")]
8#[cfg_attr(rcc_f2, path = "f2.rs")]
8#[cfg_attr(rcc_f3, path = "f3.rs")] 9#[cfg_attr(rcc_f3, path = "f3.rs")]
9#[cfg_attr(any(rcc_f4, rcc_f410), path = "f4.rs")] 10#[cfg_attr(any(rcc_f4, rcc_f410), path = "f4.rs")]
10#[cfg_attr(rcc_f7, path = "f7.rs")] 11#[cfg_attr(rcc_f7, path = "f7.rs")]
@@ -39,11 +40,11 @@ pub struct Clocks {
39 // AHB 40 // AHB
40 pub ahb1: Hertz, 41 pub ahb1: Hertz,
41 #[cfg(any( 42 #[cfg(any(
42 rcc_l4, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb, rcc_wl5 43 rcc_l4, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb, rcc_wl5
43 ))] 44 ))]
44 pub ahb2: Hertz, 45 pub ahb2: Hertz,
45 #[cfg(any( 46 #[cfg(any(
46 rcc_l4, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_u5, rcc_wb, rcc_wl5 47 rcc_l4, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7ab, rcc_u5, rcc_wb, rcc_wl5
47 ))] 48 ))]
48 pub ahb3: Hertz, 49 pub ahb3: Hertz,
49 #[cfg(any(rcc_h7, rcc_h7ab))] 50 #[cfg(any(rcc_h7, rcc_h7ab))]
diff --git a/examples/stm32f2/.cargo/config b/examples/stm32f2/.cargo/config
new file mode 100644
index 000000000..30b6d1909
--- /dev/null
+++ b/examples/stm32f2/.cargo/config
@@ -0,0 +1,6 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace STM32F207ZGTx with your chip as listed in `probe-run --list-chips`
3runner = "probe-run --chip STM32F207ZGTx"
4
5[build]
6target = "thumbv7m-none-eabi"
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml
new file mode 100644
index 000000000..ee1d7ce2b
--- /dev/null
+++ b/examples/stm32f2/Cargo.toml
@@ -0,0 +1,21 @@
1[package]
2authors = ["Dario Nieuwenhuis <[email protected]>"]
3edition = "2018"
4name = "embassy-stm32f2-examples"
5version = "0.1.0"
6resolver = "2"
7
8[dependencies]
9embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
11
12defmt = "0.3"
13defmt-rtt = "0.3"
14
15cortex-m = "0.7.3"
16cortex-m-rt = "0.7.0"
17embedded-hal = "0.2.6"
18panic-probe = { version = "0.3", features = ["print-defmt"] }
19futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
20heapless = { version = "0.7.5", default-features = false }
21nb = "1.0.0"
diff --git a/examples/stm32f2/build.rs b/examples/stm32f2/build.rs
new file mode 100644
index 000000000..8cd32d7ed
--- /dev/null
+++ b/examples/stm32f2/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/stm32f2/src/bin/blinky.rs b/examples/stm32f2/src/bin/blinky.rs
new file mode 100644
index 000000000..637c2f4fd
--- /dev/null
+++ b/examples/stm32f2/src/bin/blinky.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;
7
8use embassy::executor::Spawner;
9use embassy::time::{Duration, Timer};
10use embassy_stm32::gpio::{Level, Output, Speed};
11use embassy_stm32::Peripherals;
12use example_common::*;
13
14#[embassy::main]
15async fn main(_spawner: Spawner, p: Peripherals) {
16 info!("Hello World!");
17
18 let mut led = Output::new(p.PB14, Level::High, Speed::Low);
19
20 loop {
21 info!("high");
22 led.set_high();
23 Timer::after(Duration::from_millis(1000)).await;
24
25 info!("low");
26 led.set_low();
27 Timer::after(Duration::from_millis(1000)).await;
28 }
29}
diff --git a/examples/stm32f2/src/example_common.rs b/examples/stm32f2/src/example_common.rs
new file mode 100644
index 000000000..e14517033
--- /dev/null
+++ b/examples/stm32f2/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-gen-features/src/lib.rs b/stm32-gen-features/src/lib.rs
index 1ab4865a4..d184827cc 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 "stm32f2",
8 "stm32f3", 9 "stm32f3",
9 "stm32f4", 10 "stm32f4",
10 "stm32f7", 11 "stm32f7",
@@ -52,7 +53,7 @@ impl FilterSupported for &[(String, Vec<String>)] {
52/// 53///
53/// This function is slow because all the yaml files are parsed. 54/// This function is slow because all the yaml files are parsed.
54pub fn chip_names_and_cores() -> Vec<(String, Vec<String>)> { 55pub fn chip_names_and_cores() -> Vec<(String, Vec<String>)> {
55 glob::glob("../stm32-data/data/chips/*.yaml") 56 glob::glob("../stm32-data/data/chips/*.json")
56 .unwrap() 57 .unwrap()
57 .filter_map(|entry| entry.map_err(|e| eprintln!("{:?}", e)).ok()) 58 .filter_map(|entry| entry.map_err(|e| eprintln!("{:?}", e)).ok())
58 .filter_map(|entry| { 59 .filter_map(|entry| {