diff options
| author | everdrone <[email protected]> | 2025-09-28 01:18:40 +0200 |
|---|---|---|
| committer | everdrone <[email protected]> | 2025-09-28 01:18:40 +0200 |
| commit | 97b0afb8d000bcc72582a09e3b9c2d7c33b66e7a (patch) | |
| tree | 37f59613ef658e807326188373e5326ff77c10eb | |
| parent | 2674462a4d21b4901fceb32f6534160a44d1a564 (diff) | |
Calculate RCC frequencies
| -rw-r--r-- | embassy-stm32/src/gpio.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/n6.rs | 259 |
2 files changed, 216 insertions, 49 deletions
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index ba5cf24c6..5645f71cb 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs | |||
| @@ -654,7 +654,7 @@ fn set_as_af(pin_port: PinNumber, af_num: u8, af_type: AfType) { | |||
| 654 | let r = pin.block(); | 654 | let r = pin.block(); |
| 655 | let n = pin._pin() as usize; | 655 | let n = pin._pin() as usize; |
| 656 | 656 | ||
| 657 | r.afr(n / 8).modify(|w| w.set_afr(n % 8, af_num as u8)); | 657 | r.afr(n / 8).modify(|w| w.set_afr(n % 8, af_num)); |
| 658 | r.pupdr().modify(|w| w.set_pupdr(n, af_type.pupdr)); | 658 | r.pupdr().modify(|w| w.set_pupdr(n, af_type.pupdr)); |
| 659 | r.otyper().modify(|w| w.set_ot(n, af_type.ot)); | 659 | r.otyper().modify(|w| w.set_ot(n, af_type.ot)); |
| 660 | r.ospeedr().modify(|w| w.set_ospeedr(n, af_type.ospeedr)); | 660 | r.ospeedr().modify(|w| w.set_ospeedr(n, af_type.ospeedr)); |
| @@ -798,6 +798,10 @@ pub(crate) trait SealedPin { | |||
| 798 | } | 798 | } |
| 799 | } | 799 | } |
| 800 | 800 | ||
| 801 | /// GPIO pin number type. | ||
| 802 | /// | ||
| 803 | /// Some chips have a total number of ports that exceeds 8, a larger integer | ||
| 804 | /// is needed to hold the total pin number `(ports * number)`. | ||
| 801 | #[cfg(not(stm32n6))] | 805 | #[cfg(not(stm32n6))] |
| 802 | pub type PinNumber = u8; | 806 | pub type PinNumber = u8; |
| 803 | #[cfg(stm32n6)] | 807 | #[cfg(stm32n6)] |
diff --git a/embassy-stm32/src/rcc/n6.rs b/embassy-stm32/src/rcc/n6.rs index 51fc8cdc8..5d2003325 100644 --- a/embassy-stm32/src/rcc/n6.rs +++ b/embassy-stm32/src/rcc/n6.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | use stm32_metapac::rcc::vals::{ | 1 | use stm32_metapac::rcc::vals::{ |
| 2 | Cpusw, Cpusws, Hseext, Hsitrim, Icint, Icsel, Msifreqsel, Plldivm, Pllmodssdis, Pllpdiv, Pllsel, Syssw, Syssws, | 2 | Cpusw, Cpusws, Hseext, Hsitrim, Icint, Icsel, Msifreqsel, Plldivm, Pllmodssdis, Pllpdiv, Pllsel, Syssw, Syssws, |
| 3 | Timpre, | ||
| 3 | }; | 4 | }; |
| 4 | pub use stm32_metapac::rcc::vals::{ | 5 | pub use stm32_metapac::rcc::vals::{ |
| 5 | Hpre as AhbPrescaler, Hsidiv as HsiPrescaler, Hsitrim as HsiCalibration, Ppre as ApbPrescaler, | 6 | Hpre as AhbPrescaler, Hsidiv as HsiPrescaler, Hsitrim as HsiCalibration, Ppre as ApbPrescaler, |
| @@ -44,7 +45,7 @@ pub enum SupplyConfig { | |||
| 44 | #[derive(Clone, Copy, PartialEq)] | 45 | #[derive(Clone, Copy, PartialEq)] |
| 45 | pub enum CpuClk { | 46 | pub enum CpuClk { |
| 46 | Hse, | 47 | Hse, |
| 47 | Pll { source: Icsel, divider: Icint }, | 48 | Ic1 { source: Icsel, divider: Icint }, |
| 48 | Msi, | 49 | Msi, |
| 49 | Hsi, | 50 | Hsi, |
| 50 | } | 51 | } |
| @@ -55,7 +56,7 @@ impl CpuClk { | |||
| 55 | Self::Hsi => 0x0, | 56 | Self::Hsi => 0x0, |
| 56 | Self::Msi => 0x1, | 57 | Self::Msi => 0x1, |
| 57 | Self::Hse => 0x2, | 58 | Self::Hse => 0x2, |
| 58 | Self::Pll { .. } => 0x3, | 59 | Self::Ic1 { .. } => 0x3, |
| 59 | } | 60 | } |
| 60 | } | 61 | } |
| 61 | } | 62 | } |
| @@ -69,7 +70,7 @@ pub struct IcConfig { | |||
| 69 | #[derive(Clone, Copy, PartialEq)] | 70 | #[derive(Clone, Copy, PartialEq)] |
| 70 | pub enum SysClk { | 71 | pub enum SysClk { |
| 71 | Hse, | 72 | Hse, |
| 72 | Pll { | 73 | Ic2 { |
| 73 | ic2: IcConfig, | 74 | ic2: IcConfig, |
| 74 | ic6: IcConfig, | 75 | ic6: IcConfig, |
| 75 | ic11: IcConfig, | 76 | ic11: IcConfig, |
| @@ -84,7 +85,7 @@ impl SysClk { | |||
| 84 | Self::Hsi => 0x0, | 85 | Self::Hsi => 0x0, |
| 85 | Self::Msi => 0x1, | 86 | Self::Msi => 0x1, |
| 86 | Self::Hse => 0x2, | 87 | Self::Hse => 0x2, |
| 87 | Self::Pll { .. } => 0x3, | 88 | Self::Ic2 { .. } => 0x3, |
| 88 | } | 89 | } |
| 89 | } | 90 | } |
| 90 | } | 91 | } |
| @@ -150,12 +151,12 @@ impl Config { | |||
| 150 | lse: false, | 151 | lse: false, |
| 151 | sys: SysClk::Hsi, | 152 | sys: SysClk::Hsi, |
| 152 | cpu: CpuClk::Hsi, | 153 | cpu: CpuClk::Hsi, |
| 153 | pll1: None, | 154 | pll1: Some(Pll::Bypass { source: Pllsel::HSI }), |
| 154 | pll2: None, | 155 | pll2: Some(Pll::Bypass { source: Pllsel::HSI }), |
| 155 | pll3: None, | 156 | pll3: Some(Pll::Bypass { source: Pllsel::HSI }), |
| 156 | pll4: None, | 157 | pll4: Some(Pll::Bypass { source: Pllsel::HSI }), |
| 157 | 158 | ||
| 158 | ahb: AhbPrescaler::DIV1, | 159 | ahb: AhbPrescaler::DIV2, |
| 159 | apb1: ApbPrescaler::DIV1, | 160 | apb1: ApbPrescaler::DIV1, |
| 160 | apb2: ApbPrescaler::DIV1, | 161 | apb2: ApbPrescaler::DIV1, |
| 161 | apb4: ApbPrescaler::DIV1, | 162 | apb4: ApbPrescaler::DIV1, |
| @@ -166,7 +167,24 @@ impl Config { | |||
| 166 | } | 167 | } |
| 167 | } | 168 | } |
| 168 | 169 | ||
| 169 | fn init_clocks(config: Config) { | 170 | struct ClocksOutput { |
| 171 | cpuclk: Hertz, | ||
| 172 | sysclk: Hertz, | ||
| 173 | pclk_tim: Hertz, | ||
| 174 | ahb: Hertz, | ||
| 175 | apb1: Hertz, | ||
| 176 | apb2: Hertz, | ||
| 177 | apb4: Hertz, | ||
| 178 | apb5: Hertz, | ||
| 179 | } | ||
| 180 | |||
| 181 | struct ClocksInput { | ||
| 182 | hsi: Option<Hertz>, | ||
| 183 | msi: Option<Hertz>, | ||
| 184 | hse: Option<Hertz>, | ||
| 185 | } | ||
| 186 | |||
| 187 | fn init_clocks(config: Config, input: &ClocksInput) -> ClocksOutput { | ||
| 170 | // handle increasing dividers | 188 | // handle increasing dividers |
| 171 | debug!("configuring increasing pclk dividers"); | 189 | debug!("configuring increasing pclk dividers"); |
| 172 | RCC.cfgr2().modify(|w| { | 190 | RCC.cfgr2().modify(|w| { |
| @@ -195,7 +213,7 @@ fn init_clocks(config: Config) { | |||
| 195 | debug!("configuring cpuclk"); | 213 | debug!("configuring cpuclk"); |
| 196 | match config.cpu { | 214 | match config.cpu { |
| 197 | CpuClk::Hse if !RCC.sr().read().hserdy() => panic!("HSE is not ready to be selected as CPU clock source"), | 215 | CpuClk::Hse if !RCC.sr().read().hserdy() => panic!("HSE is not ready to be selected as CPU clock source"), |
| 198 | CpuClk::Pll { source, divider } => { | 216 | CpuClk::Ic1 { source, divider } => { |
| 199 | if !pll_sources_ready(RCC.iccfgr(0).read().icsel().to_bits(), source.to_bits()) { | 217 | if !pll_sources_ready(RCC.iccfgr(0).read().icsel().to_bits(), source.to_bits()) { |
| 200 | panic!("ICx clock switch requires both origin and destination clock source to be active") | 218 | panic!("ICx clock switch requires both origin and destination clock source to be active") |
| 201 | } | 219 | } |
| @@ -220,7 +238,7 @@ fn init_clocks(config: Config) { | |||
| 220 | debug!("configuring sysclk"); | 238 | debug!("configuring sysclk"); |
| 221 | match config.sys { | 239 | match config.sys { |
| 222 | SysClk::Hse if !RCC.sr().read().hserdy() => panic!("HSE is not ready to be selected as CPU clock source"), | 240 | SysClk::Hse if !RCC.sr().read().hserdy() => panic!("HSE is not ready to be selected as CPU clock source"), |
| 223 | SysClk::Pll { ic2, ic6, ic11 } => { | 241 | SysClk::Ic2 { ic2, ic6, ic11 } => { |
| 224 | if !pll_sources_ready(RCC.iccfgr(1).read().icsel().to_bits(), ic2.source.to_bits()) { | 242 | if !pll_sources_ready(RCC.iccfgr(1).read().icsel().to_bits(), ic2.source.to_bits()) { |
| 225 | panic!("IC2 clock switch requires both origin and destination clock source to be active") | 243 | panic!("IC2 clock switch requires both origin and destination clock source to be active") |
| 226 | } | 244 | } |
| @@ -283,6 +301,57 @@ fn init_clocks(config: Config) { | |||
| 283 | w.set_ppre5(config.apb5); | 301 | w.set_ppre5(config.apb5); |
| 284 | } | 302 | } |
| 285 | }); | 303 | }); |
| 304 | |||
| 305 | let cpuclk = match config.cpu { | ||
| 306 | CpuClk::Hsi => unwrap!(input.hsi), | ||
| 307 | CpuClk::Msi => unwrap!(input.msi), | ||
| 308 | CpuClk::Hse => unwrap!(input.hse), | ||
| 309 | CpuClk::Ic1 { .. } => todo!(), | ||
| 310 | }; | ||
| 311 | |||
| 312 | let sysclk = match config.sys { | ||
| 313 | SysClk::Hsi => unwrap!(input.hsi), | ||
| 314 | SysClk::Msi => unwrap!(input.msi), | ||
| 315 | SysClk::Hse => unwrap!(input.hse), | ||
| 316 | SysClk::Ic2 { .. } => todo!(), | ||
| 317 | }; | ||
| 318 | |||
| 319 | let timpre: u32 = match RCC.cfgr2().read().timpre() { | ||
| 320 | Timpre::DIV1 => 1, | ||
| 321 | Timpre::DIV2 => 2, | ||
| 322 | Timpre::DIV4 => 4, | ||
| 323 | Timpre::_RESERVED_3 => 8, | ||
| 324 | }; | ||
| 325 | |||
| 326 | let hpre = periph_prescaler_to_value(config.ahb.to_bits()); | ||
| 327 | let ppre1 = periph_prescaler_to_value(config.apb1.to_bits()); | ||
| 328 | let ppre2 = periph_prescaler_to_value(config.apb2.to_bits()); | ||
| 329 | let ppre4 = periph_prescaler_to_value(config.apb4.to_bits()); | ||
| 330 | let ppre5 = periph_prescaler_to_value(config.apb5.to_bits()); | ||
| 331 | |||
| 332 | ClocksOutput { | ||
| 333 | sysclk, | ||
| 334 | cpuclk, | ||
| 335 | pclk_tim: sysclk / timpre, | ||
| 336 | ahb: Hertz(sysclk.0 / hpre as u32), | ||
| 337 | apb1: sysclk / hpre / ppre1, | ||
| 338 | apb2: sysclk / hpre / ppre2, | ||
| 339 | apb4: sysclk / hpre / ppre4, | ||
| 340 | apb5: sysclk / hpre / ppre5, | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | const fn periph_prescaler_to_value(bits: u8) -> u8 { | ||
| 345 | match bits { | ||
| 346 | 0 => 1, | ||
| 347 | 1 => 2, | ||
| 348 | 2 => 4, | ||
| 349 | 3 => 8, | ||
| 350 | 4 => 16, | ||
| 351 | 5 => 32, | ||
| 352 | 6 => 64, | ||
| 353 | 7.. => 128, | ||
| 354 | } | ||
| 286 | } | 355 | } |
| 287 | 356 | ||
| 288 | fn pll_source_ready(source: u8) -> bool { | 357 | fn pll_source_ready(source: u8) -> bool { |
| @@ -318,7 +387,23 @@ fn power_supply_config(supply_config: SupplyConfig) { | |||
| 318 | while !PWR.voscr().read().actvosrdy() {} | 387 | while !PWR.voscr().read().actvosrdy() {} |
| 319 | } | 388 | } |
| 320 | 389 | ||
| 321 | fn init_pll(pll_config: Option<Pll>, pll_index: usize) { | 390 | struct PllInput { |
| 391 | hsi: Option<Hertz>, | ||
| 392 | msi: Option<Hertz>, | ||
| 393 | hse: Option<Hertz>, | ||
| 394 | i2s_ckin: Option<Hertz>, | ||
| 395 | } | ||
| 396 | |||
| 397 | #[derive(Clone, Copy, Default)] | ||
| 398 | struct PllOutput { | ||
| 399 | divm: Option<Hertz>, | ||
| 400 | divn: Option<Hertz>, | ||
| 401 | divp1: Option<Hertz>, | ||
| 402 | divp2: Option<Hertz>, | ||
| 403 | output: Option<Hertz>, | ||
| 404 | } | ||
| 405 | |||
| 406 | fn init_pll(pll_config: Option<Pll>, pll_index: usize, input: &PllInput) -> PllOutput { | ||
| 322 | let cfgr1 = RCC.pllcfgr1(pll_index); | 407 | let cfgr1 = RCC.pllcfgr1(pll_index); |
| 323 | let cfgr2 = RCC.pllcfgr2(pll_index); | 408 | let cfgr2 = RCC.pllcfgr2(pll_index); |
| 324 | let cfgr3 = RCC.pllcfgr3(pll_index); | 409 | let cfgr3 = RCC.pllcfgr3(pll_index); |
| @@ -336,7 +421,7 @@ fn init_pll(pll_config: Option<Pll>, pll_index: usize) { | |||
| 336 | RCC.ccr().write(|w| w.set_pllonc(pll_index, true)); | 421 | RCC.ccr().write(|w| w.set_pllonc(pll_index, true)); |
| 337 | while RCC.sr().read().pllrdy(pll_index) {} | 422 | while RCC.sr().read().pllrdy(pll_index) {} |
| 338 | 423 | ||
| 339 | // ensure PLLxMODSSDIS=1 | 424 | // ensure PLLxMODSSDIS=1 to work in fractional mode |
| 340 | cfgr3.modify(|w| w.set_pllmodssdis(Pllmodssdis::FRACTIONAL_DIVIDE)); | 425 | cfgr3.modify(|w| w.set_pllmodssdis(Pllmodssdis::FRACTIONAL_DIVIDE)); |
| 341 | // clear bypass mode | 426 | // clear bypass mode |
| 342 | cfgr1.modify(|w| w.set_pllbyp(false)); | 427 | cfgr1.modify(|w| w.set_pllbyp(false)); |
| @@ -346,10 +431,26 @@ fn init_pll(pll_config: Option<Pll>, pll_index: usize) { | |||
| 346 | w.set_plldivm(divm); | 431 | w.set_plldivm(divm); |
| 347 | w.set_plldivn(divn); | 432 | w.set_plldivn(divn); |
| 348 | }); | 433 | }); |
| 434 | |||
| 435 | let in_clk = match source { | ||
| 436 | Pllsel::HSI => unwrap!(input.hsi), | ||
| 437 | Pllsel::MSI => unwrap!(input.msi), | ||
| 438 | Pllsel::HSE => unwrap!(input.hse), | ||
| 439 | Pllsel::I2S_CKIN => unwrap!(input.i2s_ckin), | ||
| 440 | _ => panic!("reserved PLL source not allowed"), | ||
| 441 | }; | ||
| 442 | |||
| 443 | let m = divm.to_bits() as u32; | ||
| 444 | let n = divn as u32; | ||
| 445 | |||
| 349 | cfgr3.modify(|w| { | 446 | cfgr3.modify(|w| { |
| 350 | w.set_pllpdiv1(divp1); | 447 | w.set_pllpdiv1(divp1); |
| 351 | w.set_pllpdiv2(divp2); | 448 | w.set_pllpdiv2(divp2); |
| 352 | }); | 449 | }); |
| 450 | |||
| 451 | let p1 = divp1.to_bits() as u32; | ||
| 452 | let p2 = divp2.to_bits() as u32; | ||
| 453 | |||
| 353 | // configure pll divnfrac | 454 | // configure pll divnfrac |
| 354 | cfgr2.modify(|w| w.set_plldivnfrac(fractional)); | 455 | cfgr2.modify(|w| w.set_plldivnfrac(fractional)); |
| 355 | // clear pllxmoddsen | 456 | // clear pllxmoddsen |
| @@ -370,6 +471,14 @@ fn init_pll(pll_config: Option<Pll>, pll_index: usize) { | |||
| 370 | RCC.csr().write(|w| w.pllons(pll_index)); | 471 | RCC.csr().write(|w| w.pllons(pll_index)); |
| 371 | // wait until ready | 472 | // wait until ready |
| 372 | while RCC.sr().read().pllrdy(pll_index) {} | 473 | while RCC.sr().read().pllrdy(pll_index) {} |
| 474 | |||
| 475 | PllOutput { | ||
| 476 | divm: Some(Hertz(m)), | ||
| 477 | divn: Some(Hertz(n)), | ||
| 478 | divp1: Some(Hertz(p1)), | ||
| 479 | divp2: Some(Hertz(p2)), | ||
| 480 | output: Some(Hertz(in_clk.0 / m / n / p1 / p2)), | ||
| 481 | } | ||
| 373 | } | 482 | } |
| 374 | Some(Pll::Bypass { source }) => { | 483 | Some(Pll::Bypass { source }) => { |
| 375 | // check if source is ready | 484 | // check if source is ready |
| @@ -384,7 +493,20 @@ fn init_pll(pll_config: Option<Pll>, pll_index: usize) { | |||
| 384 | cfgr1.modify(|w| { | 493 | cfgr1.modify(|w| { |
| 385 | w.set_pllbyp(true); | 494 | w.set_pllbyp(true); |
| 386 | w.set_pllsel(source); | 495 | w.set_pllsel(source); |
| 387 | }) | 496 | }); |
| 497 | |||
| 498 | let in_clk = match source { | ||
| 499 | Pllsel::HSI => unwrap!(input.hsi), | ||
| 500 | Pllsel::MSI => unwrap!(input.msi), | ||
| 501 | Pllsel::HSE => unwrap!(input.hse), | ||
| 502 | Pllsel::I2S_CKIN => unwrap!(input.i2s_ckin), | ||
| 503 | _ => panic!("reserved PLL source not allowed"), | ||
| 504 | }; | ||
| 505 | |||
| 506 | PllOutput { | ||
| 507 | output: Some(in_clk), | ||
| 508 | ..Default::default() | ||
| 509 | } | ||
| 388 | } | 510 | } |
| 389 | None => { | 511 | None => { |
| 390 | cfgr3.modify(|w| w.set_pllpdiven(false)); | 512 | cfgr3.modify(|w| w.set_pllpdiven(false)); |
| @@ -394,11 +516,29 @@ fn init_pll(pll_config: Option<Pll>, pll_index: usize) { | |||
| 394 | 516 | ||
| 395 | // clear bypass mode | 517 | // clear bypass mode |
| 396 | cfgr1.modify(|w| w.set_pllbyp(false)); | 518 | cfgr1.modify(|w| w.set_pllbyp(false)); |
| 519 | |||
| 520 | PllOutput::default() | ||
| 397 | } | 521 | } |
| 398 | } | 522 | } |
| 399 | } | 523 | } |
| 400 | 524 | ||
| 401 | fn init_osc(config: Config) { | 525 | struct OscOutput { |
| 526 | hsi: Option<Hertz>, | ||
| 527 | hse: Option<Hertz>, | ||
| 528 | msi: Option<Hertz>, | ||
| 529 | lsi: Option<Hertz>, | ||
| 530 | lse: Option<Hertz>, | ||
| 531 | pll1: Option<Hertz>, | ||
| 532 | pll2: Option<Hertz>, | ||
| 533 | pll3: Option<Hertz>, | ||
| 534 | pll4: Option<Hertz>, | ||
| 535 | ic1sel: Icsel, | ||
| 536 | ic2sel: Icsel, | ||
| 537 | ic6sel: Icsel, | ||
| 538 | ic11sel: Icsel, | ||
| 539 | } | ||
| 540 | |||
| 541 | fn init_osc(config: Config) -> OscOutput { | ||
| 402 | let (cpu_src, sys_src) = { | 542 | let (cpu_src, sys_src) = { |
| 403 | let reg = RCC.cfgr().read(); | 543 | let reg = RCC.cfgr().read(); |
| 404 | (reg.cpusws(), reg.syssws()) | 544 | (reg.cpusws(), reg.syssws()) |
| @@ -542,18 +682,27 @@ fn init_osc(config: Config) { | |||
| 542 | None | 682 | None |
| 543 | }; | 683 | }; |
| 544 | 684 | ||
| 685 | let pll_input = PllInput { | ||
| 686 | hse, | ||
| 687 | msi, | ||
| 688 | hsi, | ||
| 689 | i2s_ckin: None, | ||
| 690 | }; | ||
| 691 | |||
| 545 | // pll1,2,3,4 config | 692 | // pll1,2,3,4 config |
| 546 | let pll_configs = [config.pll1, config.pll2, config.pll3, config.pll4]; | 693 | let pll_configs = [config.pll1, config.pll2, config.pll3, config.pll4]; |
| 547 | for (n, &pll) in pll_configs.iter().enumerate() { | 694 | let mut pll_outputs: [PllOutput; 4] = [PllOutput::default(); 4]; |
| 695 | |||
| 696 | let ic1_src = RCC.iccfgr(0).read().icsel(); | ||
| 697 | let ic2_src = RCC.iccfgr(1).read().icsel(); | ||
| 698 | let ic6_src = RCC.iccfgr(5).read().icsel(); | ||
| 699 | let ic11_src = RCC.iccfgr(10).read().icsel(); | ||
| 700 | |||
| 701 | for (n, (&pll, out)) in pll_configs.iter().zip(pll_outputs.iter_mut()).enumerate() { | ||
| 548 | debug!("configuring PLL{}", n + 1); | 702 | debug!("configuring PLL{}", n + 1); |
| 549 | let pll_ready = RCC.sr().read().pllrdy(n); | 703 | let pll_ready = RCC.sr().read().pllrdy(n); |
| 550 | 704 | ||
| 551 | if is_new_pll_config(pll, 0) { | 705 | if is_new_pll_config(pll, 0) { |
| 552 | let ic1_src = RCC.iccfgr(0).read().icsel(); | ||
| 553 | let ic2_src = RCC.iccfgr(1).read().icsel(); | ||
| 554 | let ic6_src = RCC.iccfgr(5).read().icsel(); | ||
| 555 | let ic11_src = RCC.iccfgr(10).read().icsel(); | ||
| 556 | |||
| 557 | let this_pll = Icsel::from_bits(n as u8); | 706 | let this_pll = Icsel::from_bits(n as u8); |
| 558 | 707 | ||
| 559 | if cpu_src == Cpusws::IC1 && ic1_src == this_pll { | 708 | if cpu_src == Cpusws::IC1 && ic1_src == this_pll { |
| @@ -564,13 +713,28 @@ fn init_osc(config: Config) { | |||
| 564 | panic!("PLL should not be disabled / reconfigured if used for IC2, IC6 or IC11 (sysclksrc)") | 713 | panic!("PLL should not be disabled / reconfigured if used for IC2, IC6 or IC11 (sysclksrc)") |
| 565 | } | 714 | } |
| 566 | 715 | ||
| 567 | init_pll(pll, 0); | 716 | *out = init_pll(pll, 0, &pll_input); |
| 568 | } else if pll.is_some() && !pll_ready { | 717 | } else if pll.is_some() && !pll_ready { |
| 569 | debug!("PLL{} off", n + 1); | ||
| 570 | RCC.csr().write(|w| w.pllons(n)); | 718 | RCC.csr().write(|w| w.pllons(n)); |
| 571 | while !RCC.sr().read().pllrdy(n) {} | 719 | while !RCC.sr().read().pllrdy(n) {} |
| 572 | } | 720 | } |
| 573 | } | 721 | } |
| 722 | |||
| 723 | OscOutput { | ||
| 724 | hsi, | ||
| 725 | hse, | ||
| 726 | msi, | ||
| 727 | lsi, | ||
| 728 | lse, | ||
| 729 | pll1: pll_outputs[0].output, | ||
| 730 | pll2: pll_outputs[1].output, | ||
| 731 | pll3: pll_outputs[2].output, | ||
| 732 | pll4: pll_outputs[3].output, | ||
| 733 | ic1sel: ic1_src, | ||
| 734 | ic2sel: ic2_src, | ||
| 735 | ic6sel: ic6_src, | ||
| 736 | ic11sel: ic11_src, | ||
| 737 | } | ||
| 574 | } | 738 | } |
| 575 | 739 | ||
| 576 | fn is_new_pll_config(pll: Option<Pll>, pll_index: usize) -> bool { | 740 | fn is_new_pll_config(pll: Option<Pll>, pll_index: usize) -> bool { |
| @@ -618,7 +782,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 618 | // system configuration setup | 782 | // system configuration setup |
| 619 | RCC.apb4hensr().write(|w| w.set_syscfgens(true)); | 783 | RCC.apb4hensr().write(|w| w.set_syscfgens(true)); |
| 620 | // delay after RCC peripheral clock enabling | 784 | // delay after RCC peripheral clock enabling |
| 621 | core::ptr::read_volatile(RCC.apb4hensr().as_ptr()); | 785 | RCC.apb4hensr().read(); |
| 622 | 786 | ||
| 623 | debug!("setting VTOR"); | 787 | debug!("setting VTOR"); |
| 624 | 788 | ||
| @@ -630,7 +794,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 630 | // set default vector table location after reset or standby | 794 | // set default vector table location after reset or standby |
| 631 | SYSCFG.initsvtorcr().write(|w| w.set_svtor_addr(vtor)); | 795 | SYSCFG.initsvtorcr().write(|w| w.set_svtor_addr(vtor)); |
| 632 | // read back the value to ensure it is written before deactivating SYSCFG | 796 | // read back the value to ensure it is written before deactivating SYSCFG |
| 633 | core::ptr::read_volatile(SYSCFG.initsvtorcr().as_ptr()); | 797 | SYSCFG.initsvtorcr().read(); |
| 634 | 798 | ||
| 635 | debug!("deactivating SYSCFG"); | 799 | debug!("deactivating SYSCFG"); |
| 636 | 800 | ||
| @@ -649,36 +813,35 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 649 | 813 | ||
| 650 | power_supply_config(config.supply_config); | 814 | power_supply_config(config.supply_config); |
| 651 | 815 | ||
| 652 | init_osc(config); | 816 | let osc = init_osc(config); |
| 653 | init_clocks(config); | 817 | let clock_inputs = ClocksInput { |
| 654 | 818 | hsi: osc.hsi, | |
| 655 | let sys = match config.sys { | 819 | msi: osc.msi, |
| 656 | SysClk::Hse => todo!(), | 820 | hse: osc.hse, |
| 657 | SysClk::Hsi => Hertz(64_000_000), | ||
| 658 | SysClk::Msi => todo!(), | ||
| 659 | SysClk::Pll { .. } => todo!(), | ||
| 660 | }; | 821 | }; |
| 822 | let clocks = init_clocks(config, &clock_inputs); | ||
| 661 | 823 | ||
| 662 | // TODO: sysb, sysc, sysd must have the same clock source | 824 | // TODO: sysb, sysc, sysd must have the same clock source |
| 663 | 825 | ||
| 664 | set_clocks!( | 826 | set_clocks!( |
| 665 | sys: Some(sys), | 827 | sys: Some(clocks.sysclk), |
| 666 | hsi: None, | 828 | hsi: osc.hsi, |
| 667 | hsi_div: None, | 829 | hsi_div: None, |
| 668 | hse: None, | 830 | hse: osc.hse, |
| 669 | hclk1: None, | 831 | msi: osc.msi, |
| 670 | hclk2: None, | 832 | hclk1: Some(clocks.ahb), |
| 671 | hclk3: None, | 833 | hclk2: Some(clocks.ahb), |
| 672 | hclk4: None, | 834 | hclk3: Some(clocks.ahb), |
| 673 | hclk5: None, | 835 | hclk4: Some(clocks.ahb), |
| 674 | pclk1: None, | 836 | hclk5: Some(clocks.ahb), |
| 675 | pclk2: None, | 837 | pclk1: Some(clocks.apb1), |
| 676 | pclk2_tim: Some(Hertz(1_000_000)), // FIXME: what is this?? | 838 | pclk2: Some(clocks.apb2), |
| 677 | pclk4: None, | 839 | pclk1_tim: Some(clocks.pclk_tim), |
| 678 | pclk5: None, | 840 | pclk2_tim: Some(clocks.pclk_tim), |
| 841 | pclk4: Some(clocks.apb4), | ||
| 842 | pclk5: Some(clocks.apb5), | ||
| 679 | per: None, | 843 | per: None, |
| 680 | rtc: None, | 844 | rtc: None, |
| 681 | msi: None, | ||
| 682 | i2s_ckin: None, | 845 | i2s_ckin: None, |
| 683 | ic8: None, | 846 | ic8: None, |
| 684 | ic9: None, | 847 | ic9: None, |
