diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-11-13 01:05:07 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-11-13 01:05:07 +0100 |
| commit | 066dc297ed4508c334effafcc134296cb776eb06 (patch) | |
| tree | 5930d02cad012665af217acd78464d52b9b48678 | |
| parent | 4fe344ebc0f4e030ff7a03755f27e66e9ad0476f (diff) | |
stm32/rcc: unify l0l1 and l4l5.
| -rw-r--r-- | embassy-stm32/Cargo.toml | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/l.rs (renamed from embassy-stm32/src/rcc/l4l5.rs) | 381 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/l0l1.rs | 190 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/common.rs | 4 |
5 files changed, 254 insertions, 328 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 7b3a6c2bb..373172760 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -58,7 +58,7 @@ rand_core = "0.6.3" | |||
| 58 | sdio-host = "0.5.0" | 58 | sdio-host = "0.5.0" |
| 59 | embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } | 59 | embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } |
| 60 | critical-section = "1.1" | 60 | critical-section = "1.1" |
| 61 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1374ed622714ef4702826699ca21cc1f741f4133" } | 61 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-c551c07bf12513dd8346a9fe0bc70cf79f2ea02f" } |
| 62 | vcell = "0.1.3" | 62 | vcell = "0.1.3" |
| 63 | bxcan = "0.7.0" | 63 | bxcan = "0.7.0" |
| 64 | nb = "1.0.0" | 64 | nb = "1.0.0" |
| @@ -76,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] } | |||
| 76 | [build-dependencies] | 76 | [build-dependencies] |
| 77 | proc-macro2 = "1.0.36" | 77 | proc-macro2 = "1.0.36" |
| 78 | quote = "1.0.15" | 78 | quote = "1.0.15" |
| 79 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1374ed622714ef4702826699ca21cc1f741f4133", default-features = false, features = ["metadata"]} | 79 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-c551c07bf12513dd8346a9fe0bc70cf79f2ea02f", default-features = false, features = ["metadata"]} |
| 80 | 80 | ||
| 81 | 81 | ||
| 82 | [features] | 82 | [features] |
diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l.rs index 97f231f61..257fd83fe 100644 --- a/embassy-stm32/src/rcc/l4l5.rs +++ b/embassy-stm32/src/rcc/l.rs | |||
| @@ -1,12 +1,13 @@ | |||
| 1 | #[cfg(any(stm32l0, stm32l1))] | ||
| 2 | pub use crate::pac::pwr::vals::Vos as VoltageScale; | ||
| 1 | use crate::pac::rcc::regs::Cfgr; | 3 | use crate::pac::rcc::regs::Cfgr; |
| 2 | #[cfg(any(stm32l4, stm32l5, stm32wb))] | 4 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] |
| 5 | pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; | ||
| 6 | #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))] | ||
| 3 | pub use crate::pac::rcc::vals::Clk48sel as Clk48Src; | 7 | pub use crate::pac::rcc::vals::Clk48sel as Clk48Src; |
| 4 | #[cfg(any(stm32wb, stm32wl))] | 8 | #[cfg(any(stm32wb, stm32wl))] |
| 5 | pub use crate::pac::rcc::vals::Hsepre as HsePrescaler; | 9 | pub use crate::pac::rcc::vals::Hsepre as HsePrescaler; |
| 6 | pub use crate::pac::rcc::vals::{ | 10 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange as MSIRange, Ppre as APBPrescaler, Sw as ClockSrc}; |
| 7 | Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, | ||
| 8 | Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PllSource, Ppre as APBPrescaler, Sw as ClockSrc, | ||
| 9 | }; | ||
| 10 | use crate::pac::{FLASH, RCC}; | 11 | use crate::pac::{FLASH, RCC}; |
| 11 | use crate::rcc::{set_freqs, Clocks}; | 12 | use crate::rcc::{set_freqs, Clocks}; |
| 12 | use crate::time::Hertz; | 13 | use crate::time::Hertz; |
| @@ -33,25 +34,6 @@ pub struct Hse { | |||
| 33 | pub prescaler: HsePrescaler, | 34 | pub prescaler: HsePrescaler, |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | #[derive(Clone, Copy)] | ||
| 37 | pub struct Pll { | ||
| 38 | /// PLL source | ||
| 39 | pub source: PllSource, | ||
| 40 | |||
| 41 | /// PLL pre-divider (DIVM). | ||
| 42 | pub prediv: PllPreDiv, | ||
| 43 | |||
| 44 | /// PLL multiplication factor. | ||
| 45 | pub mul: PllMul, | ||
| 46 | |||
| 47 | /// PLL P division factor. If None, PLL P output is disabled. | ||
| 48 | pub divp: Option<PllPDiv>, | ||
| 49 | /// PLL Q division factor. If None, PLL Q output is disabled. | ||
| 50 | pub divq: Option<PllQDiv>, | ||
| 51 | /// PLL R division factor. If None, PLL R output is disabled. | ||
| 52 | pub divr: Option<PllRDiv>, | ||
| 53 | } | ||
| 54 | |||
| 55 | /// Clocks configuration | 37 | /// Clocks configuration |
| 56 | pub struct Config { | 38 | pub struct Config { |
| 57 | // base clock sources | 39 | // base clock sources |
| @@ -79,13 +61,17 @@ pub struct Config { | |||
| 79 | pub shared_ahb_pre: AHBPrescaler, | 61 | pub shared_ahb_pre: AHBPrescaler, |
| 80 | 62 | ||
| 81 | // muxes | 63 | // muxes |
| 82 | #[cfg(any(stm32l4, stm32l5, stm32wb))] | 64 | #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))] |
| 83 | pub clk48_src: Clk48Src, | 65 | pub clk48_src: Clk48Src, |
| 84 | 66 | ||
| 85 | // low speed LSI/LSE/RTC | 67 | // low speed LSI/LSE/RTC |
| 86 | pub ls: super::LsConfig, | 68 | pub ls: super::LsConfig, |
| 87 | 69 | ||
| 70 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] | ||
| 88 | pub adc_clock_source: AdcClockSource, | 71 | pub adc_clock_source: AdcClockSource, |
| 72 | |||
| 73 | #[cfg(any(stm32l0, stm32l1))] | ||
| 74 | pub voltage_scale: VoltageScale, | ||
| 89 | } | 75 | } |
| 90 | 76 | ||
| 91 | impl Default for Config { | 77 | impl Default for Config { |
| @@ -110,10 +96,13 @@ impl Default for Config { | |||
| 110 | pllsai2: None, | 96 | pllsai2: None, |
| 111 | #[cfg(crs)] | 97 | #[cfg(crs)] |
| 112 | hsi48: Some(Default::default()), | 98 | hsi48: Some(Default::default()), |
| 113 | #[cfg(any(stm32l4, stm32l5, stm32wb))] | 99 | #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))] |
| 114 | clk48_src: Clk48Src::HSI48, | 100 | clk48_src: Clk48Src::HSI48, |
| 115 | ls: Default::default(), | 101 | ls: Default::default(), |
| 102 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] | ||
| 116 | adc_clock_source: AdcClockSource::SYS, | 103 | adc_clock_source: AdcClockSource::SYS, |
| 104 | #[cfg(any(stm32l0, stm32l1))] | ||
| 105 | voltage_scale: VoltageScale::RANGE1, | ||
| 117 | } | 106 | } |
| 118 | } | 107 | } |
| 119 | } | 108 | } |
| @@ -152,20 +141,26 @@ pub const WPAN_DEFAULT: Config = Config { | |||
| 152 | adc_clock_source: AdcClockSource::SYS, | 141 | adc_clock_source: AdcClockSource::SYS, |
| 153 | }; | 142 | }; |
| 154 | 143 | ||
| 144 | fn msi_enable(range: MSIRange) { | ||
| 145 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] | ||
| 146 | RCC.cr().modify(|w| { | ||
| 147 | #[cfg(not(stm32wb))] | ||
| 148 | w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR); | ||
| 149 | w.set_msirange(range); | ||
| 150 | w.set_msipllen(false); | ||
| 151 | }); | ||
| 152 | #[cfg(any(stm32l0, stm32l1))] | ||
| 153 | RCC.icscr().modify(|w| w.set_msirange(range)); | ||
| 154 | |||
| 155 | RCC.cr().modify(|w| w.set_msion(true)); | ||
| 156 | while !RCC.cr().read().msirdy() {} | ||
| 157 | } | ||
| 158 | |||
| 155 | pub(crate) unsafe fn init(config: Config) { | 159 | pub(crate) unsafe fn init(config: Config) { |
| 156 | // Switch to MSI to prevent problems with PLL configuration. | 160 | // Switch to MSI to prevent problems with PLL configuration. |
| 157 | if !RCC.cr().read().msion() { | 161 | if !RCC.cr().read().msion() { |
| 158 | // Turn on MSI and configure it to 4MHz. | 162 | // Turn on MSI and configure it to 4MHz. |
| 159 | RCC.cr().modify(|w| { | 163 | msi_enable(MSIRange::RANGE4M) |
| 160 | #[cfg(not(stm32wb))] | ||
| 161 | w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR); | ||
| 162 | w.set_msirange(MSIRange::RANGE4M); | ||
| 163 | w.set_msipllen(false); | ||
| 164 | w.set_msion(true) | ||
| 165 | }); | ||
| 166 | |||
| 167 | // Wait until MSI is running | ||
| 168 | while !RCC.cr().read().msirdy() {} | ||
| 169 | } | 164 | } |
| 170 | if RCC.cfgr().read().sws() != ClockSrc::MSI { | 165 | if RCC.cfgr().read().sws() != ClockSrc::MSI { |
| 171 | // Set MSI as a clock source, reset prescalers. | 166 | // Set MSI as a clock source, reset prescalers. |
| @@ -174,6 +169,14 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 174 | while RCC.cfgr().read().sws() != ClockSrc::MSI {} | 169 | while RCC.cfgr().read().sws() != ClockSrc::MSI {} |
| 175 | } | 170 | } |
| 176 | 171 | ||
| 172 | // Set voltage scale | ||
| 173 | #[cfg(any(stm32l0, stm32l1))] | ||
| 174 | { | ||
| 175 | while crate::pac::PWR.csr().read().vosf() {} | ||
| 176 | crate::pac::PWR.cr().write(|w| w.set_vos(config.voltage_scale)); | ||
| 177 | while crate::pac::PWR.csr().read().vosf() {} | ||
| 178 | } | ||
| 179 | |||
| 177 | #[cfg(stm32l5)] | 180 | #[cfg(stm32l5)] |
| 178 | crate::pac::PWR.cr1().modify(|w| { | 181 | crate::pac::PWR.cr1().modify(|w| { |
| 179 | w.set_vos(crate::pac::pwr::vals::Vos::RANGE0); | 182 | w.set_vos(crate::pac::pwr::vals::Vos::RANGE0); |
| @@ -182,21 +185,16 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 182 | let rtc = config.ls.init(); | 185 | let rtc = config.ls.init(); |
| 183 | 186 | ||
| 184 | let msi = config.msi.map(|range| { | 187 | let msi = config.msi.map(|range| { |
| 185 | // Enable MSI | 188 | msi_enable(range); |
| 186 | RCC.cr().modify(|w| { | ||
| 187 | #[cfg(not(stm32wb))] | ||
| 188 | w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR); | ||
| 189 | w.set_msirange(range); | ||
| 190 | w.set_msion(true); | ||
| 191 | |||
| 192 | // If LSE is enabled, enable calibration of MSI | ||
| 193 | w.set_msipllen(config.ls.lse.is_some()); | ||
| 194 | }); | ||
| 195 | while !RCC.cr().read().msirdy() {} | ||
| 196 | |||
| 197 | msirange_to_hertz(range) | 189 | msirange_to_hertz(range) |
| 198 | }); | 190 | }); |
| 199 | 191 | ||
| 192 | // If LSE is enabled and the right freq, enable calibration of MSI | ||
| 193 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] | ||
| 194 | if config.ls.lse.map(|x| x.frequency) == Some(Hertz(32_768)) { | ||
| 195 | RCC.cr().modify(|w| w.set_msipllen(true)); | ||
| 196 | } | ||
| 197 | |||
| 200 | let hsi = config.hsi.then(|| { | 198 | let hsi = config.hsi.then(|| { |
| 201 | RCC.cr().modify(|w| w.set_hsion(true)); | 199 | RCC.cr().modify(|w| w.set_hsion(true)); |
| 202 | while !RCC.cr().read().hsirdy() {} | 200 | while !RCC.cr().read().hsirdy() {} |
| @@ -218,7 +216,10 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 218 | }); | 216 | }); |
| 219 | 217 | ||
| 220 | #[cfg(crs)] | 218 | #[cfg(crs)] |
| 221 | let _hsi48 = config.hsi48.map(super::init_hsi48); | 219 | let _hsi48 = config.hsi48.map(|config| { |
| 220 | // | ||
| 221 | super::init_hsi48(config) | ||
| 222 | }); | ||
| 222 | #[cfg(not(crs))] | 223 | #[cfg(not(crs))] |
| 223 | let _hsi48: Option<Hertz> = None; | 224 | let _hsi48: Option<Hertz> = None; |
| 224 | 225 | ||
| @@ -251,7 +252,12 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 251 | }), | 252 | }), |
| 252 | }; | 253 | }; |
| 253 | 254 | ||
| 254 | let pll_input = PllInput { hse, hsi, msi }; | 255 | let pll_input = PllInput { |
| 256 | hse, | ||
| 257 | hsi, | ||
| 258 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] | ||
| 259 | msi, | ||
| 260 | }; | ||
| 255 | let pll = init_pll(PllInstance::Pll, config.pll, &pll_input); | 261 | let pll = init_pll(PllInstance::Pll, config.pll, &pll_input); |
| 256 | #[cfg(any(stm32l4, stm32l5, stm32wb))] | 262 | #[cfg(any(stm32l4, stm32l5, stm32wb))] |
| 257 | let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input); | 263 | let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input); |
| @@ -265,10 +271,13 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 265 | ClockSrc::PLL1_R => pll.r.unwrap(), | 271 | ClockSrc::PLL1_R => pll.r.unwrap(), |
| 266 | }; | 272 | }; |
| 267 | 273 | ||
| 268 | #[cfg(stm32l4)] | 274 | #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))] |
| 269 | RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src)); | 275 | RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src)); |
| 270 | #[cfg(stm32l5)] | 276 | #[cfg(any(rcc_l0_v2))] |
| 271 | RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src)); | 277 | let _clk48 = match config.clk48_src { |
| 278 | Clk48Src::HSI48 => _hsi48, | ||
| 279 | Clk48Src::PLL1_VCO_DIV_2 => pll.clk48, | ||
| 280 | }; | ||
| 272 | #[cfg(any(stm32l4, stm32l5, stm32wb))] | 281 | #[cfg(any(stm32l4, stm32l5, stm32wb))] |
| 273 | let _clk48 = match config.clk48_src { | 282 | let _clk48 = match config.clk48_src { |
| 274 | Clk48Src::HSI48 => _hsi48, | 283 | Clk48Src::HSI48 => _hsi48, |
| @@ -285,16 +294,23 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 285 | let hclk1 = sys_clk / config.ahb_pre; | 294 | let hclk1 = sys_clk / config.ahb_pre; |
| 286 | let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre); | 295 | let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre); |
| 287 | let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); | 296 | let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); |
| 288 | #[cfg(not(any(stm32wl5x, stm32wb)))] | 297 | #[cfg(any(stm32l4, stm32l5, stm32wlex))] |
| 289 | let hclk2 = hclk1; | 298 | let hclk2 = hclk1; |
| 290 | #[cfg(any(stm32wl5x, stm32wb))] | 299 | #[cfg(any(stm32wl5x, stm32wb))] |
| 291 | let hclk2 = sys_clk / config.core2_ahb_pre; | 300 | let hclk2 = sys_clk / config.core2_ahb_pre; |
| 292 | #[cfg(not(any(stm32wl, stm32wb)))] | 301 | #[cfg(any(stm32l4, stm32l5, stm32wlex))] |
| 293 | let hclk3 = hclk1; | 302 | let hclk3 = hclk1; |
| 294 | #[cfg(any(stm32wl, stm32wb))] | 303 | #[cfg(any(stm32wl5x, stm32wb))] |
| 295 | let hclk3 = sys_clk / config.shared_ahb_pre; | 304 | let hclk3 = sys_clk / config.shared_ahb_pre; |
| 296 | 305 | ||
| 297 | // Set flash wait states | 306 | // Set flash wait states |
| 307 | #[cfg(any(stm32l0, stm32l1))] | ||
| 308 | let latency = match (config.voltage_scale, sys_clk.0) { | ||
| 309 | (VoltageScale::RANGE1, ..=16_000_000) => false, | ||
| 310 | (VoltageScale::RANGE2, ..=8_000_000) => false, | ||
| 311 | (VoltageScale::RANGE3, ..=4_200_000) => false, | ||
| 312 | _ => true, | ||
| 313 | }; | ||
| 298 | #[cfg(stm32l4)] | 314 | #[cfg(stm32l4)] |
| 299 | let latency = match hclk1.0 { | 315 | let latency = match hclk1.0 { |
| 300 | 0..=16_000_000 => 0, | 316 | 0..=16_000_000 => 0, |
| @@ -330,6 +346,10 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 330 | _ => 4, | 346 | _ => 4, |
| 331 | }; | 347 | }; |
| 332 | 348 | ||
| 349 | #[cfg(stm32l1)] | ||
| 350 | FLASH.acr().write(|w| w.set_acc64(true)); | ||
| 351 | #[cfg(not(stm32l5))] | ||
| 352 | FLASH.acr().modify(|w| w.set_prften(true)); | ||
| 333 | FLASH.acr().modify(|w| w.set_latency(latency)); | 353 | FLASH.acr().modify(|w| w.set_latency(latency)); |
| 334 | while FLASH.acr().read().latency() != latency {} | 354 | while FLASH.acr().read().latency() != latency {} |
| 335 | 355 | ||
| @@ -341,9 +361,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 341 | }); | 361 | }); |
| 342 | while RCC.cfgr().read().sws() != config.mux {} | 362 | while RCC.cfgr().read().sws() != config.mux {} |
| 343 | 363 | ||
| 344 | #[cfg(stm32l5)] | 364 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] |
| 345 | RCC.ccipr1().modify(|w| w.set_adcsel(config.adc_clock_source)); | ||
| 346 | #[cfg(not(stm32l5))] | ||
| 347 | RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source)); | 365 | RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source)); |
| 348 | 366 | ||
| 349 | #[cfg(any(stm32wl, stm32wb))] | 367 | #[cfg(any(stm32wl, stm32wb))] |
| @@ -361,7 +379,9 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 361 | set_freqs(Clocks { | 379 | set_freqs(Clocks { |
| 362 | sys: sys_clk, | 380 | sys: sys_clk, |
| 363 | hclk1, | 381 | hclk1, |
| 382 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] | ||
| 364 | hclk2, | 383 | hclk2, |
| 384 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] | ||
| 365 | hclk3, | 385 | hclk3, |
| 366 | pclk1, | 386 | pclk1, |
| 367 | pclk2, | 387 | pclk2, |
| @@ -389,6 +409,12 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 389 | }); | 409 | }); |
| 390 | } | 410 | } |
| 391 | 411 | ||
| 412 | #[cfg(any(stm32l0, stm32l1))] | ||
| 413 | fn msirange_to_hertz(range: MSIRange) -> Hertz { | ||
| 414 | Hertz(32_768 * (1 << (range as u8 + 1))) | ||
| 415 | } | ||
| 416 | |||
| 417 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] | ||
| 392 | fn msirange_to_hertz(range: MSIRange) -> Hertz { | 418 | fn msirange_to_hertz(range: MSIRange) -> Hertz { |
| 393 | match range { | 419 | match range { |
| 394 | MSIRange::RANGE100K => Hertz(100_000), | 420 | MSIRange::RANGE100K => Hertz(100_000), |
| @@ -407,20 +433,6 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz { | |||
| 407 | } | 433 | } |
| 408 | } | 434 | } |
| 409 | 435 | ||
| 410 | struct PllInput { | ||
| 411 | hsi: Option<Hertz>, | ||
| 412 | hse: Option<Hertz>, | ||
| 413 | msi: Option<Hertz>, | ||
| 414 | } | ||
| 415 | |||
| 416 | #[allow(unused)] | ||
| 417 | #[derive(Default)] | ||
| 418 | struct PllOutput { | ||
| 419 | p: Option<Hertz>, | ||
| 420 | q: Option<Hertz>, | ||
| 421 | r: Option<Hertz>, | ||
| 422 | } | ||
| 423 | |||
| 424 | #[derive(PartialEq, Eq, Clone, Copy)] | 436 | #[derive(PartialEq, Eq, Clone, Copy)] |
| 425 | enum PllInstance { | 437 | enum PllInstance { |
| 426 | Pll, | 438 | Pll, |
| @@ -449,77 +461,182 @@ fn pll_enable(instance: PllInstance, enabled: bool) { | |||
| 449 | } | 461 | } |
| 450 | } | 462 | } |
| 451 | 463 | ||
| 452 | fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput { | 464 | pub use pll::*; |
| 453 | // Disable PLL | ||
| 454 | pll_enable(instance, false); | ||
| 455 | 465 | ||
| 456 | let Some(pll) = config else { return PllOutput::default() }; | 466 | #[cfg(any(stm32l0, stm32l1))] |
| 467 | mod pll { | ||
| 468 | use super::{pll_enable, PllInstance}; | ||
| 469 | pub use crate::pac::rcc::vals::{Plldiv as PllDiv, Pllmul as PllMul, Pllsrc as PllSource}; | ||
| 470 | use crate::pac::RCC; | ||
| 471 | use crate::time::Hertz; | ||
| 457 | 472 | ||
| 458 | let pll_src = match pll.source { | 473 | #[derive(Clone, Copy)] |
| 459 | PllSource::DISABLE => panic!("must not select PLL source as DISABLE"), | 474 | pub struct Pll { |
| 460 | PllSource::HSE => input.hse, | 475 | /// PLL source |
| 461 | PllSource::HSI => input.hsi, | 476 | pub source: PllSource, |
| 462 | PllSource::MSI => input.msi, | ||
| 463 | }; | ||
| 464 | 477 | ||
| 465 | let pll_src = pll_src.unwrap(); | 478 | /// PLL multiplication factor. |
| 479 | pub mul: PllMul, | ||
| 466 | 480 | ||
| 467 | let vco_freq = pll_src / pll.prediv * pll.mul; | 481 | /// PLL main output division factor. |
| 482 | pub div: PllDiv, | ||
| 483 | } | ||
| 468 | 484 | ||
| 469 | let p = pll.divp.map(|div| vco_freq / div); | 485 | pub(super) struct PllInput { |
| 470 | let q = pll.divq.map(|div| vco_freq / div); | 486 | pub hsi: Option<Hertz>, |
| 471 | let r = pll.divr.map(|div| vco_freq / div); | 487 | pub hse: Option<Hertz>, |
| 488 | } | ||
| 472 | 489 | ||
| 473 | #[cfg(stm32l5)] | 490 | #[allow(unused)] |
| 474 | if instance == PllInstance::Pllsai2 { | 491 | #[derive(Default)] |
| 475 | assert!(q.is_none(), "PLLSAI2_Q is not available on L5"); | 492 | pub(super) struct PllOutput { |
| 476 | assert!(r.is_none(), "PLLSAI2_R is not available on L5"); | 493 | pub r: Option<Hertz>, |
| 494 | pub clk48: Option<Hertz>, | ||
| 477 | } | 495 | } |
| 478 | 496 | ||
| 479 | macro_rules! write_fields { | 497 | pub(super) fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput { |
| 480 | ($w:ident) => { | 498 | // Disable PLL |
| 481 | $w.set_plln(pll.mul); | 499 | pll_enable(instance, false); |
| 482 | if let Some(divp) = pll.divp { | 500 | |
| 483 | $w.set_pllp(divp); | 501 | let Some(pll) = config else { return PllOutput::default() }; |
| 484 | $w.set_pllpen(true); | 502 | |
| 485 | } | 503 | let pll_src = match pll.source { |
| 486 | if let Some(divq) = pll.divq { | 504 | PllSource::HSE => unwrap!(input.hse), |
| 487 | $w.set_pllq(divq); | 505 | PllSource::HSI => unwrap!(input.hsi), |
| 488 | $w.set_pllqen(true); | ||
| 489 | } | ||
| 490 | if let Some(divr) = pll.divr { | ||
| 491 | $w.set_pllr(divr); | ||
| 492 | $w.set_pllren(true); | ||
| 493 | } | ||
| 494 | }; | 506 | }; |
| 495 | } | ||
| 496 | 507 | ||
| 497 | match instance { | 508 | let vco_freq = pll_src * pll.mul; |
| 498 | PllInstance::Pll => RCC.pllcfgr().write(|w| { | 509 | |
| 499 | w.set_pllm(pll.prediv); | 510 | let r = vco_freq / pll.div; |
| 500 | w.set_pllsrc(pll.source); | 511 | let clk48 = (vco_freq == Hertz(96_000_000)).then_some(Hertz(48_000_000)); |
| 501 | write_fields!(w); | 512 | |
| 502 | }), | 513 | assert!(r <= Hertz(32_000_000)); |
| 503 | #[cfg(any(stm32l4, stm32l5, stm32wb))] | 514 | |
| 504 | PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| { | 515 | RCC.cfgr().write(move |w| { |
| 505 | #[cfg(any(rcc_l4plus, stm32l5))] | 516 | w.set_pllmul(pll.mul); |
| 506 | w.set_pllm(pll.prediv); | 517 | w.set_plldiv(pll.div); |
| 507 | #[cfg(stm32l5)] | ||
| 508 | w.set_pllsrc(pll.source); | ||
| 509 | write_fields!(w); | ||
| 510 | }), | ||
| 511 | #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] | ||
| 512 | PllInstance::Pllsai2 => RCC.pllsai2cfgr().write(|w| { | ||
| 513 | #[cfg(any(rcc_l4plus, stm32l5))] | ||
| 514 | w.set_pllm(pll.prediv); | ||
| 515 | #[cfg(stm32l5)] | ||
| 516 | w.set_pllsrc(pll.source); | 518 | w.set_pllsrc(pll.source); |
| 517 | write_fields!(w); | 519 | }); |
| 518 | }), | 520 | |
| 521 | // Enable PLL | ||
| 522 | pll_enable(instance, true); | ||
| 523 | |||
| 524 | PllOutput { r: Some(r), clk48 } | ||
| 525 | } | ||
| 526 | } | ||
| 527 | |||
| 528 | #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] | ||
| 529 | mod pll { | ||
| 530 | use super::{pll_enable, PllInstance}; | ||
| 531 | pub use crate::pac::rcc::vals::{ | ||
| 532 | Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PllSource, | ||
| 533 | }; | ||
| 534 | use crate::pac::RCC; | ||
| 535 | use crate::time::Hertz; | ||
| 536 | |||
| 537 | #[derive(Clone, Copy)] | ||
| 538 | pub struct Pll { | ||
| 539 | /// PLL source | ||
| 540 | pub source: PllSource, | ||
| 541 | |||
| 542 | /// PLL pre-divider (DIVM). | ||
| 543 | pub prediv: PllPreDiv, | ||
| 544 | |||
| 545 | /// PLL multiplication factor. | ||
| 546 | pub mul: PllMul, | ||
| 547 | |||
| 548 | /// PLL P division factor. If None, PLL P output is disabled. | ||
| 549 | pub divp: Option<PllPDiv>, | ||
| 550 | /// PLL Q division factor. If None, PLL Q output is disabled. | ||
| 551 | pub divq: Option<PllQDiv>, | ||
| 552 | /// PLL R division factor. If None, PLL R output is disabled. | ||
| 553 | pub divr: Option<PllRDiv>, | ||
| 519 | } | 554 | } |
| 520 | 555 | ||
| 521 | // Enable PLL | 556 | pub(super) struct PllInput { |
| 522 | pll_enable(instance, true); | 557 | pub hsi: Option<Hertz>, |
| 558 | pub hse: Option<Hertz>, | ||
| 559 | pub msi: Option<Hertz>, | ||
| 560 | } | ||
| 561 | |||
| 562 | #[allow(unused)] | ||
| 563 | #[derive(Default)] | ||
| 564 | pub(super) struct PllOutput { | ||
| 565 | pub p: Option<Hertz>, | ||
| 566 | pub q: Option<Hertz>, | ||
| 567 | pub r: Option<Hertz>, | ||
| 568 | } | ||
| 569 | |||
| 570 | pub(super) fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput { | ||
| 571 | // Disable PLL | ||
| 572 | pll_enable(instance, false); | ||
| 573 | |||
| 574 | let Some(pll) = config else { return PllOutput::default() }; | ||
| 575 | |||
| 576 | let pll_src = match pll.source { | ||
| 577 | PllSource::DISABLE => panic!("must not select PLL source as DISABLE"), | ||
| 578 | PllSource::HSE => unwrap!(input.hse), | ||
| 579 | PllSource::HSI => unwrap!(input.hsi), | ||
| 580 | PllSource::MSI => unwrap!(input.msi), | ||
| 581 | }; | ||
| 582 | |||
| 583 | let vco_freq = pll_src / pll.prediv * pll.mul; | ||
| 523 | 584 | ||
| 524 | PllOutput { p, q, r } | 585 | let p = pll.divp.map(|div| vco_freq / div); |
| 586 | let q = pll.divq.map(|div| vco_freq / div); | ||
| 587 | let r = pll.divr.map(|div| vco_freq / div); | ||
| 588 | |||
| 589 | #[cfg(stm32l5)] | ||
| 590 | if instance == PllInstance::Pllsai2 { | ||
| 591 | assert!(q.is_none(), "PLLSAI2_Q is not available on L5"); | ||
| 592 | assert!(r.is_none(), "PLLSAI2_R is not available on L5"); | ||
| 593 | } | ||
| 594 | |||
| 595 | macro_rules! write_fields { | ||
| 596 | ($w:ident) => { | ||
| 597 | $w.set_plln(pll.mul); | ||
| 598 | if let Some(divp) = pll.divp { | ||
| 599 | $w.set_pllp(divp); | ||
| 600 | $w.set_pllpen(true); | ||
| 601 | } | ||
| 602 | if let Some(divq) = pll.divq { | ||
| 603 | $w.set_pllq(divq); | ||
| 604 | $w.set_pllqen(true); | ||
| 605 | } | ||
| 606 | if let Some(divr) = pll.divr { | ||
| 607 | $w.set_pllr(divr); | ||
| 608 | $w.set_pllren(true); | ||
| 609 | } | ||
| 610 | }; | ||
| 611 | } | ||
| 612 | |||
| 613 | match instance { | ||
| 614 | PllInstance::Pll => RCC.pllcfgr().write(|w| { | ||
| 615 | w.set_pllm(pll.prediv); | ||
| 616 | w.set_pllsrc(pll.source); | ||
| 617 | write_fields!(w); | ||
| 618 | }), | ||
| 619 | #[cfg(any(stm32l4, stm32l5, stm32wb))] | ||
| 620 | PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| { | ||
| 621 | #[cfg(any(rcc_l4plus, stm32l5))] | ||
| 622 | w.set_pllm(pll.prediv); | ||
| 623 | #[cfg(stm32l5)] | ||
| 624 | w.set_pllsrc(pll.source); | ||
| 625 | write_fields!(w); | ||
| 626 | }), | ||
| 627 | #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] | ||
| 628 | PllInstance::Pllsai2 => RCC.pllsai2cfgr().write(|w| { | ||
| 629 | #[cfg(any(rcc_l4plus, stm32l5))] | ||
| 630 | w.set_pllm(pll.prediv); | ||
| 631 | #[cfg(stm32l5)] | ||
| 632 | w.set_pllsrc(pll.source); | ||
| 633 | write_fields!(w); | ||
| 634 | }), | ||
| 635 | } | ||
| 636 | |||
| 637 | // Enable PLL | ||
| 638 | pll_enable(instance, true); | ||
| 639 | |||
| 640 | PllOutput { p, q, r } | ||
| 641 | } | ||
| 525 | } | 642 | } |
diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs deleted file mode 100644 index c3d58e8ec..000000000 --- a/embassy-stm32/src/rcc/l0l1.rs +++ /dev/null | |||
| @@ -1,190 +0,0 @@ | |||
| 1 | pub use crate::pac::pwr::vals::Vos as VoltageScale; | ||
| 2 | pub use crate::pac::rcc::vals::{ | ||
| 3 | Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PllDiv, Pllmul as PllMul, Pllsrc as PllSource, | ||
| 4 | Ppre as APBPrescaler, Sw as ClockSrc, | ||
| 5 | }; | ||
| 6 | use crate::pac::{FLASH, PWR, RCC}; | ||
| 7 | use crate::rcc::{set_freqs, Clocks}; | ||
| 8 | use crate::time::Hertz; | ||
| 9 | |||
| 10 | /// HSI speed | ||
| 11 | pub const HSI_FREQ: Hertz = Hertz(16_000_000); | ||
| 12 | |||
| 13 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
| 14 | pub enum HseMode { | ||
| 15 | /// crystal/ceramic oscillator (HSEBYP=0) | ||
| 16 | Oscillator, | ||
| 17 | /// external analog clock (low swing) (HSEBYP=1) | ||
| 18 | Bypass, | ||
| 19 | } | ||
| 20 | |||
| 21 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
| 22 | pub struct Hse { | ||
| 23 | /// HSE frequency. | ||
| 24 | pub freq: Hertz, | ||
| 25 | /// HSE mode. | ||
| 26 | pub mode: HseMode, | ||
| 27 | } | ||
| 28 | |||
| 29 | #[derive(Clone, Copy)] | ||
| 30 | pub struct Pll { | ||
| 31 | /// PLL source | ||
| 32 | pub source: PllSource, | ||
| 33 | |||
| 34 | /// PLL multiplication factor. | ||
| 35 | pub mul: PllMul, | ||
| 36 | |||
| 37 | /// PLL main output division factor. | ||
| 38 | pub div: PllDiv, | ||
| 39 | } | ||
| 40 | |||
| 41 | /// Clocks configutation | ||
| 42 | pub struct Config { | ||
| 43 | // base clock sources | ||
| 44 | pub msi: Option<MSIRange>, | ||
| 45 | pub hsi: bool, | ||
| 46 | pub hse: Option<Hse>, | ||
| 47 | #[cfg(crs)] | ||
| 48 | pub hsi48: Option<super::Hsi48Config>, | ||
| 49 | |||
| 50 | pub pll: Option<Pll>, | ||
| 51 | |||
| 52 | pub mux: ClockSrc, | ||
| 53 | pub ahb_pre: AHBPrescaler, | ||
| 54 | pub apb1_pre: APBPrescaler, | ||
| 55 | pub apb2_pre: APBPrescaler, | ||
| 56 | |||
| 57 | pub ls: super::LsConfig, | ||
| 58 | pub voltage_scale: VoltageScale, | ||
| 59 | } | ||
| 60 | |||
| 61 | impl Default for Config { | ||
| 62 | #[inline] | ||
| 63 | fn default() -> Config { | ||
| 64 | Config { | ||
| 65 | msi: Some(MSIRange::RANGE5), | ||
| 66 | hse: None, | ||
| 67 | hsi: false, | ||
| 68 | #[cfg(crs)] | ||
| 69 | hsi48: Some(Default::default()), | ||
| 70 | |||
| 71 | pll: None, | ||
| 72 | |||
| 73 | mux: ClockSrc::MSI, | ||
| 74 | ahb_pre: AHBPrescaler::DIV1, | ||
| 75 | apb1_pre: APBPrescaler::DIV1, | ||
| 76 | apb2_pre: APBPrescaler::DIV1, | ||
| 77 | voltage_scale: VoltageScale::RANGE1, | ||
| 78 | ls: Default::default(), | ||
| 79 | } | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | pub(crate) unsafe fn init(config: Config) { | ||
| 84 | // Set voltage scale | ||
| 85 | while PWR.csr().read().vosf() {} | ||
| 86 | PWR.cr().write(|w| w.set_vos(config.voltage_scale)); | ||
| 87 | while PWR.csr().read().vosf() {} | ||
| 88 | |||
| 89 | let rtc = config.ls.init(); | ||
| 90 | |||
| 91 | let msi = config.msi.map(|range| { | ||
| 92 | RCC.icscr().modify(|w| w.set_msirange(range)); | ||
| 93 | |||
| 94 | RCC.cr().modify(|w| w.set_msion(true)); | ||
| 95 | while !RCC.cr().read().msirdy() {} | ||
| 96 | |||
| 97 | Hertz(32_768 * (1 << (range as u8 + 1))) | ||
| 98 | }); | ||
| 99 | |||
| 100 | let hsi = config.hsi.then(|| { | ||
| 101 | RCC.cr().modify(|w| w.set_hsion(true)); | ||
| 102 | while !RCC.cr().read().hsirdy() {} | ||
| 103 | |||
| 104 | HSI_FREQ | ||
| 105 | }); | ||
| 106 | |||
| 107 | let hse = config.hse.map(|hse| { | ||
| 108 | RCC.cr().modify(|w| { | ||
| 109 | w.set_hsebyp(hse.mode == HseMode::Bypass); | ||
| 110 | w.set_hseon(true); | ||
| 111 | }); | ||
| 112 | while !RCC.cr().read().hserdy() {} | ||
| 113 | |||
| 114 | hse.freq | ||
| 115 | }); | ||
| 116 | |||
| 117 | let pll = config.pll.map(|pll| { | ||
| 118 | let freq = match pll.source { | ||
| 119 | PllSource::HSE => hse.unwrap(), | ||
| 120 | PllSource::HSI => hsi.unwrap(), | ||
| 121 | }; | ||
| 122 | |||
| 123 | // Disable PLL | ||
| 124 | RCC.cr().modify(|w| w.set_pllon(false)); | ||
| 125 | while RCC.cr().read().pllrdy() {} | ||
| 126 | |||
| 127 | let freq = freq * pll.mul / pll.div; | ||
| 128 | |||
| 129 | assert!(freq <= Hertz(32_000_000)); | ||
| 130 | |||
| 131 | RCC.cfgr().write(move |w| { | ||
| 132 | w.set_pllmul(pll.mul); | ||
| 133 | w.set_plldiv(pll.div); | ||
| 134 | w.set_pllsrc(pll.source); | ||
| 135 | }); | ||
| 136 | |||
| 137 | // Enable PLL | ||
| 138 | RCC.cr().modify(|w| w.set_pllon(true)); | ||
| 139 | while !RCC.cr().read().pllrdy() {} | ||
| 140 | |||
| 141 | freq | ||
| 142 | }); | ||
| 143 | |||
| 144 | let sys_clk = match config.mux { | ||
| 145 | ClockSrc::HSE => hse.unwrap(), | ||
| 146 | ClockSrc::HSI => hsi.unwrap(), | ||
| 147 | ClockSrc::MSI => msi.unwrap(), | ||
| 148 | ClockSrc::PLL1_P => pll.unwrap(), | ||
| 149 | }; | ||
| 150 | |||
| 151 | let wait_states = match (config.voltage_scale, sys_clk.0) { | ||
| 152 | (VoltageScale::RANGE1, ..=16_000_000) => 0, | ||
| 153 | (VoltageScale::RANGE2, ..=8_000_000) => 0, | ||
| 154 | (VoltageScale::RANGE3, ..=4_200_000) => 0, | ||
| 155 | _ => 1, | ||
| 156 | }; | ||
| 157 | |||
| 158 | #[cfg(stm32l1)] | ||
| 159 | FLASH.acr().write(|w| w.set_acc64(true)); | ||
| 160 | FLASH.acr().modify(|w| w.set_prften(true)); | ||
| 161 | FLASH.acr().modify(|w| w.set_latency(wait_states != 0)); | ||
| 162 | |||
| 163 | RCC.cfgr().modify(|w| { | ||
| 164 | w.set_sw(config.mux); | ||
| 165 | w.set_hpre(config.ahb_pre); | ||
| 166 | w.set_ppre1(config.apb1_pre); | ||
| 167 | w.set_ppre2(config.apb2_pre); | ||
| 168 | }); | ||
| 169 | |||
| 170 | let hclk1 = sys_clk / config.ahb_pre; | ||
| 171 | let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre); | ||
| 172 | let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); | ||
| 173 | |||
| 174 | #[cfg(crs)] | ||
| 175 | let _hsi48 = config.hsi48.map(|config| { | ||
| 176 | // Select HSI48 as USB clock | ||
| 177 | RCC.ccipr().modify(|w| w.set_hsi48msel(true)); | ||
| 178 | super::init_hsi48(config) | ||
| 179 | }); | ||
| 180 | |||
| 181 | set_freqs(Clocks { | ||
| 182 | sys: sys_clk, | ||
| 183 | hclk1, | ||
| 184 | pclk1, | ||
| 185 | pclk2, | ||
| 186 | pclk1_tim, | ||
| 187 | pclk2_tim, | ||
| 188 | rtc, | ||
| 189 | }); | ||
| 190 | } | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index e15f4fe41..debd16ca1 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -23,8 +23,7 @@ pub use hsi48::*; | |||
| 23 | #[cfg_attr(rcc_g0, path = "g0.rs")] | 23 | #[cfg_attr(rcc_g0, path = "g0.rs")] |
| 24 | #[cfg_attr(rcc_g4, path = "g4.rs")] | 24 | #[cfg_attr(rcc_g4, path = "g4.rs")] |
| 25 | #[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")] | 25 | #[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")] |
| 26 | #[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")] | 26 | #[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl), path = "l.rs")] |
| 27 | #[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle, rcc_wb), path = "l4l5.rs")] | ||
| 28 | #[cfg_attr(rcc_u5, path = "u5.rs")] | 27 | #[cfg_attr(rcc_u5, path = "u5.rs")] |
| 29 | #[cfg_attr(rcc_wba, path = "wba.rs")] | 28 | #[cfg_attr(rcc_wba, path = "wba.rs")] |
| 30 | mod _version; | 29 | mod _version; |
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 35f42d28a..e7367d5ed 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs | |||
| @@ -466,7 +466,7 @@ pub fn config() -> Config { | |||
| 466 | mul: PllMul::MUL4, | 466 | mul: PllMul::MUL4, |
| 467 | div: PllDiv::DIV2, // 32Mhz clock (16 * 4 / 2) | 467 | div: PllDiv::DIV2, // 32Mhz clock (16 * 4 / 2) |
| 468 | }); | 468 | }); |
| 469 | config.rcc.mux = ClockSrc::PLL1_P; | 469 | config.rcc.mux = ClockSrc::PLL1_R; |
| 470 | } | 470 | } |
| 471 | 471 | ||
| 472 | #[cfg(any(feature = "stm32l152re"))] | 472 | #[cfg(any(feature = "stm32l152re"))] |
| @@ -478,7 +478,7 @@ pub fn config() -> Config { | |||
| 478 | mul: PllMul::MUL4, | 478 | mul: PllMul::MUL4, |
| 479 | div: PllDiv::DIV2, // 32Mhz clock (16 * 4 / 2) | 479 | div: PllDiv::DIV2, // 32Mhz clock (16 * 4 / 2) |
| 480 | }); | 480 | }); |
| 481 | config.rcc.mux = ClockSrc::PLL1_P; | 481 | config.rcc.mux = ClockSrc::PLL1_R; |
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | config | 484 | config |
