aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/rcc
diff options
context:
space:
mode:
authoreverdrone <[email protected]>2025-09-27 15:47:48 +0200
committereverdrone <[email protected]>2025-09-27 15:47:48 +0200
commit791ce77dba0a9302ebb1ec0aaca0b121b6cf554e (patch)
treef36869a88bdf5f223826426d2d364266392a8725 /embassy-stm32/src/rcc
parent81cc2f1e9fe76ad6584b6ecc8bc855946bd131b0 (diff)
Port RCC initialization from CMSIS HAL
Diffstat (limited to 'embassy-stm32/src/rcc')
-rw-r--r--embassy-stm32/src/rcc/n6.rs640
1 files changed, 550 insertions, 90 deletions
diff --git a/embassy-stm32/src/rcc/n6.rs b/embassy-stm32/src/rcc/n6.rs
index c8dae6303..08ea2fc4e 100644
--- a/embassy-stm32/src/rcc/n6.rs
+++ b/embassy-stm32/src/rcc/n6.rs
@@ -1,10 +1,15 @@
1use stm32_metapac::rcc::vals::{Cpusws, Hseext, Hsitrim, Pllsel, Syssws}; 1use stm32_metapac::rcc::vals::{
2pub use stm32_metapac::rcc::vals::{Hsidiv as HsiPrescaler, Hsitrim as HsiCalibration, Syssw as Sysclk}; 2 Cpusw, Cpusws, Hseext, Hsitrim, Icint, Icsel, Msifreqsel, Plldivm, Pllmodssdis, Pllpdiv, Pllsel, Syssw, Syssws,
3};
4pub use stm32_metapac::rcc::vals::{
5 Hpre as AhbPrescaler, Hsidiv as HsiPrescaler, Hsitrim as HsiCalibration, Ppre as ApbPrescaler,
6};
3 7
4use crate::pac::{PWR, RCC, SYSCFG}; 8use crate::pac::{PWR, RCC, SYSCFG};
5use crate::time::Hertz; 9use crate::time::Hertz;
6 10
7pub const HSI_FREQ: Hertz = Hertz(64_000_000); 11pub const HSI_FREQ: Hertz = Hertz(64_000_000);
12pub const LSE_FREQ: Hertz = Hertz(32_768);
8 13
9#[derive(Clone, Copy, Eq, PartialEq)] 14#[derive(Clone, Copy, Eq, PartialEq)]
10pub enum HseMode { 15pub enum HseMode {
@@ -27,7 +32,7 @@ pub struct Hse {
27#[derive(Clone, Copy, Eq, PartialEq)] 32#[derive(Clone, Copy, Eq, PartialEq)]
28pub struct Hsi { 33pub struct Hsi {
29 pub pre: HsiPrescaler, 34 pub pre: HsiPrescaler,
30 pub calib: Hsitrim, 35 pub trim: Hsitrim,
31} 36}
32 37
33#[derive(Clone, Copy, PartialEq)] 38#[derive(Clone, Copy, PartialEq)]
@@ -36,13 +41,108 @@ pub enum SupplyConfig {
36 External, 41 External,
37} 42}
38 43
44#[derive(Clone, Copy, PartialEq)]
45pub enum CpuClk {
46 Hse,
47 Pll { source: Icsel, divider: Icint },
48 Msi,
49 Hsi,
50}
51
52impl CpuClk {
53 const fn to_bits(self) -> u8 {
54 match self {
55 Self::Hsi => 0x0,
56 Self::Msi => 0x1,
57 Self::Hse => 0x2,
58 Self::Pll { .. } => 0x3,
59 }
60 }
61}
62
63#[derive(Clone, Copy, PartialEq)]
64pub struct IcConfig {
65 source: Icsel,
66 divider: Icint,
67}
68
69#[derive(Clone, Copy, PartialEq)]
70pub enum SysClk {
71 Hse,
72 Pll {
73 ic2: IcConfig,
74 ic6: IcConfig,
75 ic11: IcConfig,
76 },
77 Msi,
78 Hsi,
79}
80
81impl SysClk {
82 const fn to_bits(self) -> u8 {
83 match self {
84 Self::Hsi => 0x0,
85 Self::Msi => 0x1,
86 Self::Hse => 0x2,
87 Self::Pll { .. } => 0x3,
88 }
89 }
90}
91
92#[derive(Clone, Copy, PartialEq)]
93pub struct Msi {
94 pub freq: Msifreqsel,
95 pub trim: u8,
96}
97
98#[derive(Clone, Copy, PartialEq)]
99pub struct PllOscillator {
100 pub source: Pllsel,
101 pub divm: Plldivm,
102 pub fractional: u32,
103 pub divn: u16,
104 pub divp1: Pllpdiv,
105 pub divp2: Pllpdiv,
106}
107
108#[derive(Clone, Copy, PartialEq)]
109pub enum Pll {
110 Oscillator {
111 source: Pllsel,
112 m: Plldivm,
113 fractional: u32,
114 n: u16,
115 p1: Pllpdiv,
116 p2: Pllpdiv,
117 },
118 Bypass {
119 source: Pllsel,
120 },
121}
122
39/// Configuration of the core clocks 123/// Configuration of the core clocks
40#[non_exhaustive] 124#[non_exhaustive]
41#[derive(Clone, Copy)] 125#[derive(Clone, Copy)]
42pub struct Config { 126pub struct Config {
43 pub hsi: Option<Hsi>, 127 pub hsi: Option<Hsi>,
44 pub hse: Option<Hse>, 128 pub hse: Option<Hse>,
45 pub sys: Sysclk, 129 pub msi: Option<Msi>,
130 pub lsi: bool,
131 pub lse: bool,
132
133 pub sys: SysClk,
134 pub cpu: CpuClk,
135
136 pub pll1: Option<Pll>,
137 pub pll2: Option<Pll>,
138 pub pll3: Option<Pll>,
139 pub pll4: Option<Pll>,
140
141 pub ahb: AhbPrescaler,
142 pub apb1: ApbPrescaler,
143 pub apb2: ApbPrescaler,
144 pub apb4: ApbPrescaler,
145 pub apb5: ApbPrescaler,
46 146
47 pub supply_config: SupplyConfig, 147 pub supply_config: SupplyConfig,
48} 148}
@@ -52,13 +152,160 @@ impl Config {
52 Self { 152 Self {
53 hsi: None, 153 hsi: None,
54 hse: None, 154 hse: None,
55 sys: Sysclk::HSI, 155 msi: None,
156 lsi: true,
157 lse: false,
158 sys: SysClk::Hsi,
159 cpu: CpuClk::Hsi,
160 pll1: None,
161 pll2: None,
162 pll3: None,
163 pll4: None,
164
165 ahb: AhbPrescaler::DIV1,
166 apb1: ApbPrescaler::DIV1,
167 apb2: ApbPrescaler::DIV1,
168 apb4: ApbPrescaler::DIV1,
169 apb5: ApbPrescaler::DIV1,
56 170
57 supply_config: SupplyConfig::Smps, 171 supply_config: SupplyConfig::Smps,
58 } 172 }
59 } 173 }
60} 174}
61 175
176fn HAL_RCC_ClockConfig(config: Config) {
177 // handle increasing dividers
178 debug!("configuring increasing pclk dividers");
179 RCC.cfgr2().modify(|w| {
180 if config.apb1 > w.ppre1() {
181 debug!(" - APB1");
182 w.set_ppre1(config.apb1);
183 }
184 if config.apb2 > w.ppre2() {
185 debug!(" - APB2");
186 w.set_ppre2(config.apb2);
187 }
188 if config.apb4 > w.ppre4() {
189 debug!(" - APB4");
190 w.set_ppre4(config.apb4);
191 }
192 if config.apb5 > w.ppre5() {
193 debug!(" - APB5");
194 w.set_ppre5(config.apb5);
195 }
196 if config.ahb > w.hpre() {
197 debug!(" - AHB");
198 w.set_hpre(config.ahb);
199 }
200 });
201 // cpuclk
202 debug!("configuring cpuclk");
203 match config.cpu {
204 CpuClk::Hse if !RCC.sr().read().hserdy() => panic!("HSE is not ready to be selected as CPU clock source"),
205 CpuClk::Pll { source, divider } => {
206 if !RCC_IC_CheckPLLSources(RCC.iccfgr(0).read().icsel().to_bits(), source.to_bits()) {
207 panic!("ICx clock switch requires both origin and destination clock source to be active")
208 }
209
210 RCC.iccfgr(0).write(|w| {
211 w.set_icsel(source);
212 w.set_icint(divider);
213 });
214 RCC.divensr().modify(|w| w.set_ic1ens(true));
215 }
216 CpuClk::Msi if !RCC.sr().read().msirdy() => panic!("MSI is not ready to be selected as CPU clock source"),
217 CpuClk::Hsi if !RCC.sr().read().hsirdy() => panic!("HSI is not ready to be selected as CPU clock source"),
218 _ => {}
219 }
220 // set source
221 let cpusw = Cpusw::from_bits(config.cpu.to_bits());
222 RCC.cfgr().modify(|w| w.set_cpusw(cpusw));
223 // wait for changes to take effect
224 while RCC.cfgr().read().cpusws() != Cpusws::from_bits(config.cpu.to_bits()) {}
225
226 // sysclk
227 debug!("configuring sysclk");
228 match config.sys {
229 SysClk::Hse if !RCC.sr().read().hserdy() => panic!("HSE is not ready to be selected as CPU clock source"),
230 SysClk::Pll { ic2, ic6, ic11 } => {
231 if !RCC_IC_CheckPLLSources(RCC.iccfgr(1).read().icsel().to_bits(), ic2.source.to_bits()) {
232 panic!("IC2 clock switch requires both origin and destination clock source to be active")
233 }
234 if !RCC_IC_CheckPLLSources(RCC.iccfgr(5).read().icsel().to_bits(), ic6.source.to_bits()) {
235 panic!("IC6 clock switch requires both origin and destination clock source to be active")
236 }
237 if !RCC_IC_CheckPLLSources(RCC.iccfgr(10).read().icsel().to_bits(), ic11.source.to_bits()) {
238 panic!("IC11 clock switch requires both origin and destination clock source to be active")
239 }
240
241 RCC.iccfgr(1).write(|w| {
242 w.set_icsel(ic2.source);
243 w.set_icint(ic2.divider);
244 });
245 RCC.iccfgr(5).write(|w| {
246 w.set_icsel(ic6.source);
247 w.set_icint(ic6.divider);
248 });
249 RCC.iccfgr(10).write(|w| {
250 w.set_icsel(ic11.source);
251 w.set_icint(ic11.divider);
252 });
253 RCC.divensr().modify(|w| {
254 w.set_ic2ens(true);
255 w.set_ic6ens(true);
256 w.set_ic11ens(true);
257 });
258 }
259 SysClk::Msi if !RCC.sr().read().msirdy() => panic!("MSI is not ready to be selected as CPU clock source"),
260 SysClk::Hsi if !RCC.sr().read().hsirdy() => panic!("HSI is not ready to be selected as CPU clock source"),
261 _ => {}
262 }
263 // switch the system bus clock
264 let syssw = Syssw::from_bits(config.sys.to_bits());
265 RCC.cfgr().modify(|w| w.set_syssw(syssw));
266 // wait for changes to be applied
267 while RCC.cfgr().read().syssws() != Syssws::from_bits(config.sys.to_bits()) {}
268
269 // decreasing dividers
270 debug!("configuring decreasing pclk dividers");
271 RCC.cfgr2().modify(|w| {
272 if config.ahb < w.hpre() {
273 debug!(" - AHB");
274 w.set_hpre(config.ahb);
275 }
276 if config.apb1 < w.ppre1() {
277 debug!(" - APB1");
278 w.set_ppre1(config.apb1);
279 }
280 if config.apb2 < w.ppre2() {
281 debug!(" - APB2");
282 w.set_ppre2(config.apb2);
283 }
284 if config.apb4 < w.ppre4() {
285 debug!(" - APB4");
286 w.set_ppre4(config.apb4);
287 }
288 if config.apb5 < w.ppre5() {
289 debug!(" - APB5");
290 w.set_ppre5(config.apb5);
291 }
292 });
293}
294
295fn RCC_PLL_Source_IsReady(source: u8) -> bool {
296 match source {
297 0x0 if !RCC.sr().read().pllrdy(0) && !RCC.pllcfgr1(0).read().pllbyp() => false,
298 0x1 if !RCC.sr().read().pllrdy(1) && !RCC.pllcfgr1(1).read().pllbyp() => false,
299 0x2 if !RCC.sr().read().pllrdy(2) && !RCC.pllcfgr1(2).read().pllbyp() => false,
300 0x3 if !RCC.sr().read().pllrdy(3) && !RCC.pllcfgr1(3).read().pllbyp() => false,
301 _ => true,
302 }
303}
304
305fn RCC_IC_CheckPLLSources(source1: u8, source2: u8) -> bool {
306 RCC_PLL_Source_IsReady(source1) && RCC_PLL_Source_IsReady(source2)
307}
308
62impl Default for Config { 309impl Default for Config {
63 fn default() -> Self { 310 fn default() -> Self {
64 Self::new() 311 Self::new()
@@ -78,104 +325,310 @@ fn power_supply_config(supply_config: SupplyConfig) {
78 while !PWR.voscr().read().actvosrdy() {} 325 while !PWR.voscr().read().actvosrdy() {}
79} 326}
80 327
81fn osc_config(config: Config) -> (Option<Hertz>, Option<Hertz>) { 328fn pll_config(pll_config: Option<Pll>, pll_index: usize) {
82 let (cpu_clk_src, sys_clk_src) = { 329 let cfgr1 = RCC.pllcfgr1(pll_index);
83 let cfgr = RCC.cfgr().read(); 330 let cfgr2 = RCC.pllcfgr2(pll_index);
84 (cfgr.cpusws(), cfgr.syssws()) 331 let cfgr3 = RCC.pllcfgr3(pll_index);
85 }; 332
86 let pll1_clk_src = RCC.pll1cfgr1().read().pllsel(); 333 match pll_config {
87 let pll2_clk_src = RCC.pll2cfgr1().read().pllsel(); 334 Some(Pll::Oscillator {
88 let pll3_clk_src = RCC.pll3cfgr1().read().pllsel(); 335 source,
89 let pll4_clk_src = RCC.pll4cfgr1().read().pllsel(); 336 m,
90 let sr = RCC.sr().read(); 337 fractional,
338 n,
339 p1,
340 p2,
341 }) => {
342 // ensure pll is disabled
343 RCC.ccr().write(|w| w.set_pllonc(pll_index, true));
344 while RCC.sr().read().pllrdy(pll_index) {}
345
346 // ensure PLLxMODSSDIS=1
347 cfgr3.modify(|w| w.set_pllmodssdis(Pllmodssdis::FRACTIONAL_DIVIDE));
348 // clear bypass mode
349 cfgr1.modify(|w| w.set_pllbyp(false));
350 // configure the pll clock source, mul and div factors
351 cfgr1.modify(|w| {
352 w.set_pllsel(source);
353 w.set_plldivm(m);
354 w.set_plldivn(n);
355 });
356 cfgr3.modify(|w| {
357 w.set_pllpdiv1(p1);
358 w.set_pllpdiv2(p2);
359 });
360 // configure pll divnfrac
361 cfgr2.modify(|w| w.set_plldivnfrac(fractional));
362 // clear pllxmoddsen
363 cfgr3.modify(|w| w.set_pllmoddsen(false));
364 // fractional mode
365 if fractional != 0 {
366 cfgr3.modify(|w| {
367 w.set_pllmoddsen(true);
368 w.set_plldacen(true);
369 })
370 }
371 // enable pll post divider output
372 cfgr3.modify(|w| {
373 w.set_pllmodssrst(true);
374 w.set_pllpdiven(true);
375 });
376 // enable the pll
377 RCC.csr().write(|w| w.pllons(pll_index));
378 // wait until ready
379 while RCC.sr().read().pllrdy(pll_index) {}
380 }
381 Some(Pll::Bypass { source }) => {
382 // check if source is ready
383 if !RCC_PLL_Source_IsReady(source.to_bits()) {
384 panic!("PLL source is not ready")
385 }
91 386
92 let hsi = match config.hsi { 387 // ensure pll is disabled
388 RCC.ccr().write(|w| w.set_pllonc(pll_index, true));
389 while RCC.sr().read().pllrdy(pll_index) {}
390
391 cfgr1.modify(|w| {
392 w.set_pllbyp(true);
393 w.set_pllsel(source);
394 })
395 }
93 None => { 396 None => {
94 if (cpu_clk_src == Cpusws::HSI || sys_clk_src == Syssws::HSI) 397 cfgr3.modify(|w| w.set_pllpdiven(false));
95 || (pll1_clk_src == Pllsel::HSI && sr.pllrdy(0)) 398 RCC.ccr().write(|w| w.set_pllonc(pll_index, true));
96 || (pll2_clk_src == Pllsel::HSI && sr.pllrdy(1)) 399 // wait till disabled
97 || (pll3_clk_src == Pllsel::HSI && sr.pllrdy(2)) 400 while RCC.sr().read().pllrdy(pll_index) {}
98 || (pll4_clk_src == Pllsel::HSI && sr.pllrdy(3))
99 {
100 if config.hse.is_none() {
101 panic!("When the HSI is used as CPU or system bus clock source, it is not allowed to be disabled");
102 }
103 } else {
104 // disable the HSI
105 RCC.ccr().write(|w| w.set_hsionc(true));
106 // wait until HSI is disabled
107 while RCC.sr().read().hsirdy() {}
108 }
109 401
110 None 402 // clear bypass mode
403 cfgr1.modify(|w| w.set_pllbyp(false));
111 } 404 }
112 Some(hsi_config) => { 405 }
113 RCC.hsicfgr().modify(|w| { 406}
114 w.set_hsidiv(hsi_config.pre); 407
115 w.set_hsitrim(hsi_config.calib); 408fn HAL_RCC_OscConfig(config: Config) {
116 }); 409 let (cpu_src, sys_src) = {
117 Some(HSI_FREQ / hsi_config.pre) 410 let reg = RCC.cfgr().read();
411 (reg.cpusws(), reg.syssws())
412 };
413 let pll1_src = RCC.pllcfgr1(0).read().pllsel();
414 let pll2_src = RCC.pllcfgr1(1).read().pllsel();
415 let pll3_src = RCC.pllcfgr1(2).read().pllsel();
416 let pll4_src = RCC.pllcfgr1(3).read().pllsel();
417 let rcc_sr = RCC.sr().read();
418
419 debug!("configuring HSE");
420
421 // hse configuration
422 let hse = if let Some(hse) = config.hse {
423 match hse.mode {
424 HseMode::Oscillator => {
425 debug!("HSE in oscillator mode");
426 }
427 HseMode::Bypass => {
428 debug!("HSE in bypass mode");
429 RCC.hsecfgr().modify(|w| {
430 w.set_hsebyp(true);
431 w.set_hseext(Hseext::ANALOG);
432 });
433 }
434 HseMode::BypassDigital => {
435 debug!("HSE in bypass digital mode");
436 RCC.hsecfgr().modify(|w| {
437 w.set_hsebyp(true);
438 w.set_hseext(Hseext::DIGITAL);
439 });
440 }
118 } 441 }
442 RCC.csr().write(|w| w.set_hseons(true));
443
444 // wait until the hse is ready
445 while !RCC.sr().read().hserdy() {}
446
447 Some(hse.freq)
448 } else if cpu_src == Cpusws::HSE
449 || sys_src == Syssws::HSE
450 || (pll1_src == Pllsel::HSE && rcc_sr.pllrdy(0))
451 || (pll2_src == Pllsel::HSE && rcc_sr.pllrdy(1))
452 || (pll3_src == Pllsel::HSE && rcc_sr.pllrdy(2))
453 || (pll4_src == Pllsel::HSE && rcc_sr.pllrdy(3))
454 {
455 panic!("When the HSE is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled");
456 } else {
457 debug!("HSE off");
458
459 RCC.ccr().write(|w| w.set_hseonc(true));
460 RCC.hsecfgr().modify(|w| {
461 w.set_hseext(Hseext::ANALOG);
462 w.set_hsebyp(false);
463 });
464
465 // wait until the hse is disabled
466 while RCC.sr().read().hserdy() {}
467
468 None
119 }; 469 };
120 470
121 let hse = match config.hse { 471 // hsi configuration
122 None => { 472 debug!("configuring HSI");
123 if ((cpu_clk_src == Cpusws::HSE || sys_clk_src == Syssws::HSE) 473 let hsi = if let Some(hsi) = config.hsi {
124 || (pll1_clk_src == Pllsel::HSE && sr.pllrdy(0)) 474 RCC.csr().write(|w| w.set_hsions(true));
125 || (pll2_clk_src == Pllsel::HSE && sr.pllrdy(1)) 475 while !RCC.sr().read().hsirdy() {}
126 || (pll3_clk_src == Pllsel::HSE && sr.pllrdy(2)) 476
127 || (pll4_clk_src == Pllsel::HSE && sr.pllrdy(3))) 477 // set divider and calibration
128 && config.hse.is_none() 478 RCC.hsicfgr().modify(|w| {
129 { 479 w.set_hsidiv(hsi.pre);
130 panic!("When the HSE is used as CPU or system bus clock source, it is not allowed to be disabled"); 480 w.set_hsitrim(hsi.trim);
481 });
482
483 Some(HSI_FREQ / hsi.pre)
484 } else if cpu_src == Cpusws::HSI
485 || sys_src == Syssws::HSI
486 || (pll1_src == Pllsel::HSI && rcc_sr.pllrdy(0))
487 || (pll2_src == Pllsel::HSI && rcc_sr.pllrdy(1))
488 || (pll3_src == Pllsel::HSI && rcc_sr.pllrdy(2))
489 || (pll4_src == Pllsel::HSI && rcc_sr.pllrdy(3))
490 {
491 panic!("When the HSI is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled");
492 } else {
493 debug!("HSI off");
494
495 RCC.ccr().write(|w| w.set_hsionc(true));
496 while RCC.sr().read().hsirdy() {}
497
498 None
499 };
500
501 // msi configuration
502 debug!("configuring MSI");
503 let msi = if let Some(msi) = config.msi {
504 RCC.msicfgr().modify(|w| w.set_msifreqsel(msi.freq));
505 RCC.csr().write(|w| w.set_msions(true));
506 while !RCC.sr().read().msirdy() {}
507 RCC.msicfgr().modify(|w| w.set_msitrim(msi.trim));
508
509 Some(match msi.freq {
510 Msifreqsel::_4MHZ => Hertz::mhz(4),
511 Msifreqsel::_16MHZ => Hertz::mhz(16),
512 })
513 } else if cpu_src == Cpusws::MSI
514 || sys_src == Syssws::MSI
515 || (pll1_src == Pllsel::MSI && rcc_sr.pllrdy(0))
516 || (pll2_src == Pllsel::MSI && rcc_sr.pllrdy(1))
517 || (pll3_src == Pllsel::MSI && rcc_sr.pllrdy(2))
518 || (pll4_src == Pllsel::MSI && rcc_sr.pllrdy(3))
519 {
520 panic!("When the MSI is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled");
521 } else {
522 RCC.ccr().write(|w| w.set_msionc(true));
523 while RCC.sr().read().msirdy() {}
524
525 None
526 };
527
528 // lsi configuration
529 debug!("configuring LSI");
530 let lsi = if config.lsi {
531 RCC.csr().write(|w| w.set_lsions(true));
532 while !RCC.sr().read().lsirdy() {}
533 Some(super::LSI_FREQ)
534 } else {
535 RCC.ccr().write(|w| w.set_lsionc(true));
536 while RCC.sr().read().lsirdy() {}
537 None
538 };
539
540 // lse configuration
541 debug!("configuring LSE");
542 let lse = if config.lse {
543 RCC.csr().write(|w| w.set_lseons(true));
544 while !RCC.sr().read().lserdy() {}
545 Some(LSE_FREQ)
546 } else {
547 RCC.ccr().write(|w| w.set_lseonc(true));
548 while RCC.sr().read().lserdy() {}
549 None
550 };
551
552 // pll1,2,3,4 config
553 let pll_configs = [config.pll1, config.pll2, config.pll3, config.pll4];
554 for (n, &pll) in pll_configs.iter().enumerate() {
555 debug!("configuring PLL{}", n + 1);
556 let pll_ready = RCC.sr().read().pllrdy(n);
557
558 if RCC_PLL_IsNewConfig(pll, 0) {
559 let ic1_src = RCC.iccfgr(0).read().icsel();
560 let ic2_src = RCC.iccfgr(1).read().icsel();
561 let ic6_src = RCC.iccfgr(5).read().icsel();
562 let ic11_src = RCC.iccfgr(10).read().icsel();
563
564 let this_pll = Icsel::from_bits(n as u8);
565
566 if cpu_src == Cpusws::IC1 && ic1_src == this_pll {
567 panic!("PLL should not be disabled / reconfigured if used for IC1 (cpuclksrc)")
131 } 568 }
132 569
133 // hse off 570 if sys_src == Syssws::IC2 && (ic2_src == this_pll || ic6_src == this_pll || ic11_src == this_pll) {
134 RCC.csr().modify(|w| w.set_hseons(false)); 571 panic!("PLL should not be disabled / reconfigured if used for IC2, IC6 or IC11 (sysclksrc)")
135 RCC.hsecfgr().modify(|w| { 572 }
136 w.set_hseext(Hseext::ANALOG);
137 w.set_hsebyp(false);
138 });
139 573
140 // wait until hse is off 574 pll_config(pll, 0);
141 while RCC.sr().read().hserdy() {} 575 } else if pll.is_some() && !pll_ready {
142 576 debug!("PLL{} off", n + 1);
143 None 577 RCC.csr().write(|w| w.pllons(n));
144 } 578 while !RCC.sr().read().pllrdy(n) {}
145 Some(hse_config) => {
146 match hse_config.mode {
147 HseMode::Oscillator => RCC.csr().modify(|w| w.set_hseons(true)),
148 HseMode::Bypass => {
149 RCC.hsecfgr().modify(|w| {
150 w.set_hsebyp(true);
151 w.set_hseext(Hseext::ANALOG);
152 });
153 RCC.csr().modify(|w| w.set_hseons(true));
154 }
155 HseMode::BypassDigital => {
156 RCC.hsecfgr().modify(|w| {
157 w.set_hsebyp(true);
158 w.set_hseext(Hseext::DIGITAL)
159 });
160 }
161 };
162
163 // wait until the hse is ready
164 while !RCC.sr().read().hserdy() {}
165
166 Some(hse_config.freq)
167 } 579 }
168 }; 580 }
581}
582
583fn RCC_PLL_IsNewConfig(pll: Option<Pll>, pll_index: usize) -> bool {
584 let cfgr1 = RCC.pllcfgr1(pll_index).read();
585 let cfgr2 = RCC.pllcfgr2(pll_index).read();
586 let cfgr3 = RCC.pllcfgr3(pll_index).read();
587
588 let ready = RCC.sr().read().pllrdy(pll_index);
589 let bypass = cfgr1.pllbyp();
590
591 match (pll, ready, bypass) {
592 (None, true, _) => return true,
593 (Some(_), false, _) => return true,
594 (Some(conf), true, bypass) => match (conf, bypass) {
595 (Pll::Bypass { .. }, false) => return true,
596 (Pll::Oscillator { .. }, true) => return true,
597 _ => {}
598 },
599 _ => {}
600 }
169 601
170 (hsi, hse) 602 match pll {
603 Some(Pll::Bypass { source }) => cfgr1.pllsel() != source,
604 Some(Pll::Oscillator {
605 source,
606 m,
607 fractional,
608 n,
609 p1,
610 p2,
611 }) => {
612 cfgr1.pllsel() != source
613 || cfgr1.plldivm() != m
614 || cfgr1.plldivn() != n
615 || cfgr2.plldivnfrac() != fractional
616 || cfgr3.pllpdiv1() != p1
617 || cfgr3.pllpdiv2() != p2
618 }
619 None => false,
620 }
171} 621}
172 622
173pub(crate) unsafe fn init(config: Config) { 623pub(crate) unsafe fn init(config: Config) {
624 debug!("enabling SYSCFG");
174 // system configuration setup 625 // system configuration setup
175 RCC.apb4hensr().write(|w| w.set_syscfgens(true)); 626 RCC.apb4hensr().write(|w| w.set_syscfgens(true));
176 // delay after RCC peripheral clock enabling 627 // delay after RCC peripheral clock enabling
177 core::ptr::read_volatile(RCC.apb4hensr().as_ptr()); 628 core::ptr::read_volatile(RCC.apb4hensr().as_ptr());
178 629
630 debug!("setting VTOR");
631
179 let vtor = unsafe { 632 let vtor = unsafe {
180 let p = cortex_m::Peripherals::steal(); 633 let p = cortex_m::Peripherals::steal();
181 p.SCB.vtor.read() 634 p.SCB.vtor.read()
@@ -186,33 +639,40 @@ pub(crate) unsafe fn init(config: Config) {
186 // read back the value to ensure it is written before deactivating SYSCFG 639 // read back the value to ensure it is written before deactivating SYSCFG
187 core::ptr::read_volatile(SYSCFG.initsvtorcr().as_ptr()); 640 core::ptr::read_volatile(SYSCFG.initsvtorcr().as_ptr());
188 641
642 debug!("deactivating SYSCFG");
643
189 // deactivate SYSCFG 644 // deactivate SYSCFG
190 RCC.apb4hensr().write(|w| w.set_syscfgens(false)); 645 RCC.apb4hensr().write(|w| w.set_syscfgens(false));
191 646
647 debug!("enabling FPU");
648
192 // enable fpu 649 // enable fpu
193 unsafe { 650 unsafe {
194 let p = cortex_m::Peripherals::steal(); 651 let p = cortex_m::Peripherals::steal();
195 p.SCB.cpacr.modify(|w| w | (3 << 20) | (3 << 22)); 652 p.SCB.cpacr.modify(|w| w | (3 << 20) | (3 << 22));
196 } 653 }
197 654
655 debug!("setting power supply config");
656
198 power_supply_config(config.supply_config); 657 power_supply_config(config.supply_config);
199 658
200 let (hsi, hse) = osc_config(config); 659 HAL_RCC_OscConfig(config);
660 HAL_RCC_ClockConfig(config);
201 661
202 let sys = match config.sys { 662 let sys = match config.sys {
203 Sysclk::HSE => unwrap!(hse), 663 SysClk::Hse => todo!(),
204 Sysclk::HSI => unwrap!(hsi), 664 SysClk::Hsi => Hertz(64_000_000),
205 Sysclk::MSI => todo!(), 665 SysClk::Msi => todo!(),
206 Sysclk::IC2 => todo!(), 666 SysClk::Pll { .. } => todo!(),
207 }; 667 };
208 668
209 // TODO: sysb, sysc, sysd must have the same clock source 669 // TODO: sysb, sysc, sysd must have the same clock source
210 670
211 set_clocks!( 671 set_clocks!(
212 sys: Some(sys), 672 sys: Some(sys),
213 hsi: hsi, 673 hsi: None,
214 hsi_div: None, 674 hsi_div: None,
215 hse: hse, 675 hse: None,
216 hclk1: None, 676 hclk1: None,
217 hclk2: None, 677 hclk2: None,
218 hclk3: None, 678 hclk3: None,