aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-11-09 14:00:25 +0000
committerGitHub <[email protected]>2021-11-09 14:00:25 +0000
commitfc75e0ec573267d7b97698ea140e1533e356e012 (patch)
tree5fd2767c6067f5a4e59a6c6b5b75287432ccd6d7
parentdb889da0446833ff219e652bd68c397af858b999 (diff)
parent12a64b867b22003ea42e9706f6a77f36bd00a814 (diff)
Merge #481
481: Stm32u5 r=Dirbaio a=bobmcwhirter Co-authored-by: Bob McWhirter <[email protected]>
-rw-r--r--embassy-stm32/src/pwr/u5.rs31
-rw-r--r--embassy-stm32/src/rcc/u5/mod.rs507
-rw-r--r--examples/stm32u5/.cargo/config.toml3
-rw-r--r--examples/stm32u5/Cargo.toml8
m---------stm32-data0
5 files changed, 543 insertions, 6 deletions
diff --git a/embassy-stm32/src/pwr/u5.rs b/embassy-stm32/src/pwr/u5.rs
index 8b1378917..a90659d9c 100644
--- a/embassy-stm32/src/pwr/u5.rs
+++ b/embassy-stm32/src/pwr/u5.rs
@@ -1 +1,32 @@
1use crate::peripherals;
1 2
3/// Voltage Scale
4///
5/// Represents the voltage range feeding the CPU core. The maximum core
6/// clock frequency depends on this value.
7#[derive(Copy, Clone, PartialEq)]
8pub enum VoltageScale {
9 // Highest frequency
10 Range1,
11 Range2,
12 Range3,
13 // Lowest power
14 Range4,
15}
16
17/// Power Configuration
18///
19/// Generated when the PWR peripheral is frozen. The existence of this
20/// value indicates that the voltage scaling configuration can no
21/// longer be changed.
22pub struct Power {
23 pub(crate) vos: VoltageScale,
24}
25
26impl Power {
27 pub fn new(_peri: peripherals::PWR) -> Self {
28 Self {
29 vos: VoltageScale::Range4,
30 }
31 }
32}
diff --git a/embassy-stm32/src/rcc/u5/mod.rs b/embassy-stm32/src/rcc/u5/mod.rs
index dbf5e8dfb..6e68b2205 100644
--- a/embassy-stm32/src/rcc/u5/mod.rs
+++ b/embassy-stm32/src/rcc/u5/mod.rs
@@ -1,8 +1,295 @@
1pub struct Config {} 1use crate::pac;
2use crate::peripherals::{self, RCC};
3use crate::pwr::{Power, VoltageScale};
4use crate::rcc::{set_freqs, Clocks};
5use crate::time::{Hertz, U32Ext};
6use stm32_metapac::rcc::vals::{Hpre, Msirange, Msirgsel, Pllm, Pllsrc, Ppre, Sw};
7
8/// HSI16 speed
9pub const HSI16_FREQ: u32 = 16_000_000;
10
11#[derive(Copy, Clone)]
12pub enum ClockSrc {
13 MSI(MSIRange),
14 HSE(Hertz),
15 HSI16,
16 PLL1R(PllSrc, PllM, PllN, PllClkDiv),
17}
18
19#[derive(Clone, Copy, Debug)]
20pub enum PllSrc {
21 MSI(MSIRange),
22 HSE(Hertz),
23 HSI16,
24}
25
26impl Into<Pllsrc> for PllSrc {
27 fn into(self) -> Pllsrc {
28 match self {
29 PllSrc::MSI(..) => Pllsrc::MSIS,
30 PllSrc::HSE(..) => Pllsrc::HSE,
31 PllSrc::HSI16 => Pllsrc::HSI16,
32 }
33 }
34}
35
36seq_macro::seq!(N in 2..=128 {
37 #[derive(Copy, Clone, Debug)]
38 pub enum PllClkDiv {
39 NotDivided,
40 #(
41 Div#N = (N-1),
42 )*
43 }
44
45 impl PllClkDiv {
46 fn to_div(&self) -> u8 {
47 match self {
48 PllClkDiv::NotDivided => 1,
49 #(
50 PllClkDiv::Div#N => (N + 1),
51 )*
52 }
53 }
54 }
55});
56
57impl Into<u8> for PllClkDiv {
58 fn into(self) -> u8 {
59 (self as u8) + 1
60 }
61}
62
63seq_macro::seq!(N in 4..=512 {
64 #[derive(Copy, Clone, Debug)]
65 pub enum PllN {
66 NotMultiplied,
67 #(
68 Mul#N = (N-1),
69 )*
70 }
71
72 impl PllN {
73 fn to_mul(&self) -> u16 {
74 match self {
75 PllN::NotMultiplied => 1,
76 #(
77 PllN::Mul#N => (N + 1),
78 )*
79 }
80 }
81 }
82});
83
84impl Into<u16> for PllN {
85 fn into(self) -> u16 {
86 (self as u16) + 1
87 }
88}
89
90// Pre-division
91#[derive(Copy, Clone, Debug)]
92pub enum PllM {
93 NotDivided = 0b0000,
94 Div2 = 0b0001,
95 Div3 = 0b0010,
96 Div4 = 0b0011,
97 Div5 = 0b0100,
98 Div6 = 0b0101,
99 Div7 = 0b0110,
100 Div8 = 0b0111,
101 Div9 = 0b1000,
102 Div10 = 0b1001,
103 Div11 = 0b1010,
104 Div12 = 0b1011,
105 Div13 = 0b1100,
106 Div14 = 0b1101,
107 Div15 = 0b1110,
108 Div16 = 0b1111,
109}
110
111impl Into<Pllm> for PllM {
112 fn into(self) -> Pllm {
113 Pllm(self as u8)
114 }
115}
116
117/// AHB prescaler
118#[derive(Clone, Copy, PartialEq)]
119pub enum AHBPrescaler {
120 NotDivided,
121 Div2,
122 Div4,
123 Div8,
124 Div16,
125 Div64,
126 Div128,
127 Div256,
128 Div512,
129}
130
131impl Into<Hpre> for AHBPrescaler {
132 fn into(self) -> Hpre {
133 match self {
134 AHBPrescaler::NotDivided => Hpre::NONE,
135 AHBPrescaler::Div2 => Hpre::DIV2,
136 AHBPrescaler::Div4 => Hpre::DIV4,
137 AHBPrescaler::Div8 => Hpre::DIV8,
138 AHBPrescaler::Div16 => Hpre::DIV16,
139 AHBPrescaler::Div64 => Hpre::DIV64,
140 AHBPrescaler::Div128 => Hpre::DIV128,
141 AHBPrescaler::Div256 => Hpre::DIV256,
142 AHBPrescaler::Div512 => Hpre::DIV512,
143 }
144 }
145}
146
147impl Into<u8> for AHBPrescaler {
148 fn into(self) -> u8 {
149 match self {
150 AHBPrescaler::NotDivided => 1,
151 AHBPrescaler::Div2 => 0x08,
152 AHBPrescaler::Div4 => 0x09,
153 AHBPrescaler::Div8 => 0x0a,
154 AHBPrescaler::Div16 => 0x0b,
155 AHBPrescaler::Div64 => 0x0c,
156 AHBPrescaler::Div128 => 0x0d,
157 AHBPrescaler::Div256 => 0x0e,
158 AHBPrescaler::Div512 => 0x0f,
159 }
160 }
161}
162
163impl Default for AHBPrescaler {
164 fn default() -> Self {
165 AHBPrescaler::NotDivided
166 }
167}
168
169/// APB prescaler
170#[derive(Clone, Copy)]
171pub enum APBPrescaler {
172 NotDivided,
173 Div2,
174 Div4,
175 Div8,
176 Div16,
177}
178
179impl Into<Ppre> for APBPrescaler {
180 fn into(self) -> Ppre {
181 match self {
182 APBPrescaler::NotDivided => Ppre::NONE,
183 APBPrescaler::Div2 => Ppre::DIV2,
184 APBPrescaler::Div4 => Ppre::DIV4,
185 APBPrescaler::Div8 => Ppre::DIV8,
186 APBPrescaler::Div16 => Ppre::DIV16,
187 }
188 }
189}
190
191impl Default for APBPrescaler {
192 fn default() -> Self {
193 APBPrescaler::NotDivided
194 }
195}
196
197impl Into<u8> for APBPrescaler {
198 fn into(self) -> u8 {
199 match self {
200 APBPrescaler::NotDivided => 1,
201 APBPrescaler::Div2 => 0x04,
202 APBPrescaler::Div4 => 0x05,
203 APBPrescaler::Div8 => 0x06,
204 APBPrescaler::Div16 => 0x07,
205 }
206 }
207}
208
209impl Into<Sw> for ClockSrc {
210 fn into(self) -> Sw {
211 match self {
212 ClockSrc::MSI(..) => Sw::MSIS,
213 ClockSrc::HSE(..) => Sw::HSE,
214 ClockSrc::HSI16 => Sw::HSI16,
215 ClockSrc::PLL1R(..) => Sw::PLL1R,
216 }
217 }
218}
219
220#[derive(Debug, Copy, Clone)]
221pub enum MSIRange {
222 Range48mhz = 48_000_000,
223 Range24mhz = 24_000_000,
224 Range16mhz = 16_000_000,
225 Range12mhz = 12_000_000,
226 Range4mhz = 4_000_000,
227 Range2mhz = 2_000_000,
228 Range1_33mhz = 1_330_000,
229 Range1mhz = 1_000_000,
230 Range3_072mhz = 3_072_000,
231 Range1_536mhz = 1_536_000,
232 Range1_024mhz = 1_024_000,
233 Range768khz = 768_000,
234 Range400khz = 400_000,
235 Range200khz = 200_000,
236 Range133khz = 133_000,
237 Range100khz = 100_000,
238}
239
240impl Into<u32> for MSIRange {
241 fn into(self) -> u32 {
242 self as u32
243 }
244}
245
246impl Into<Msirange> for MSIRange {
247 fn into(self) -> Msirange {
248 match self {
249 MSIRange::Range48mhz => Msirange::RANGE_48MHZ,
250 MSIRange::Range24mhz => Msirange::RANGE_24MHZ,
251 MSIRange::Range16mhz => Msirange::RANGE_16MHZ,
252 MSIRange::Range12mhz => Msirange::RANGE_12MHZ,
253 MSIRange::Range4mhz => Msirange::RANGE_4MHZ,
254 MSIRange::Range2mhz => Msirange::RANGE_2MHZ,
255 MSIRange::Range1_33mhz => Msirange::RANGE_1_33MHZ,
256 MSIRange::Range1mhz => Msirange::RANGE_1MHZ,
257 MSIRange::Range3_072mhz => Msirange::RANGE_3_072MHZ,
258 MSIRange::Range1_536mhz => Msirange::RANGE_1_536MHZ,
259 MSIRange::Range1_024mhz => Msirange::RANGE_1_024MHZ,
260 MSIRange::Range768khz => Msirange::RANGE_768KHZ,
261 MSIRange::Range400khz => Msirange::RANGE_400KHZ,
262 MSIRange::Range200khz => Msirange::RANGE_200KHZ,
263 MSIRange::Range133khz => Msirange::RANGE_133KHZ,
264 MSIRange::Range100khz => Msirange::RANGE_100KHZ,
265 }
266 }
267}
268
269impl Default for MSIRange {
270 fn default() -> Self {
271 MSIRange::Range4mhz
272 }
273}
274
275#[derive(Copy, Clone)]
276pub struct Config {
277 mux: ClockSrc,
278 ahb_pre: AHBPrescaler,
279 apb1_pre: APBPrescaler,
280 apb2_pre: APBPrescaler,
281 apb3_pre: APBPrescaler,
282}
2 283
3impl Config { 284impl Config {
4 pub fn new() -> Self { 285 pub fn new() -> Self {
5 Config {} 286 Config {
287 mux: ClockSrc::MSI(MSIRange::default()),
288 ahb_pre: Default::default(),
289 apb1_pre: Default::default(),
290 apb2_pre: Default::default(),
291 apb3_pre: Default::default(),
292 }
6 } 293 }
7} 294}
8 295
@@ -12,4 +299,218 @@ impl Default for Config {
12 } 299 }
13} 300}
14 301
15pub unsafe fn init(_config: Config) {} 302/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
303pub trait RccExt {
304 fn freeze(self, config: Config, power: &Power) -> Clocks;
305}
306
307impl RccExt for RCC {
308 #[inline]
309 fn freeze(self, cfgr: Config, power: &Power) -> Clocks {
310 let rcc = pac::RCC;
311
312 let sys_clk = match cfgr.mux {
313 ClockSrc::MSI(range) => {
314 unsafe {
315 rcc.icscr1().modify(|w| {
316 let bits: Msirange = range.into();
317 w.set_msisrange(bits);
318 w.set_msirgsel(Msirgsel::RCC_ICSCR1);
319 });
320 rcc.cr().write(|w| {
321 w.set_msipllen(false);
322 w.set_msison(true);
323 w.set_msison(true);
324 });
325 while !rcc.cr().read().msisrdy() {}
326 }
327
328 range.into()
329 }
330 ClockSrc::HSE(freq) => {
331 unsafe {
332 rcc.cr().write(|w| w.set_hseon(true));
333 while !rcc.cr().read().hserdy() {}
334 }
335
336 freq.0
337 }
338 ClockSrc::HSI16 => {
339 unsafe {
340 rcc.cr().write(|w| w.set_hsion(true));
341 while !rcc.cr().read().hsirdy() {}
342 }
343
344 HSI16_FREQ
345 }
346 ClockSrc::PLL1R(src, m, n, div) => {
347 let freq = match src {
348 PllSrc::MSI(_) => MSIRange::default().into(),
349 PllSrc::HSE(hertz) => hertz.0,
350 PllSrc::HSI16 => HSI16_FREQ,
351 };
352
353 // disable
354 unsafe {
355 rcc.cr().modify(|w| w.set_pllon(0, false));
356 while rcc.cr().read().pllrdy(0) {}
357 }
358
359 let vco = freq * n as u8 as u32;
360 let pll_ck = vco / (div as u8 as u32 + 1);
361
362 unsafe {
363 rcc.pll1cfgr().write(|w| {
364 w.set_pllm(m.into());
365 w.set_pllsrc(src.into());
366 });
367
368 rcc.pll1divr().modify(|w| {
369 w.set_pllr(div.to_div());
370 w.set_plln(n.to_mul());
371 });
372
373 // Enable PLL
374 rcc.cr().modify(|w| w.set_pllon(0, true));
375 while !rcc.cr().read().pllrdy(0) {}
376 rcc.pll1cfgr().modify(|w| w.set_pllren(true));
377 }
378
379 unsafe {
380 rcc.cr().write(|w| w.set_pllon(0, true));
381 while !rcc.cr().read().pllrdy(0) {}
382 }
383
384 pll_ck
385 }
386 };
387
388 // states and programming delay
389 let wait_states = match power.vos {
390 // VOS 0 range VCORE 1.26V - 1.40V
391 VoltageScale::Range1 => {
392 if sys_clk < 32_000_000 {
393 0
394 } else if sys_clk < 64_000_000 {
395 1
396 } else if sys_clk < 96_000_000 {
397 2
398 } else if sys_clk < 128_000_000 {
399 3
400 } else {
401 4
402 }
403 }
404 // VOS 1 range VCORE 1.15V - 1.26V
405 VoltageScale::Range2 => {
406 if sys_clk < 30_000_000 {
407 0
408 } else if sys_clk < 60_000_000 {
409 1
410 } else if sys_clk < 90_000_000 {
411 2
412 } else {
413 3
414 }
415 }
416 // VOS 2 range VCORE 1.05V - 1.15V
417 VoltageScale::Range3 => {
418 if sys_clk < 24_000_000 {
419 0
420 } else if sys_clk < 48_000_000 {
421 1
422 } else {
423 2
424 }
425 }
426 // VOS 3 range VCORE 0.95V - 1.05V
427 VoltageScale::Range4 => {
428 if sys_clk < 12_000_000 {
429 0
430 } else {
431 1
432 }
433 }
434 };
435
436 unsafe {
437 pac::FLASH.acr().modify(|w| {
438 w.set_latency(wait_states);
439 })
440 }
441
442 unsafe {
443 rcc.cfgr1().modify(|w| {
444 w.set_sw(cfgr.mux.into());
445 });
446
447 rcc.cfgr2().modify(|w| {
448 w.set_hpre(cfgr.ahb_pre.into());
449 w.set_ppre1(cfgr.apb1_pre.into());
450 w.set_ppre2(cfgr.apb2_pre.into());
451 });
452
453 rcc.cfgr3().modify(|w| {
454 w.set_ppre3(cfgr.apb3_pre.into());
455 });
456 }
457
458 let ahb_freq: u32 = match cfgr.ahb_pre {
459 AHBPrescaler::NotDivided => sys_clk,
460 pre => {
461 let pre: u8 = pre.into();
462 let pre = 1 << (pre as u32 - 7);
463 sys_clk / pre
464 }
465 };
466
467 let (apb1_freq, apb1_tim_freq) = match cfgr.apb1_pre {
468 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
469 pre => {
470 let pre: u8 = pre.into();
471 let pre: u8 = 1 << (pre - 3);
472 let freq = ahb_freq / pre as u32;
473 (freq, freq * 2)
474 }
475 };
476
477 let (apb2_freq, apb2_tim_freq) = match cfgr.apb2_pre {
478 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
479 pre => {
480 let pre: u8 = pre.into();
481 let pre: u8 = 1 << (pre - 3);
482 let freq = ahb_freq / (1 << (pre as u8 - 3));
483 (freq, freq * 2)
484 }
485 };
486
487 let (apb3_freq, _apb3_tim_freq) = match cfgr.apb3_pre {
488 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
489 pre => {
490 let pre: u8 = pre.into();
491 let pre: u8 = 1 << (pre - 3);
492 let freq = ahb_freq / (1 << (pre as u8 - 3));
493 (freq, freq * 2)
494 }
495 };
496
497 Clocks {
498 sys: sys_clk.hz(),
499 ahb1: ahb_freq.hz(),
500 ahb2: ahb_freq.hz(),
501 ahb3: ahb_freq.hz(),
502 apb1: apb1_freq.hz(),
503 apb2: apb2_freq.hz(),
504 apb3: apb3_freq.hz(),
505 apb1_tim: apb1_tim_freq.hz(),
506 apb2_tim: apb2_tim_freq.hz(),
507 }
508 }
509}
510
511pub unsafe fn init(config: Config) {
512 let r = <peripherals::RCC as embassy::util::Steal>::steal();
513 let power = Power::new(<peripherals::PWR as embassy::util::Steal>::steal());
514 let clocks = r.freeze(config, &power);
515 set_freqs(clocks);
516}
diff --git a/examples/stm32u5/.cargo/config.toml b/examples/stm32u5/.cargo/config.toml
index ba3ef1dc5..9f5e14801 100644
--- a/examples/stm32u5/.cargo/config.toml
+++ b/examples/stm32u5/.cargo/config.toml
@@ -1,6 +1,7 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))'] 1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace STM32F429ZITx with your chip as listed in `probe-run --list-chips` 2# replace STM32F429ZITx with your chip as listed in `probe-run --list-chips`
3runner = "probe-run --chip STM32U585AIIx" 3#runner = "probe-run --chip STM32U585AIIx"
4runner = "/Users/bob/outboard-repos/probe-run/target/debug/probe-run-rp --chip STM32U585AIIx"
4 5
5[build] 6[build]
6target = "thumbv7em-none-eabi" 7target = "thumbv7em-none-eabi"
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml
index b3c3c9700..e84e1992f 100644
--- a/examples/stm32u5/Cargo.toml
+++ b/examples/stm32u5/Cargo.toml
@@ -22,8 +22,8 @@ embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features =
22embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "unstable-pac", "stm32u585ai", "memory-x" ] } 22embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "unstable-pac", "stm32u585ai", "memory-x" ] }
23embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } 23embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" }
24 24
25defmt = "0.2.3" 25defmt = "0.2"
26defmt-rtt = "0.2.0" 26defmt-rtt = "0.2"
27 27
28cortex-m = "0.7.3" 28cortex-m = "0.7.3"
29cortex-m-rt = "0.7.0" 29cortex-m-rt = "0.7.0"
@@ -35,3 +35,7 @@ heapless = { version = "0.7.5", default-features = false }
35 35
36micromath = "2.0.0" 36micromath = "2.0.0"
37 37
38#[patch.crates-io]
39#defmt = { git="https://github.com/knurling-rs/defmt.git" }
40#defmt-rtt = { git="https://github.com/knurling-rs/defmt.git" }
41
diff --git a/stm32-data b/stm32-data
Subproject e106785ebae82f43c4abd33b9a3f3ea3b31d608 Subproject 103d86c0558b5ce90ab4765f87b5e756b55312f