From 066dc297ed4508c334effafcc134296cb776eb06 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 13 Nov 2023 01:05:07 +0100 Subject: [PATCH] stm32/rcc: unify l0l1 and l4l5. --- embassy-stm32/Cargo.toml | 4 +- embassy-stm32/src/rcc/{l4l5.rs => l.rs} | 393 +++++++++++++++--------- embassy-stm32/src/rcc/l0l1.rs | 190 ------------ embassy-stm32/src/rcc/mod.rs | 3 +- tests/stm32/src/common.rs | 4 +- 5 files changed, 260 insertions(+), 334 deletions(-) rename embassy-stm32/src/rcc/{l4l5.rs => l.rs} (58%) delete mode 100644 embassy-stm32/src/rcc/l0l1.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 7b3a6c2b..37317276 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -58,7 +58,7 @@ rand_core = "0.6.3" sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1374ed622714ef4702826699ca21cc1f741f4133" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-c551c07bf12513dd8346a9fe0bc70cf79f2ea02f" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -76,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1374ed622714ef4702826699ca21cc1f741f4133", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-c551c07bf12513dd8346a9fe0bc70cf79f2ea02f", default-features = false, features = ["metadata"]} [features] diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l.rs similarity index 58% rename from embassy-stm32/src/rcc/l4l5.rs rename to embassy-stm32/src/rcc/l.rs index 97f231f6..257fd83f 100644 --- a/embassy-stm32/src/rcc/l4l5.rs +++ b/embassy-stm32/src/rcc/l.rs @@ -1,12 +1,13 @@ +#[cfg(any(stm32l0, stm32l1))] +pub use crate::pac::pwr::vals::Vos as VoltageScale; use crate::pac::rcc::regs::Cfgr; -#[cfg(any(stm32l4, stm32l5, stm32wb))] +#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] +pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; +#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))] pub use crate::pac::rcc::vals::Clk48sel as Clk48Src; #[cfg(any(stm32wb, stm32wl))] pub use crate::pac::rcc::vals::Hsepre as HsePrescaler; -pub use crate::pac::rcc::vals::{ - Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, - Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PllSource, Ppre as APBPrescaler, Sw as ClockSrc, -}; +pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange as MSIRange, Ppre as APBPrescaler, Sw as ClockSrc}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -33,25 +34,6 @@ pub struct Hse { pub prescaler: HsePrescaler, } -#[derive(Clone, Copy)] -pub struct Pll { - /// PLL source - pub source: PllSource, - - /// PLL pre-divider (DIVM). - pub prediv: PllPreDiv, - - /// PLL multiplication factor. - pub mul: PllMul, - - /// PLL P division factor. If None, PLL P output is disabled. - pub divp: Option, - /// PLL Q division factor. If None, PLL Q output is disabled. - pub divq: Option, - /// PLL R division factor. If None, PLL R output is disabled. - pub divr: Option, -} - /// Clocks configuration pub struct Config { // base clock sources @@ -79,13 +61,17 @@ pub struct Config { pub shared_ahb_pre: AHBPrescaler, // muxes - #[cfg(any(stm32l4, stm32l5, stm32wb))] + #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))] pub clk48_src: Clk48Src, // low speed LSI/LSE/RTC pub ls: super::LsConfig, + #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] pub adc_clock_source: AdcClockSource, + + #[cfg(any(stm32l0, stm32l1))] + pub voltage_scale: VoltageScale, } impl Default for Config { @@ -110,10 +96,13 @@ impl Default for Config { pllsai2: None, #[cfg(crs)] hsi48: Some(Default::default()), - #[cfg(any(stm32l4, stm32l5, stm32wb))] + #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))] clk48_src: Clk48Src::HSI48, ls: Default::default(), + #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] adc_clock_source: AdcClockSource::SYS, + #[cfg(any(stm32l0, stm32l1))] + voltage_scale: VoltageScale::RANGE1, } } } @@ -152,20 +141,26 @@ pub const WPAN_DEFAULT: Config = Config { adc_clock_source: AdcClockSource::SYS, }; +fn msi_enable(range: MSIRange) { + #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] + RCC.cr().modify(|w| { + #[cfg(not(stm32wb))] + w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR); + w.set_msirange(range); + w.set_msipllen(false); + }); + #[cfg(any(stm32l0, stm32l1))] + RCC.icscr().modify(|w| w.set_msirange(range)); + + RCC.cr().modify(|w| w.set_msion(true)); + while !RCC.cr().read().msirdy() {} +} + pub(crate) unsafe fn init(config: Config) { // Switch to MSI to prevent problems with PLL configuration. if !RCC.cr().read().msion() { // Turn on MSI and configure it to 4MHz. - RCC.cr().modify(|w| { - #[cfg(not(stm32wb))] - w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR); - w.set_msirange(MSIRange::RANGE4M); - w.set_msipllen(false); - w.set_msion(true) - }); - - // Wait until MSI is running - while !RCC.cr().read().msirdy() {} + msi_enable(MSIRange::RANGE4M) } if RCC.cfgr().read().sws() != ClockSrc::MSI { // Set MSI as a clock source, reset prescalers. @@ -174,6 +169,14 @@ pub(crate) unsafe fn init(config: Config) { while RCC.cfgr().read().sws() != ClockSrc::MSI {} } + // Set voltage scale + #[cfg(any(stm32l0, stm32l1))] + { + while crate::pac::PWR.csr().read().vosf() {} + crate::pac::PWR.cr().write(|w| w.set_vos(config.voltage_scale)); + while crate::pac::PWR.csr().read().vosf() {} + } + #[cfg(stm32l5)] crate::pac::PWR.cr1().modify(|w| { w.set_vos(crate::pac::pwr::vals::Vos::RANGE0); @@ -182,21 +185,16 @@ pub(crate) unsafe fn init(config: Config) { let rtc = config.ls.init(); let msi = config.msi.map(|range| { - // Enable MSI - RCC.cr().modify(|w| { - #[cfg(not(stm32wb))] - w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR); - w.set_msirange(range); - w.set_msion(true); - - // If LSE is enabled, enable calibration of MSI - w.set_msipllen(config.ls.lse.is_some()); - }); - while !RCC.cr().read().msirdy() {} - + msi_enable(range); msirange_to_hertz(range) }); + // If LSE is enabled and the right freq, enable calibration of MSI + #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] + if config.ls.lse.map(|x| x.frequency) == Some(Hertz(32_768)) { + RCC.cr().modify(|w| w.set_msipllen(true)); + } + let hsi = config.hsi.then(|| { RCC.cr().modify(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} @@ -218,7 +216,10 @@ pub(crate) unsafe fn init(config: Config) { }); #[cfg(crs)] - let _hsi48 = config.hsi48.map(super::init_hsi48); + let _hsi48 = config.hsi48.map(|config| { + // + super::init_hsi48(config) + }); #[cfg(not(crs))] let _hsi48: Option = None; @@ -251,7 +252,12 @@ pub(crate) unsafe fn init(config: Config) { }), }; - let pll_input = PllInput { hse, hsi, msi }; + let pll_input = PllInput { + hse, + hsi, + #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] + msi, + }; let pll = init_pll(PllInstance::Pll, config.pll, &pll_input); #[cfg(any(stm32l4, stm32l5, stm32wb))] let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input); @@ -265,10 +271,13 @@ pub(crate) unsafe fn init(config: Config) { ClockSrc::PLL1_R => pll.r.unwrap(), }; - #[cfg(stm32l4)] + #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))] RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src)); - #[cfg(stm32l5)] - RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src)); + #[cfg(any(rcc_l0_v2))] + let _clk48 = match config.clk48_src { + Clk48Src::HSI48 => _hsi48, + Clk48Src::PLL1_VCO_DIV_2 => pll.clk48, + }; #[cfg(any(stm32l4, stm32l5, stm32wb))] let _clk48 = match config.clk48_src { Clk48Src::HSI48 => _hsi48, @@ -285,16 +294,23 @@ pub(crate) unsafe fn init(config: Config) { let hclk1 = sys_clk / config.ahb_pre; let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre); let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); - #[cfg(not(any(stm32wl5x, stm32wb)))] + #[cfg(any(stm32l4, stm32l5, stm32wlex))] let hclk2 = hclk1; #[cfg(any(stm32wl5x, stm32wb))] let hclk2 = sys_clk / config.core2_ahb_pre; - #[cfg(not(any(stm32wl, stm32wb)))] + #[cfg(any(stm32l4, stm32l5, stm32wlex))] let hclk3 = hclk1; - #[cfg(any(stm32wl, stm32wb))] + #[cfg(any(stm32wl5x, stm32wb))] let hclk3 = sys_clk / config.shared_ahb_pre; // Set flash wait states + #[cfg(any(stm32l0, stm32l1))] + let latency = match (config.voltage_scale, sys_clk.0) { + (VoltageScale::RANGE1, ..=16_000_000) => false, + (VoltageScale::RANGE2, ..=8_000_000) => false, + (VoltageScale::RANGE3, ..=4_200_000) => false, + _ => true, + }; #[cfg(stm32l4)] let latency = match hclk1.0 { 0..=16_000_000 => 0, @@ -330,6 +346,10 @@ pub(crate) unsafe fn init(config: Config) { _ => 4, }; + #[cfg(stm32l1)] + FLASH.acr().write(|w| w.set_acc64(true)); + #[cfg(not(stm32l5))] + FLASH.acr().modify(|w| w.set_prften(true)); FLASH.acr().modify(|w| w.set_latency(latency)); while FLASH.acr().read().latency() != latency {} @@ -341,9 +361,7 @@ pub(crate) unsafe fn init(config: Config) { }); while RCC.cfgr().read().sws() != config.mux {} - #[cfg(stm32l5)] - RCC.ccipr1().modify(|w| w.set_adcsel(config.adc_clock_source)); - #[cfg(not(stm32l5))] + #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source)); #[cfg(any(stm32wl, stm32wb))] @@ -361,7 +379,9 @@ pub(crate) unsafe fn init(config: Config) { set_freqs(Clocks { sys: sys_clk, hclk1, + #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] hclk2, + #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] hclk3, pclk1, pclk2, @@ -389,6 +409,12 @@ pub(crate) unsafe fn init(config: Config) { }); } +#[cfg(any(stm32l0, stm32l1))] +fn msirange_to_hertz(range: MSIRange) -> Hertz { + Hertz(32_768 * (1 << (range as u8 + 1))) +} + +#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] fn msirange_to_hertz(range: MSIRange) -> Hertz { match range { MSIRange::RANGE100K => Hertz(100_000), @@ -407,20 +433,6 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz { } } -struct PllInput { - hsi: Option, - hse: Option, - msi: Option, -} - -#[allow(unused)] -#[derive(Default)] -struct PllOutput { - p: Option, - q: Option, - r: Option, -} - #[derive(PartialEq, Eq, Clone, Copy)] enum PllInstance { Pll, @@ -449,77 +461,182 @@ fn pll_enable(instance: PllInstance, enabled: bool) { } } -fn init_pll(instance: PllInstance, config: Option, input: &PllInput) -> PllOutput { - // Disable PLL - pll_enable(instance, false); +pub use pll::*; - let Some(pll) = config else { return PllOutput::default() }; +#[cfg(any(stm32l0, stm32l1))] +mod pll { + use super::{pll_enable, PllInstance}; + pub use crate::pac::rcc::vals::{Plldiv as PllDiv, Pllmul as PllMul, Pllsrc as PllSource}; + use crate::pac::RCC; + use crate::time::Hertz; - let pll_src = match pll.source { - PllSource::DISABLE => panic!("must not select PLL source as DISABLE"), - PllSource::HSE => input.hse, - PllSource::HSI => input.hsi, - PllSource::MSI => input.msi, - }; + #[derive(Clone, Copy)] + pub struct Pll { + /// PLL source + pub source: PllSource, - let pll_src = pll_src.unwrap(); + /// PLL multiplication factor. + pub mul: PllMul, - let vco_freq = pll_src / pll.prediv * pll.mul; - - let p = pll.divp.map(|div| vco_freq / div); - let q = pll.divq.map(|div| vco_freq / div); - let r = pll.divr.map(|div| vco_freq / div); - - #[cfg(stm32l5)] - if instance == PllInstance::Pllsai2 { - assert!(q.is_none(), "PLLSAI2_Q is not available on L5"); - assert!(r.is_none(), "PLLSAI2_R is not available on L5"); + /// PLL main output division factor. + pub div: PllDiv, } - macro_rules! write_fields { - ($w:ident) => { - $w.set_plln(pll.mul); - if let Some(divp) = pll.divp { - $w.set_pllp(divp); - $w.set_pllpen(true); - } - if let Some(divq) = pll.divq { - $w.set_pllq(divq); - $w.set_pllqen(true); - } - if let Some(divr) = pll.divr { - $w.set_pllr(divr); - $w.set_pllren(true); - } + pub(super) struct PllInput { + pub hsi: Option, + pub hse: Option, + } + + #[allow(unused)] + #[derive(Default)] + pub(super) struct PllOutput { + pub r: Option, + pub clk48: Option, + } + + pub(super) fn init_pll(instance: PllInstance, config: Option, input: &PllInput) -> PllOutput { + // Disable PLL + pll_enable(instance, false); + + let Some(pll) = config else { return PllOutput::default() }; + + let pll_src = match pll.source { + PllSource::HSE => unwrap!(input.hse), + PllSource::HSI => unwrap!(input.hsi), }; + + let vco_freq = pll_src * pll.mul; + + let r = vco_freq / pll.div; + let clk48 = (vco_freq == Hertz(96_000_000)).then_some(Hertz(48_000_000)); + + assert!(r <= Hertz(32_000_000)); + + RCC.cfgr().write(move |w| { + w.set_pllmul(pll.mul); + w.set_plldiv(pll.div); + w.set_pllsrc(pll.source); + }); + + // Enable PLL + pll_enable(instance, true); + + PllOutput { r: Some(r), clk48 } + } +} + +#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))] +mod pll { + use super::{pll_enable, PllInstance}; + pub use crate::pac::rcc::vals::{ + Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PllSource, + }; + use crate::pac::RCC; + use crate::time::Hertz; + + #[derive(Clone, Copy)] + pub struct Pll { + /// PLL source + pub source: PllSource, + + /// PLL pre-divider (DIVM). + pub prediv: PllPreDiv, + + /// PLL multiplication factor. + pub mul: PllMul, + + /// PLL P division factor. If None, PLL P output is disabled. + pub divp: Option, + /// PLL Q division factor. If None, PLL Q output is disabled. + pub divq: Option, + /// PLL R division factor. If None, PLL R output is disabled. + pub divr: Option, + } + + pub(super) struct PllInput { + pub hsi: Option, + pub hse: Option, + pub msi: Option, + } + + #[allow(unused)] + #[derive(Default)] + pub(super) struct PllOutput { + pub p: Option, + pub q: Option, + pub r: Option, + } + + pub(super) fn init_pll(instance: PllInstance, config: Option, input: &PllInput) -> PllOutput { + // Disable PLL + pll_enable(instance, false); + + let Some(pll) = config else { return PllOutput::default() }; + + let pll_src = match pll.source { + PllSource::DISABLE => panic!("must not select PLL source as DISABLE"), + PllSource::HSE => unwrap!(input.hse), + PllSource::HSI => unwrap!(input.hsi), + PllSource::MSI => unwrap!(input.msi), + }; + + let vco_freq = pll_src / pll.prediv * pll.mul; + + let p = pll.divp.map(|div| vco_freq / div); + let q = pll.divq.map(|div| vco_freq / div); + let r = pll.divr.map(|div| vco_freq / div); + + #[cfg(stm32l5)] + if instance == PllInstance::Pllsai2 { + assert!(q.is_none(), "PLLSAI2_Q is not available on L5"); + assert!(r.is_none(), "PLLSAI2_R is not available on L5"); + } + + macro_rules! write_fields { + ($w:ident) => { + $w.set_plln(pll.mul); + if let Some(divp) = pll.divp { + $w.set_pllp(divp); + $w.set_pllpen(true); + } + if let Some(divq) = pll.divq { + $w.set_pllq(divq); + $w.set_pllqen(true); + } + if let Some(divr) = pll.divr { + $w.set_pllr(divr); + $w.set_pllren(true); + } + }; + } + + match instance { + PllInstance::Pll => RCC.pllcfgr().write(|w| { + w.set_pllm(pll.prediv); + w.set_pllsrc(pll.source); + write_fields!(w); + }), + #[cfg(any(stm32l4, stm32l5, stm32wb))] + PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| { + #[cfg(any(rcc_l4plus, stm32l5))] + w.set_pllm(pll.prediv); + #[cfg(stm32l5)] + w.set_pllsrc(pll.source); + write_fields!(w); + }), + #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] + PllInstance::Pllsai2 => RCC.pllsai2cfgr().write(|w| { + #[cfg(any(rcc_l4plus, stm32l5))] + w.set_pllm(pll.prediv); + #[cfg(stm32l5)] + w.set_pllsrc(pll.source); + write_fields!(w); + }), + } + + // Enable PLL + pll_enable(instance, true); + + PllOutput { p, q, r } } - - match instance { - PllInstance::Pll => RCC.pllcfgr().write(|w| { - w.set_pllm(pll.prediv); - w.set_pllsrc(pll.source); - write_fields!(w); - }), - #[cfg(any(stm32l4, stm32l5, stm32wb))] - PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| { - #[cfg(any(rcc_l4plus, stm32l5))] - w.set_pllm(pll.prediv); - #[cfg(stm32l5)] - w.set_pllsrc(pll.source); - write_fields!(w); - }), - #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] - PllInstance::Pllsai2 => RCC.pllsai2cfgr().write(|w| { - #[cfg(any(rcc_l4plus, stm32l5))] - w.set_pllm(pll.prediv); - #[cfg(stm32l5)] - w.set_pllsrc(pll.source); - write_fields!(w); - }), - } - - // Enable PLL - pll_enable(instance, true); - - PllOutput { p, q, r } } diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs deleted file mode 100644 index c3d58e8e..00000000 --- a/embassy-stm32/src/rcc/l0l1.rs +++ /dev/null @@ -1,190 +0,0 @@ -pub use crate::pac::pwr::vals::Vos as VoltageScale; -pub use crate::pac::rcc::vals::{ - Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PllDiv, Pllmul as PllMul, Pllsrc as PllSource, - Ppre as APBPrescaler, Sw as ClockSrc, -}; -use crate::pac::{FLASH, PWR, RCC}; -use crate::rcc::{set_freqs, Clocks}; -use crate::time::Hertz; - -/// HSI speed -pub const HSI_FREQ: Hertz = Hertz(16_000_000); - -#[derive(Clone, Copy, Eq, PartialEq)] -pub enum HseMode { - /// crystal/ceramic oscillator (HSEBYP=0) - Oscillator, - /// external analog clock (low swing) (HSEBYP=1) - Bypass, -} - -#[derive(Clone, Copy, Eq, PartialEq)] -pub struct Hse { - /// HSE frequency. - pub freq: Hertz, - /// HSE mode. - pub mode: HseMode, -} - -#[derive(Clone, Copy)] -pub struct Pll { - /// PLL source - pub source: PllSource, - - /// PLL multiplication factor. - pub mul: PllMul, - - /// PLL main output division factor. - pub div: PllDiv, -} - -/// Clocks configutation -pub struct Config { - // base clock sources - pub msi: Option, - pub hsi: bool, - pub hse: Option, - #[cfg(crs)] - pub hsi48: Option, - - pub pll: Option, - - pub mux: ClockSrc, - pub ahb_pre: AHBPrescaler, - pub apb1_pre: APBPrescaler, - pub apb2_pre: APBPrescaler, - - pub ls: super::LsConfig, - pub voltage_scale: VoltageScale, -} - -impl Default for Config { - #[inline] - fn default() -> Config { - Config { - msi: Some(MSIRange::RANGE5), - hse: None, - hsi: false, - #[cfg(crs)] - hsi48: Some(Default::default()), - - pll: None, - - mux: ClockSrc::MSI, - ahb_pre: AHBPrescaler::DIV1, - apb1_pre: APBPrescaler::DIV1, - apb2_pre: APBPrescaler::DIV1, - voltage_scale: VoltageScale::RANGE1, - ls: Default::default(), - } - } -} - -pub(crate) unsafe fn init(config: Config) { - // Set voltage scale - while PWR.csr().read().vosf() {} - PWR.cr().write(|w| w.set_vos(config.voltage_scale)); - while PWR.csr().read().vosf() {} - - let rtc = config.ls.init(); - - let msi = config.msi.map(|range| { - RCC.icscr().modify(|w| w.set_msirange(range)); - - RCC.cr().modify(|w| w.set_msion(true)); - while !RCC.cr().read().msirdy() {} - - Hertz(32_768 * (1 << (range as u8 + 1))) - }); - - let hsi = config.hsi.then(|| { - RCC.cr().modify(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - - HSI_FREQ - }); - - let hse = config.hse.map(|hse| { - RCC.cr().modify(|w| { - w.set_hsebyp(hse.mode == HseMode::Bypass); - w.set_hseon(true); - }); - while !RCC.cr().read().hserdy() {} - - hse.freq - }); - - let pll = config.pll.map(|pll| { - let freq = match pll.source { - PllSource::HSE => hse.unwrap(), - PllSource::HSI => hsi.unwrap(), - }; - - // Disable PLL - RCC.cr().modify(|w| w.set_pllon(false)); - while RCC.cr().read().pllrdy() {} - - let freq = freq * pll.mul / pll.div; - - assert!(freq <= Hertz(32_000_000)); - - RCC.cfgr().write(move |w| { - w.set_pllmul(pll.mul); - w.set_plldiv(pll.div); - w.set_pllsrc(pll.source); - }); - - // Enable PLL - RCC.cr().modify(|w| w.set_pllon(true)); - while !RCC.cr().read().pllrdy() {} - - freq - }); - - let sys_clk = match config.mux { - ClockSrc::HSE => hse.unwrap(), - ClockSrc::HSI => hsi.unwrap(), - ClockSrc::MSI => msi.unwrap(), - ClockSrc::PLL1_P => pll.unwrap(), - }; - - let wait_states = match (config.voltage_scale, sys_clk.0) { - (VoltageScale::RANGE1, ..=16_000_000) => 0, - (VoltageScale::RANGE2, ..=8_000_000) => 0, - (VoltageScale::RANGE3, ..=4_200_000) => 0, - _ => 1, - }; - - #[cfg(stm32l1)] - FLASH.acr().write(|w| w.set_acc64(true)); - FLASH.acr().modify(|w| w.set_prften(true)); - FLASH.acr().modify(|w| w.set_latency(wait_states != 0)); - - RCC.cfgr().modify(|w| { - w.set_sw(config.mux); - w.set_hpre(config.ahb_pre); - w.set_ppre1(config.apb1_pre); - w.set_ppre2(config.apb2_pre); - }); - - let hclk1 = sys_clk / config.ahb_pre; - let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre); - let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); - - #[cfg(crs)] - let _hsi48 = config.hsi48.map(|config| { - // Select HSI48 as USB clock - RCC.ccipr().modify(|w| w.set_hsi48msel(true)); - super::init_hsi48(config) - }); - - set_freqs(Clocks { - sys: sys_clk, - hclk1, - pclk1, - pclk2, - pclk1_tim, - pclk2_tim, - rtc, - }); -} diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index e15f4fe4..debd16ca 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -23,8 +23,7 @@ pub use hsi48::*; #[cfg_attr(rcc_g0, path = "g0.rs")] #[cfg_attr(rcc_g4, path = "g4.rs")] #[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")] -#[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")] -#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle, rcc_wb), path = "l4l5.rs")] +#[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl), path = "l.rs")] #[cfg_attr(rcc_u5, path = "u5.rs")] #[cfg_attr(rcc_wba, path = "wba.rs")] mod _version; diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 35f42d28..e7367d5e 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -466,7 +466,7 @@ pub fn config() -> Config { mul: PllMul::MUL4, div: PllDiv::DIV2, // 32Mhz clock (16 * 4 / 2) }); - config.rcc.mux = ClockSrc::PLL1_P; + config.rcc.mux = ClockSrc::PLL1_R; } #[cfg(any(feature = "stm32l152re"))] @@ -478,7 +478,7 @@ pub fn config() -> Config { mul: PllMul::MUL4, div: PllDiv::DIV2, // 32Mhz clock (16 * 4 / 2) }); - config.rcc.mux = ClockSrc::PLL1_P; + config.rcc.mux = ClockSrc::PLL1_R; } config