aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob McWhirter <[email protected]>2021-11-08 14:20:31 -0500
committerBob McWhirter <[email protected]>2021-11-08 14:20:51 -0500
commit5f124ec49f82ae2a4163edb6f1a8bad7898ba823 (patch)
treeb5f2313e4544638a75d322eb595172801c7160ad
parentdb889da0446833ff219e652bd68c397af858b999 (diff)
Update U5 to init RCC.
-rw-r--r--embassy-stm32/src/pwr/u5.rs32
-rw-r--r--embassy-stm32/src/rcc/u5/mod.rs513
-rw-r--r--examples/stm32u5/.cargo/config.toml3
-rw-r--r--examples/stm32u5/Cargo.toml8
m---------stm32-data0
5 files changed, 550 insertions, 6 deletions
diff --git a/embassy-stm32/src/pwr/u5.rs b/embassy-stm32/src/pwr/u5.rs
index 8b1378917..b4b01ea39 100644
--- a/embassy-stm32/src/pwr/u5.rs
+++ b/embassy-stm32/src/pwr/u5.rs
@@ -1 +1,33 @@
1use crate::pac::{PWR, RCC, SYSCFG};
2use crate::peripherals;
1 3
4/// Voltage Scale
5///
6/// Represents the voltage range feeding the CPU core. The maximum core
7/// clock frequency depends on this value.
8#[derive(Copy, Clone, PartialEq)]
9pub enum VoltageScale {
10 // Highest frequency
11 Range1,
12 Range2,
13 Range3,
14 // Lowest power
15 Range4,
16}
17
18/// Power Configuration
19///
20/// Generated when the PWR peripheral is frozen. The existence of this
21/// value indicates that the voltage scaling configuration can no
22/// longer be changed.
23pub struct Power {
24 pub(crate) vos: VoltageScale,
25}
26
27impl Power {
28 pub fn new(_peri: peripherals::PWR) -> Self {
29 Self {
30 vos: VoltageScale::Range4,
31 }
32 }
33}
diff --git a/embassy-stm32/src/rcc/u5/mod.rs b/embassy-stm32/src/rcc/u5/mod.rs
index dbf5e8dfb..0087f6993 100644
--- a/embassy-stm32/src/rcc/u5/mod.rs
+++ b/embassy-stm32/src/rcc/u5/mod.rs
@@ -1,8 +1,301 @@
1pub struct Config {} 1use crate::pac;
2use crate::peripherals::{self, RCC};
3use crate::pwr::{Power, VoltageScale};
4use crate::rcc::{get_freqs, 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 PllM {
112 fn to_div(&self) -> u32 {
113 (*self as u32) + 1
114 }
115}
116
117impl Into<Pllm> for PllM {
118 fn into(self) -> Pllm {
119 Pllm(self as u8)
120 }
121}
122
123/// AHB prescaler
124#[derive(Clone, Copy, PartialEq)]
125pub enum AHBPrescaler {
126 NotDivided,
127 Div2,
128 Div4,
129 Div8,
130 Div16,
131 Div64,
132 Div128,
133 Div256,
134 Div512,
135}
136
137impl Into<Hpre> for AHBPrescaler {
138 fn into(self) -> Hpre {
139 match self {
140 AHBPrescaler::NotDivided => Hpre::NONE,
141 AHBPrescaler::Div2 => Hpre::DIV2,
142 AHBPrescaler::Div4 => Hpre::DIV4,
143 AHBPrescaler::Div8 => Hpre::DIV8,
144 AHBPrescaler::Div16 => Hpre::DIV16,
145 AHBPrescaler::Div64 => Hpre::DIV64,
146 AHBPrescaler::Div128 => Hpre::DIV128,
147 AHBPrescaler::Div256 => Hpre::DIV256,
148 AHBPrescaler::Div512 => Hpre::DIV512,
149 }
150 }
151}
152
153impl Into<u8> for AHBPrescaler {
154 fn into(self) -> u8 {
155 match self {
156 AHBPrescaler::NotDivided => 1,
157 AHBPrescaler::Div2 => 0x08,
158 AHBPrescaler::Div4 => 0x09,
159 AHBPrescaler::Div8 => 0x0a,
160 AHBPrescaler::Div16 => 0x0b,
161 AHBPrescaler::Div64 => 0x0c,
162 AHBPrescaler::Div128 => 0x0d,
163 AHBPrescaler::Div256 => 0x0e,
164 AHBPrescaler::Div512 => 0x0f,
165 }
166 }
167}
168
169impl Default for AHBPrescaler {
170 fn default() -> Self {
171 AHBPrescaler::NotDivided
172 }
173}
174
175/// APB prescaler
176#[derive(Clone, Copy)]
177pub enum APBPrescaler {
178 NotDivided,
179 Div2,
180 Div4,
181 Div8,
182 Div16,
183}
184
185impl Into<Ppre> for APBPrescaler {
186 fn into(self) -> Ppre {
187 match self {
188 APBPrescaler::NotDivided => Ppre::NONE,
189 APBPrescaler::Div2 => Ppre::DIV2,
190 APBPrescaler::Div4 => Ppre::DIV4,
191 APBPrescaler::Div8 => Ppre::DIV8,
192 APBPrescaler::Div16 => Ppre::DIV16,
193 }
194 }
195}
196
197impl Default for APBPrescaler {
198 fn default() -> Self {
199 APBPrescaler::NotDivided
200 }
201}
202
203impl Into<u8> for APBPrescaler {
204 fn into(self) -> u8 {
205 match self {
206 APBPrescaler::NotDivided => 1,
207 APBPrescaler::Div2 => 0x04,
208 APBPrescaler::Div4 => 0x05,
209 APBPrescaler::Div8 => 0x06,
210 APBPrescaler::Div16 => 0x07,
211 }
212 }
213}
214
215impl Into<Sw> for ClockSrc {
216 fn into(self) -> Sw {
217 match self {
218 ClockSrc::MSI(..) => Sw::MSIS,
219 ClockSrc::HSE(..) => Sw::HSE,
220 ClockSrc::HSI16 => Sw::HSI16,
221 ClockSrc::PLL1R(..) => Sw::PLL1R,
222 }
223 }
224}
225
226#[derive(Debug, Copy, Clone)]
227pub enum MSIRange {
228 Range48mhz = 48_000_000,
229 Range24mhz = 24_000_000,
230 Range16mhz = 16_000_000,
231 Range12mhz = 12_000_000,
232 Range4mhz = 4_000_000,
233 Range2mhz = 2_000_000,
234 Range1_33mhz = 1_330_000,
235 Range1mhz = 1_000_000,
236 Range3_072mhz = 3_072_000,
237 Range1_536mhz = 1_536_000,
238 Range1_024mhz = 1_024_000,
239 Range768khz = 768_000,
240 Range400khz = 400_000,
241 Range200khz = 200_000,
242 Range133khz = 133_000,
243 Range100khz = 100_000,
244}
245
246impl Into<u32> for MSIRange {
247 fn into(self) -> u32 {
248 self as u32
249 }
250}
251
252impl Into<Msirange> for MSIRange {
253 fn into(self) -> Msirange {
254 match self {
255 MSIRange::Range48mhz => Msirange::RANGE_48MHZ,
256 MSIRange::Range24mhz => Msirange::RANGE_24MHZ,
257 MSIRange::Range16mhz => Msirange::RANGE_16MHZ,
258 MSIRange::Range12mhz => Msirange::RANGE_12MHZ,
259 MSIRange::Range4mhz => Msirange::RANGE_4MHZ,
260 MSIRange::Range2mhz => Msirange::RANGE_2MHZ,
261 MSIRange::Range1_33mhz => Msirange::RANGE_1_33MHZ,
262 MSIRange::Range1mhz => Msirange::RANGE_1MHZ,
263 MSIRange::Range3_072mhz => Msirange::RANGE_3_072MHZ,
264 MSIRange::Range1_536mhz => Msirange::RANGE_1_536MHZ,
265 MSIRange::Range1_024mhz => Msirange::RANGE_1_024MHZ,
266 MSIRange::Range768khz => Msirange::RANGE_768KHZ,
267 MSIRange::Range400khz => Msirange::RANGE_400KHZ,
268 MSIRange::Range200khz => Msirange::RANGE_200KHZ,
269 MSIRange::Range133khz => Msirange::RANGE_133KHZ,
270 MSIRange::Range100khz => Msirange::RANGE_100KHZ,
271 }
272 }
273}
274
275impl Default for MSIRange {
276 fn default() -> Self {
277 MSIRange::Range4mhz
278 }
279}
280
281#[derive(Copy, Clone)]
282pub struct Config {
283 mux: ClockSrc,
284 ahb_pre: AHBPrescaler,
285 apb1_pre: APBPrescaler,
286 apb2_pre: APBPrescaler,
287 apb3_pre: APBPrescaler,
288}
2 289
3impl Config { 290impl Config {
4 pub fn new() -> Self { 291 pub fn new() -> Self {
5 Config {} 292 Config {
293 mux: ClockSrc::MSI(MSIRange::default()),
294 ahb_pre: Default::default(),
295 apb1_pre: Default::default(),
296 apb2_pre: Default::default(),
297 apb3_pre: Default::default(),
298 }
6 } 299 }
7} 300}
8 301
@@ -12,4 +305,218 @@ impl Default for Config {
12 } 305 }
13} 306}
14 307
15pub unsafe fn init(_config: Config) {} 308/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
309pub trait RccExt {
310 fn freeze(self, config: Config, power: &Power) -> Clocks;
311}
312
313impl RccExt for RCC {
314 #[inline]
315 fn freeze(self, cfgr: Config, power: &Power) -> Clocks {
316 let rcc = pac::RCC;
317
318 let sys_clk = match cfgr.mux {
319 ClockSrc::MSI(range) => {
320 unsafe {
321 rcc.icscr1().modify(|w| {
322 let bits: Msirange = range.into();
323 w.set_msisrange(bits);
324 w.set_msirgsel(Msirgsel::RCC_ICSCR1);
325 });
326 rcc.cr().write(|w| {
327 w.set_msipllen(false);
328 w.set_msison(true);
329 w.set_msison(true);
330 });
331 while !rcc.cr().read().msisrdy() {}
332 }
333
334 range.into()
335 }
336 ClockSrc::HSE(freq) => {
337 unsafe {
338 rcc.cr().write(|w| w.set_hseon(true));
339 while !rcc.cr().read().hserdy() {}
340 }
341
342 freq.0
343 }
344 ClockSrc::HSI16 => {
345 unsafe {
346 rcc.cr().write(|w| w.set_hsion(true));
347 while !rcc.cr().read().hsirdy() {}
348 }
349
350 HSI16_FREQ
351 }
352 ClockSrc::PLL1R(src, m, n, div) => {
353 let freq = match src {
354 PllSrc::MSI(_) => MSIRange::default().into(),
355 PllSrc::HSE(hertz) => hertz.0,
356 PllSrc::HSI16 => HSI16_FREQ,
357 };
358
359 // disable
360 unsafe {
361 rcc.cr().modify(|w| w.set_pllon(0, false));
362 while rcc.cr().read().pllrdy(0) {}
363 }
364
365 let vco = freq * n as u8 as u32;
366 let pll_ck = vco / (div as u8 as u32 + 1);
367
368 unsafe {
369 rcc.pll1cfgr().write(|w| {
370 w.set_pllm(m.into());
371 w.set_pllsrc(src.into());
372 });
373
374 rcc.pll1divr().modify(|w| {
375 w.set_pllr(div.to_div());
376 w.set_plln(n.to_mul());
377 });
378
379 // Enable PLL
380 rcc.cr().modify(|w| w.set_pllon(0, true));
381 while !rcc.cr().read().pllrdy(0) {}
382 rcc.pll1cfgr().modify(|w| w.set_pllren(true));
383 }
384
385 unsafe {
386 rcc.cr().write(|w| w.set_pllon(0, true));
387 while !rcc.cr().read().pllrdy(0) {}
388 }
389
390 pll_ck
391 }
392 };
393
394 // states and programming delay
395 let wait_states = match power.vos {
396 // VOS 0 range VCORE 1.26V - 1.40V
397 VoltageScale::Range1 => {
398 if sys_clk < 32_000_000 {
399 0
400 } else if sys_clk < 64_000_000 {
401 1
402 } else if sys_clk < 96_000_000 {
403 2
404 } else if sys_clk < 128_000_000 {
405 3
406 } else {
407 4
408 }
409 }
410 // VOS 1 range VCORE 1.15V - 1.26V
411 VoltageScale::Range2 => {
412 if sys_clk < 30_000_000 {
413 0
414 } else if sys_clk < 60_000_000 {
415 1
416 } else if sys_clk < 90_000_000 {
417 2
418 } else {
419 3
420 }
421 }
422 // VOS 2 range VCORE 1.05V - 1.15V
423 VoltageScale::Range3 => {
424 if sys_clk < 24_000_000 {
425 0
426 } else if sys_clk < 48_000_000 {
427 1
428 } else {
429 2
430 }
431 }
432 // VOS 3 range VCORE 0.95V - 1.05V
433 VoltageScale::Range4 => {
434 if sys_clk < 12_000_000 {
435 0
436 } else {
437 1
438 }
439 }
440 };
441
442 unsafe {
443 pac::FLASH.acr().modify(|w| {
444 w.set_latency(wait_states);
445 })
446 }
447
448 unsafe {
449 rcc.cfgr1().modify(|w| {
450 w.set_sw(cfgr.mux.into());
451 });
452
453 rcc.cfgr2().modify(|w| {
454 w.set_hpre(cfgr.ahb_pre.into());
455 w.set_ppre1(cfgr.apb1_pre.into());
456 w.set_ppre2(cfgr.apb2_pre.into());
457 });
458
459 rcc.cfgr3().modify(|w| {
460 w.set_ppre3(cfgr.apb3_pre.into());
461 });
462 }
463
464 let ahb_freq: u32 = match cfgr.ahb_pre {
465 AHBPrescaler::NotDivided => sys_clk,
466 pre => {
467 let pre: u8 = pre.into();
468 let pre = 1 << (pre as u32 - 7);
469 sys_clk / pre
470 }
471 };
472
473 let (apb1_freq, apb1_tim_freq) = match cfgr.apb1_pre {
474 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
475 pre => {
476 let pre: u8 = pre.into();
477 let pre: u8 = 1 << (pre - 3);
478 let freq = ahb_freq / pre as u32;
479 (freq, freq * 2)
480 }
481 };
482
483 let (apb2_freq, apb2_tim_freq) = match cfgr.apb2_pre {
484 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
485 pre => {
486 let pre: u8 = pre.into();
487 let pre: u8 = 1 << (pre - 3);
488 let freq = ahb_freq / (1 << (pre as u8 - 3));
489 (freq, freq * 2)
490 }
491 };
492
493 let (apb3_freq, apb3_tim_freq) = match cfgr.apb3_pre {
494 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
495 pre => {
496 let pre: u8 = pre.into();
497 let pre: u8 = 1 << (pre - 3);
498 let freq = ahb_freq / (1 << (pre as u8 - 3));
499 (freq, freq * 2)
500 }
501 };
502
503 Clocks {
504 sys: sys_clk.hz(),
505 ahb1: ahb_freq.hz(),
506 ahb2: ahb_freq.hz(),
507 ahb3: ahb_freq.hz(),
508 apb1: apb1_freq.hz(),
509 apb2: apb2_freq.hz(),
510 apb3: apb3_freq.hz(),
511 apb1_tim: apb1_tim_freq.hz(),
512 apb2_tim: apb2_tim_freq.hz(),
513 }
514 }
515}
516
517pub unsafe fn init(config: Config) {
518 let r = <peripherals::RCC as embassy::util::Steal>::steal();
519 let power = Power::new(<peripherals::PWR as embassy::util::Steal>::steal());
520 let clocks = r.freeze(config, &power);
521 set_freqs(clocks);
522}
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