From b91d1eaca07a65e8d4b688a3f9059c5578e92836 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 11 Oct 2023 03:53:27 +0200 Subject: [PATCH] stm32/rcc: add LSE/LSI to all chips, add RTC to more chips. --- embassy-stm32/Cargo.toml | 4 +- embassy-stm32/src/rcc/bd.rs | 219 +++++++++++------- embassy-stm32/src/rcc/c0.rs | 10 +- embassy-stm32/src/rcc/f0.rs | 8 +- embassy-stm32/src/rcc/f1.rs | 8 +- embassy-stm32/src/rcc/f2.rs | 20 +- embassy-stm32/src/rcc/f3.rs | 7 +- embassy-stm32/src/rcc/f4.rs | 25 +- embassy-stm32/src/rcc/f7.rs | 20 +- embassy-stm32/src/rcc/g0.rs | 10 +- embassy-stm32/src/rcc/g4.rs | 9 +- embassy-stm32/src/rcc/h.rs | 40 +--- embassy-stm32/src/rcc/l0l1.rs | 20 +- embassy-stm32/src/rcc/l4.rs | 23 +- embassy-stm32/src/rcc/l5.rs | 23 +- embassy-stm32/src/rcc/mod.rs | 18 +- embassy-stm32/src/rcc/u5.rs | 9 +- embassy-stm32/src/rcc/wb.rs | 66 ++---- embassy-stm32/src/rcc/wba.rs | 9 +- embassy-stm32/src/rcc/wl.rs | 26 +-- embassy-stm32/src/rtc/mod.rs | 16 +- examples/stm32f4/src/bin/rtc.rs | 6 +- examples/stm32h7/src/bin/rtc.rs | 14 +- examples/stm32l4/src/bin/rtc.rs | 5 +- .../src/bin/spe_adin1110_http_server.rs | 2 - examples/stm32wl/src/bin/lora_lorawan.rs | 1 - examples/stm32wl/src/bin/random.rs | 1 - examples/stm32wl/src/bin/rtc.rs | 8 +- tests/stm32/Cargo.toml | 20 +- tests/stm32/src/bin/rtc.rs | 16 +- tests/stm32/src/bin/stop.rs | 7 +- 31 files changed, 267 insertions(+), 403 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 6137e3c0..33583d22 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -59,7 +59,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9f45b0c48cc3de71ec6a66fe7e871b21aef0940c" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6bfa5a0dcec6a9bd42cea94ba11eeae1a17a7f2c" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -77,7 +77,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-9f45b0c48cc3de71ec6a66fe7e871b21aef0940c", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6bfa5a0dcec6a9bd42cea94ba11eeae1a17a7f2c", default-features = false, features = ["metadata"]} [features] diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs index c18e92bc..66ca65f8 100644 --- a/embassy-stm32/src/rcc/bd.rs +++ b/embassy-stm32/src/rcc/bd.rs @@ -1,14 +1,24 @@ +use core::sync::atomic::{compiler_fence, Ordering}; + +use crate::pac::common::{Reg, RW}; +pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource; +use crate::time::Hertz; + +#[cfg(any(stm32f0, stm32f1, stm32f3))] +pub const LSI_FREQ: Hertz = Hertz(40_000); +#[cfg(not(any(stm32f0, stm32f1, stm32f3)))] +pub const LSI_FREQ: Hertz = Hertz(32_000); + #[allow(dead_code)] #[derive(Clone, Copy)] -pub enum LseCfg { +pub enum LseMode { Oscillator(LseDrive), Bypass, } -impl Default for LseCfg { - fn default() -> Self { - Self::Oscillator(Default::default()) - } +pub struct LseConfig { + pub frequency: Hertz, + pub mode: LseMode, } #[allow(dead_code)] @@ -36,90 +46,116 @@ impl From for crate::pac::rcc::vals::Lsedrv { } } -pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource; - #[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))] -#[allow(dead_code)] type Bdcr = crate::pac::rcc::regs::Bdcr; - #[cfg(any(rtc_v2l0, rtc_v2l1))] -#[allow(dead_code)] type Bdcr = crate::pac::rcc::regs::Csr; +#[cfg(any(stm32c0))] +type Bdcr = crate::pac::rcc::regs::Csr1; -#[allow(dead_code)] -pub struct BackupDomain {} +#[cfg(any(stm32c0))] +fn unlock() {} -impl BackupDomain { - #[cfg(any( - rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, - rtc_v3u5 - ))] - #[allow(dead_code, unused_variables)] - fn modify(f: impl FnOnce(&mut Bdcr) -> R) -> R { - #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1, rtc_v2l0))] - let cr = crate::pac::PWR.cr(); - #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] - let cr = crate::pac::PWR.cr1(); +#[cfg(not(any(stm32c0)))] +fn unlock() { + #[cfg(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1))] + let cr = crate::pac::PWR.cr(); + #[cfg(not(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1, stm32u5, stm32h5, stm32wba)))] + let cr = crate::pac::PWR.cr1(); + #[cfg(any(stm32u5, stm32h5, stm32wba))] + let cr = crate::pac::PWR.dbpcr(); - // TODO: Missing from PAC for l0 and f0? - #[cfg(not(any(rtc_v2f0, rtc_v3u5)))] - { - cr.modify(|w| w.set_dbp(true)); - while !cr.read().dbp() {} + cr.modify(|w| w.set_dbp(true)); + while !cr.read().dbp() {} +} + +fn bdcr() -> Reg { + #[cfg(any(rtc_v2l0, rtc_v2l1))] + return crate::pac::RCC.csr(); + #[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))] + return crate::pac::RCC.bdcr(); + #[cfg(any(stm32c0))] + return crate::pac::RCC.csr1(); +} + +pub struct LsConfig { + pub rtc: RtcClockSource, + pub lsi: bool, + pub lse: Option, +} + +impl LsConfig { + pub const fn default_lse() -> Self { + Self { + rtc: RtcClockSource::LSE, + lse: Some(LseConfig { + frequency: Hertz(32_000), + mode: LseMode::Oscillator(LseDrive::MediumHigh), + }), + lsi: false, } - - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - - cr.modify(|w| f(w)) } - #[cfg(any( - rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, - rtc_v3u5 - ))] - #[allow(dead_code)] - fn read() -> Bdcr { - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let r = crate::pac::RCC.csr().read(); - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let r = crate::pac::RCC.bdcr().read(); - - r + pub const fn default_lsi() -> Self { + Self { + rtc: RtcClockSource::LSI, + lsi: true, + lse: None, + } } - #[cfg(any( - rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, - rtc_v3u5 - ))] - #[allow(dead_code, unused_variables)] - pub fn configure_ls(clock_source: RtcClockSource, lsi: bool, lse: Option) { - use atomic_polyfill::{compiler_fence, Ordering}; + pub const fn off() -> Self { + Self { + rtc: RtcClockSource::NOCLOCK, + lsi: false, + lse: None, + } + } +} - match clock_source { - RtcClockSource::LSI => assert!(lsi), - RtcClockSource::LSE => assert!(lse.is_some()), - _ => {} +impl Default for LsConfig { + fn default() -> Self { + // on L5, just the fact that LSI is enabled makes things crash. + // TODO: investigate. + + #[cfg(not(stm32l5))] + return Self::default_lsi(); + #[cfg(stm32l5)] + return Self::off(); + } +} + +impl LsConfig { + pub(crate) fn init(&self) -> Option { + let rtc_clk = match self.rtc { + RtcClockSource::LSI => { + assert!(self.lsi); + Some(LSI_FREQ) + } + RtcClockSource::LSE => Some(self.lse.as_ref().unwrap().frequency), + RtcClockSource::NOCLOCK => None, + _ => todo!(), }; - let (lse_en, lse_byp, lse_drv) = match lse { - Some(LseCfg::Oscillator(lse_drv)) => (true, false, Some(lse_drv)), - Some(LseCfg::Bypass) => (true, true, None), + + let (lse_en, lse_byp, lse_drv) = match &self.lse { + Some(c) => match c.mode { + LseMode::Oscillator(lse_drv) => (true, false, Some(lse_drv)), + LseMode::Bypass => (true, true, None), + }, None => (false, false, None), }; + _ = lse_drv; // not all chips have it. - if lsi { - #[cfg(rtc_v3u5)] + // Disable backup domain write protection + unlock(); + + if self.lsi { + #[cfg(any(stm32u5, stm32h5, stm32wba))] let csr = crate::pac::RCC.bdcr(); - - #[cfg(not(rtc_v3u5))] + #[cfg(not(any(stm32u5, stm32h5, stm32wba, stm32c0)))] let csr = crate::pac::RCC.csr(); - - // Disable backup domain write protection - Self::modify(|_| {}); + #[cfg(any(stm32c0))] + let csr = crate::pac::RCC.csr2(); #[cfg(not(any(rcc_wb, rcc_wba)))] csr.modify(|w| w.set_lsion(true)); @@ -139,12 +175,12 @@ impl BackupDomain { // first check if the configuration matches what we want. // check if it's already enabled and in the source we want. - let reg = Self::read(); + let reg = bdcr().read(); let mut ok = true; - ok &= reg.rtcsel() == clock_source; + ok &= reg.rtcsel() == self.rtc; #[cfg(not(rcc_wba))] { - ok &= reg.rtcen() == (clock_source != RtcClockSource::NOCLOCK); + ok &= reg.rtcen() == (self.rtc != RtcClockSource::NOCLOCK); } ok &= reg.lseon() == lse_en; ok &= reg.lsebyp() == lse_byp; @@ -155,22 +191,29 @@ impl BackupDomain { // if configuration is OK, we're done. if ok { - // RTC code assumes backup domain is unlocked - Self::modify(|w| {}); - - trace!("BDCR ok: {:08x}", Self::read().0); - return; + trace!("BDCR ok: {:08x}", bdcr().read().0); + return rtc_clk; } // If not OK, reset backup domain and configure it. - #[cfg(not(any(rcc_l0, rcc_l0_v2, rcc_l1)))] + #[cfg(not(any(rcc_l0, rcc_l0_v2, rcc_l1, stm32h5, stm32c0)))] { - Self::modify(|w| w.set_bdrst(true)); - Self::modify(|w| w.set_bdrst(false)); + bdcr().modify(|w| w.set_bdrst(true)); + bdcr().modify(|w| w.set_bdrst(false)); + } + #[cfg(any(stm32h5))] + { + bdcr().modify(|w| w.set_vswrst(true)); + bdcr().modify(|w| w.set_vswrst(false)); + } + #[cfg(any(stm32c0))] + { + bdcr().modify(|w| w.set_rtcrst(true)); + bdcr().modify(|w| w.set_rtcrst(false)); } if lse_en { - Self::modify(|w| { + bdcr().modify(|w| { #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f400, rcc_f410, rcc_l1)))] if let Some(lse_drv) = lse_drv { w.set_lsedrv(lse_drv.into()); @@ -179,22 +222,24 @@ impl BackupDomain { w.set_lseon(true); }); - while !Self::read().lserdy() {} + while !bdcr().read().lserdy() {} } - if clock_source != RtcClockSource::NOCLOCK { - Self::modify(|w| { + if self.rtc != RtcClockSource::NOCLOCK { + bdcr().modify(|w| { #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet."); #[cfg(not(rcc_wba))] w.set_rtcen(true); - w.set_rtcsel(clock_source); + w.set_rtcsel(self.rtc); }); } - trace!("BDCR configured: {:08x}", Self::read().0); + trace!("BDCR configured: {:08x}", bdcr().read().0); compiler_fence(Ordering::SeqCst); + + rtc_clk } } diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index 34d339a7..eeb6418a 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -8,9 +8,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(48_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -24,6 +21,7 @@ pub struct Config { pub mux: ClockSrc, pub ahb_pre: AHBPrescaler, pub apb_pre: APBPrescaler, + pub ls: super::LsConfig, } impl Default for Config { @@ -33,6 +31,7 @@ impl Default for Config { mux: ClockSrc::HSI(HSIPrescaler::DIV1), ahb_pre: AHBPrescaler::DIV1, apb_pre: APBPrescaler::DIV1, + ls: Default::default(), } } } @@ -60,10 +59,12 @@ pub(crate) unsafe fn init(config: Config) { // Enable LSI RCC.csr2().write(|w| w.set_lsion(true)); while !RCC.csr2().read().lsirdy() {} - (LSI_FREQ, Sw::LSI) + (super::LSI_FREQ, Sw::LSI) } }; + let rtc = config.ls.init(); + // Determine the flash latency implied by the target clock speed // RM0454 § 3.3.4: let target_flash_latency = if sys_clk <= Hertz(24_000_000) { @@ -137,5 +138,6 @@ pub(crate) unsafe fn init(config: Config) { ahb1: ahb_freq, apb1: apb_freq, apb1_tim: apb_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/f0.rs b/embassy-stm32/src/rcc/f0.rs index ca6eed28..cc712e87 100644 --- a/embassy-stm32/src/rcc/f0.rs +++ b/embassy-stm32/src/rcc/f0.rs @@ -8,9 +8,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(8_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(40_000); - /// Configuration of the clocks /// /// hse takes precedence over hsi48 if both are enabled @@ -27,6 +24,8 @@ pub struct Config { pub sys_ck: Option, pub hclk: Option, pub pclk: Option, + + pub ls: super::LsConfig, } pub(crate) unsafe fn init(config: Config) { @@ -159,6 +158,8 @@ pub(crate) unsafe fn init(config: Config) { }) } + let rtc = config.ls.init(); + set_freqs(Clocks { sys: Hertz(real_sysclk), apb1: Hertz(pclk), @@ -166,5 +167,6 @@ pub(crate) unsafe fn init(config: Config) { apb1_tim: Hertz(pclk * timer_mul), apb2_tim: Hertz(pclk * timer_mul), ahb1: Hertz(hclk), + rtc, }); } diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs index 081c0c76..56c49cd8 100644 --- a/embassy-stm32/src/rcc/f1.rs +++ b/embassy-stm32/src/rcc/f1.rs @@ -9,9 +9,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(8_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(40_000); - /// Configuration of the clocks /// #[non_exhaustive] @@ -25,6 +22,8 @@ pub struct Config { pub pclk2: Option, pub adcclk: Option, pub pllxtpre: bool, + + pub ls: super::LsConfig, } pub(crate) unsafe fn init(config: Config) { @@ -177,6 +176,8 @@ pub(crate) unsafe fn init(config: Config) { }); }); + let rtc = config.ls.init(); + set_freqs(Clocks { sys: Hertz(real_sysclk), apb1: Hertz(pclk1), @@ -185,5 +186,6 @@ pub(crate) unsafe fn init(config: Config) { apb2_tim: Hertz(pclk2 * timer_mul2), ahb1: Hertz(hclk), adc: Some(Hertz(adcclk)), + rtc, }); } diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs index 478d8894..ab588233 100644 --- a/embassy-stm32/src/rcc/f2.rs +++ b/embassy-stm32/src/rcc/f2.rs @@ -5,17 +5,12 @@ pub use crate::pac::rcc::vals::{ Ppre as APBPrescaler, }; use crate::pac::{FLASH, RCC}; -use crate::rcc::bd::BackupDomain; use crate::rcc::{set_freqs, Clocks}; -use crate::rtc::RtcClockSource; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - #[derive(Clone, Copy)] pub struct HSEConfig { pub frequency: Hertz, @@ -180,13 +175,11 @@ pub struct Config { pub pll_mux: PLLSrc, pub pll: PLLConfig, pub mux: ClockSrc, - pub rtc: Option, - pub lsi: bool, - pub lse: Option, pub voltage: VoltageScale, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, + pub ls: super::LsConfig, } impl Default for Config { @@ -199,12 +192,10 @@ impl Default for Config { pll: PLLConfig::default(), voltage: VoltageScale::Range3, mux: ClockSrc::HSI, - rtc: None, - lsi: false, - lse: None, ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, + ls: Default::default(), } } } @@ -312,11 +303,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().modify(|w| w.set_hsion(false)); } - BackupDomain::configure_ls( - config.rtc.unwrap_or(RtcClockSource::NOCLOCK), - config.lsi, - config.lse.map(|_| Default::default()), - ); + let rtc = config.ls.init(); set_freqs(Clocks { sys: sys_clk, @@ -328,5 +315,6 @@ pub(crate) unsafe fn init(config: Config) { apb2: apb2_freq, apb2_tim: apb2_tim_freq, pll48: Some(pll_clocks.pll48_freq), + rtc, }); } diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs index a11eeee5..2aa79cec 100644 --- a/embassy-stm32/src/rcc/f3.rs +++ b/embassy-stm32/src/rcc/f3.rs @@ -10,9 +10,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(8_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(40_000); - #[cfg(rcc_f3)] impl From for Ckmode { fn from(value: AdcClockSource) -> Self { @@ -87,6 +84,7 @@ pub struct Config { pub adc34: Option, #[cfg(stm32f334)] pub hrtim: HrtimClockSource, + pub ls: super::LsConfig, } // Information required to setup the PLL clock @@ -279,6 +277,8 @@ pub(crate) unsafe fn init(config: Config) { } }; + let rtc = config.ls.init(); + set_freqs(Clocks { sys: sysclk, apb1: pclk1, @@ -294,6 +294,7 @@ pub(crate) unsafe fn init(config: Config) { adc34: None, #[cfg(stm32f334)] hrtim: hrtim, + rtc, }); } diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 754a0d57..79c2d2f6 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -1,17 +1,11 @@ -use stm32_metapac::rcc::vals::{Pllm, Plln, Pllq, Pllr}; - -use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; +use crate::pac::rcc::vals::{Hpre, Pllm, Plln, Pllq, Pllr, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; -use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// Clocks configuration #[non_exhaustive] #[derive(Default)] @@ -30,9 +24,7 @@ pub struct Config { pub pllsai: Option, pub pll48: bool, - pub rtc: Option, - pub lsi: bool, - pub lse: Option, + pub ls: super::LsConfig, } #[cfg(stm32f410)] @@ -344,17 +336,7 @@ pub(crate) unsafe fn init(config: Config) { }) }); - BackupDomain::configure_ls( - config.rtc.unwrap_or(RtcClockSource::NOCLOCK), - config.lsi, - config.lse.map(|_| Default::default()), - ); - - let rtc = match config.rtc { - Some(RtcClockSource::LSI) => Some(LSI_FREQ), - Some(RtcClockSource::LSE) => Some(config.lse.unwrap()), - _ => None, - }; + let rtc = config.ls.init(); set_freqs(Clocks { sys: Hertz(sysclk), @@ -377,7 +359,6 @@ pub(crate) unsafe fn init(config: Config) { pllsai: plls.pllsaiclk.map(Hertz), rtc, - rtc_hse: None, }); } diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs index 565f6aa9..0a0a1cf2 100644 --- a/embassy-stm32/src/rcc/f7.rs +++ b/embassy-stm32/src/rcc/f7.rs @@ -1,16 +1,12 @@ use crate::pac::pwr::vals::Vos; use crate::pac::rcc::vals::{Hpre, Pllm, Plln, Pllp, Pllq, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; -use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// Clocks configuration #[non_exhaustive] #[derive(Default)] @@ -23,9 +19,7 @@ pub struct Config { pub pclk2: Option, pub pll48: bool, - pub rtc: Option, - pub lsi: bool, - pub lse: Option, + pub ls: super::LsConfig, } fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48clk: bool) -> PllResults { @@ -261,17 +255,7 @@ pub(crate) unsafe fn init(config: Config) { }) }); - BackupDomain::configure_ls( - config.rtc.unwrap_or(RtcClockSource::NOCLOCK), - config.lsi, - config.lse.map(|_| Default::default()), - ); - - let rtc = match config.rtc { - Some(RtcClockSource::LSI) => Some(LSI_FREQ), - Some(RtcClockSource::LSE) => Some(config.lse.unwrap()), - _ => None, - }; + let rtc = config.ls.init(); set_freqs(Clocks { sys: Hertz(sysclk), diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index 823836af..962b1dc0 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -10,9 +10,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -73,6 +70,7 @@ pub struct Config { pub ahb_pre: AHBPrescaler, pub apb_pre: APBPrescaler, pub low_power_run: bool, + pub ls: super::LsConfig, } impl Default for Config { @@ -83,6 +81,7 @@ impl Default for Config { ahb_pre: AHBPrescaler::DIV1, apb_pre: APBPrescaler::DIV1, low_power_run: false, + ls: Default::default(), } } } @@ -193,7 +192,7 @@ pub(crate) unsafe fn init(config: Config) { // Enable LSI RCC.csr().write(|w| w.set_lsion(true)); while !RCC.csr().read().lsirdy() {} - (LSI_FREQ, Sw::LSI) + (super::LSI_FREQ, Sw::LSI) } }; @@ -272,10 +271,13 @@ pub(crate) unsafe fn init(config: Config) { PWR.cr1().modify(|w| w.set_lpr(true)); } + let rtc = config.ls.init(); + set_freqs(Clocks { sys: sys_clk, ahb1: ahb_freq, apb1: apb_freq, apb1_tim: apb_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 43256524..a4078e38 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -14,9 +14,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -101,6 +98,8 @@ pub struct Config { pub clock_48mhz_src: Option, pub adc12_clock_source: AdcClockSource, pub adc345_clock_source: AdcClockSource, + + pub ls: super::LsConfig, } /// Configuration for the Clock Recovery System (CRS) used to trim the HSI48 oscillator. @@ -122,6 +121,7 @@ impl Default for Config { clock_48mhz_src: None, adc12_clock_source: Adcsel::NOCLK, adc345_clock_source: Adcsel::NOCLK, + ls: Default::default(), } } } @@ -344,6 +344,8 @@ pub(crate) unsafe fn init(config: Config) { PWR.cr1().modify(|w| w.set_lpr(true)); } + let rtc = config.ls.init(); + set_freqs(Clocks { sys: sys_clk, ahb1: ahb_freq, @@ -354,5 +356,6 @@ pub(crate) unsafe fn init(config: Config) { apb2_tim: apb2_tim_freq, adc: adc12_ck, adc34: adc345_ck, + rtc, }); } diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index d2906499..7236d82f 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -9,8 +9,6 @@ pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre}; pub use crate::pac::rcc::vals::{Ckpersel as PerClockSource, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul}; use crate::pac::{FLASH, PWR, RCC}; -#[cfg(stm32h7)] -use crate::rcc::bd::{BackupDomain, LseCfg, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -23,9 +21,6 @@ pub const CSI_FREQ: Hertz = Hertz(4_000_000); /// HSI48 speed pub const HSI48_FREQ: Hertz = Hertz(48_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - const VCO_RANGE: RangeInclusive = Hertz(150_000_000)..=Hertz(420_000_000); #[cfg(any(stm32h5, pwr_h7rm0455))] const VCO_WIDE_RANGE: RangeInclusive = Hertz(128_000_000)..=Hertz(560_000_000); @@ -196,8 +191,7 @@ pub struct Config { pub adc_clock_source: AdcClockSource, pub timer_prescaler: TimerPrescaler, pub voltage_scale: VoltageScale, - #[cfg(stm32h7)] - pub rtc_mux: Option, + pub ls: super::LsConfig, } impl Default for Config { @@ -231,8 +225,7 @@ impl Default for Config { adc_clock_source: AdcClockSource::from_bits(0), // PLL2_P on H7, HCLK on H5 timer_prescaler: TimerPrescaler::DefaultX2, voltage_scale: VoltageScale::Scale0, - #[cfg(stm32h7)] - rtc_mux: None, + ls: Default::default(), } } } @@ -471,18 +464,7 @@ pub(crate) unsafe fn init(config: Config) { flash_setup(hclk, config.voltage_scale); - #[cfg(stm32h7)] - { - let lsecfg = config.lse.map(|lse| match lse { - Lse::Bypass(freq) => { - assert!(freq <= Hertz(1_000_000)); - LseCfg::Bypass - } - Lse::Oscillator => LseCfg::Oscillator(Default::default()), - }); - - BackupDomain::configure_ls(config.rtc_mux.unwrap_or(RtcClockSource::NOCLOCK), config.lsi, lsecfg); - } + let rtc = config.ls.init(); #[cfg(stm32h7)] { @@ -548,17 +530,6 @@ pub(crate) unsafe fn init(config: Config) { while !pac::SYSCFG.cccsr().read().ready() {} } - #[cfg(stm32h7)] - let rtc_clk = match config.rtc_mux { - Some(RtcClockSource::LSI) => Some(LSI_FREQ), - Some(RtcClockSource::LSE) => Some(match config.lse { - Some(Lse::Oscillator) => Hertz(32768), - Some(Lse::Bypass(freq)) => freq, - None => panic!("LSE not configured"), - }), - _ => None, - }; - set_freqs(Clocks { sys, ahb1: hclk, @@ -573,10 +544,7 @@ pub(crate) unsafe fn init(config: Config) { apb1_tim, apb2_tim, adc, - #[cfg(stm32h7)] - rtc: rtc_clk, - #[cfg(stm32h7)] - rtc_hse: None, + rtc, }); } diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs index 4b1acae5..d8a1fc10 100644 --- a/embassy-stm32/src/rcc/l0l1.rs +++ b/embassy-stm32/src/rcc/l0l1.rs @@ -1,5 +1,3 @@ -use super::bd::BackupDomain; -use super::RtcClockSource; 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, Ppre as APBPrescaler, @@ -14,9 +12,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -50,9 +45,7 @@ pub struct Config { pub apb2_pre: APBPrescaler, #[cfg(crs)] pub enable_hsi48: bool, - pub rtc: Option, - pub lse: Option, - pub lsi: bool, + pub ls: super::LsConfig, pub voltage_scale: VoltageScale, } @@ -66,10 +59,8 @@ impl Default for Config { apb2_pre: APBPrescaler::DIV1, #[cfg(crs)] enable_hsi48: false, - rtc: None, - lse: None, - lsi: false, voltage_scale: VoltageScale::RANGE1, + ls: Default::default(), } } } @@ -144,11 +135,7 @@ pub(crate) unsafe fn init(config: Config) { } }; - BackupDomain::configure_ls( - config.rtc.unwrap_or(RtcClockSource::NOCLOCK), - config.lsi, - config.lse.map(|_| Default::default()), - ); + let rtc = config.ls.init(); let wait_states = match (config.voltage_scale, sys_clk.0) { (VoltageScale::RANGE1, ..=16_000_000) => 0, @@ -227,5 +214,6 @@ pub(crate) unsafe fn init(config: Config) { apb2: apb2_freq, apb1_tim: apb1_tim_freq, apb2_tim: apb2_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 686bbd4e..1e5733d3 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -5,16 +5,12 @@ pub use crate::pac::rcc::vals::{ }; use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw}; use crate::pac::{FLASH, RCC}; -use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -51,9 +47,7 @@ pub struct Config { pub pllsai1: Option<(PllMul, PllPreDiv, Option, Option, Option)>, #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] pub hsi48: bool, - pub rtc_mux: RtcClockSource, - pub lse: Option, - pub lsi: bool, + pub ls: super::LsConfig, } impl Default for Config { @@ -67,9 +61,7 @@ impl Default for Config { pllsai1: None, #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] hsi48: false, - rtc_mux: RtcClockSource::LSI, - lsi: true, - lse: None, + ls: Default::default(), } } } @@ -95,7 +87,7 @@ pub(crate) unsafe fn init(config: Config) { while RCC.cfgr().read().sws() != Sw::MSI {} } - BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default())); + let rtc = config.ls.init(); let (sys_clk, sw) = match config.mux { ClockSrc::MSI(range) => { @@ -105,12 +97,8 @@ pub(crate) unsafe fn init(config: Config) { w.set_msirgsel(true); w.set_msion(true); - if config.rtc_mux == RtcClockSource::LSE { - // If LSE is enabled, enable calibration of MSI - w.set_msipllen(true); - } else { - w.set_msipllen(false); - } + // If LSE is enabled, enable calibration of MSI + w.set_msipllen(config.ls.lse.is_some()); }); while !RCC.cr().read().msirdy() {} @@ -285,6 +273,7 @@ pub(crate) unsafe fn init(config: Config) { apb2: apb2_freq, apb1_tim: apb1_tim_freq, apb2_tim: apb2_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs index ac4804d4..1f4e0034 100644 --- a/embassy-stm32/src/rcc/l5.rs +++ b/embassy-stm32/src/rcc/l5.rs @@ -5,16 +5,12 @@ pub use crate::pac::rcc::vals::{ }; use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw}; use crate::pac::{FLASH, PWR, RCC}; -use crate::rcc::bd::RtcClockSource; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -50,9 +46,7 @@ pub struct Config { pub apb2_pre: APBPrescaler, pub pllsai1: Option<(PllMul, PllPreDiv, Option, Option, Option)>, pub hsi48: bool, - pub rtc_mux: RtcClockSource, - pub lse: Option, - pub lsi: bool, + pub ls: super::LsConfig, } impl Default for Config { @@ -65,9 +59,7 @@ impl Default for Config { apb2_pre: APBPrescaler::DIV1, pllsai1: None, hsi48: false, - rtc_mux: RtcClockSource::LSI, - lsi: true, - lse: None, + ls: Default::default(), } } } @@ -93,7 +85,7 @@ pub(crate) unsafe fn init(config: Config) { while RCC.cfgr().read().sws() != Sw::MSI {} } - //BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default())); + let rtc = config.ls.init(); PWR.cr1().modify(|w| w.set_vos(stm32_metapac::pwr::vals::Vos::RANGE0)); let (sys_clk, sw) = match config.mux { @@ -104,12 +96,8 @@ pub(crate) unsafe fn init(config: Config) { w.set_msirgsel(true); w.set_msion(true); - if config.rtc_mux == RtcClockSource::LSE { - // If LSE is enabled, enable calibration of MSI - w.set_msipllen(true); - } else { - w.set_msipllen(false); - } + // If LSE is enabled, enable calibration of MSI + w.set_msipllen(config.ls.lse.is_some()); }); while !RCC.cr().read().msirdy() {} @@ -280,6 +268,7 @@ pub(crate) unsafe fn init(config: Config) { apb2: apb2_freq, apb1_tim: apb1_tim_freq, apb2_tim: apb2_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 3d4de0e6..a9e53d42 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -2,11 +2,11 @@ use core::mem::MaybeUninit; -pub use crate::rcc::bd::RtcClockSource; use crate::time::Hertz; -pub(crate) mod bd; +mod bd; mod mco; +pub use bd::*; pub use mco::*; #[cfg_attr(rcc_f0, path = "f0.rs")] @@ -132,13 +132,7 @@ pub struct Clocks { #[cfg(stm32f334)] pub hrtim: Option, - #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7rm0433, rcc_h7ab))] - /// Set only if the lsi or lse is configured, indicates stop is supported pub rtc: Option, - - #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_h7, rcc_h7rm0433, rcc_h7ab))] - /// Set if the hse is configured, indicates stop is not supported - pub rtc_hse: Option, } #[cfg(feature = "low-power")] @@ -166,14 +160,6 @@ pub(crate) fn clock_refcount_sub() { /// The existence of this value indicates that the clock configuration can no longer be changed static mut CLOCK_FREQS: MaybeUninit = MaybeUninit::uninit(); -#[cfg(stm32wb)] -/// RCC initialization function -pub(crate) unsafe fn init(config: Config) { - set_freqs(compute_clocks(&config)); - - configure_clocks(&config); -} - /// Sets the clock frequencies /// /// Safety: Sets a mutable global. diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index d8fb1730..68a8d3a3 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -7,9 +7,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - pub use crate::pac::pwr::vals::Vos as VoltageScale; #[derive(Copy, Clone)] @@ -111,7 +108,6 @@ impl Into for ClockSrc { } } -#[derive(Copy, Clone)] pub struct Config { pub mux: ClockSrc, pub ahb_pre: AHBPrescaler, @@ -125,6 +121,7 @@ pub struct Config { /// /// See RM0456 § 10.5.4 for a general overview and § 11.4.10 for clock source frequency limits. pub voltage_range: VoltageScale, + pub ls: super::LsConfig, } impl Config { @@ -193,6 +190,7 @@ impl Default for Config { apb3_pre: APBPrescaler::DIV1, hsi48: false, voltage_range: VoltageScale::RANGE3, + ls: Default::default(), } } } @@ -434,6 +432,8 @@ pub(crate) unsafe fn init(config: Config) { } }; + let rtc = config.ls.init(); + set_freqs(Clocks { sys: sys_clk, ahb1: ahb_freq, @@ -444,6 +444,7 @@ pub(crate) unsafe fn init(config: Config) { apb3: apb3_freq, apb1_tim: apb1_tim_freq, apb2_tim: apb2_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index f8eeaa95..181e6bb5 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -2,16 +2,12 @@ pub use crate::pac::rcc::vals::{ Hpre as AHBPrescaler, Hsepre as HsePrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, }; -use crate::rcc::bd::{BackupDomain, RtcClockSource}; -use crate::rcc::Clocks; -use crate::time::{khz, mhz, Hertz}; +use crate::rcc::{set_freqs, Clocks}; +use crate::time::{mhz, Hertz}; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - pub struct Hse { pub prediv: HsePrescaler, @@ -42,11 +38,8 @@ pub struct Pll { /// Clocks configutation pub struct Config { pub hse: Option, - pub lse: Option, - pub lsi: bool, pub sys: Sysclk, pub mux: Option, - pub rtc: Option, pub pll: Option, pub pllsai: Option, @@ -56,6 +49,8 @@ pub struct Config { pub ahb3_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, + + pub ls: super::LsConfig, } pub const WPAN_DEFAULT: Config = Config { @@ -63,14 +58,13 @@ pub const WPAN_DEFAULT: Config = Config { frequency: mhz(32), prediv: HsePrescaler::DIV1, }), - lse: Some(khz(32)), sys: Sysclk::PLL, mux: Some(PllMux { source: PllSource::HSE, prediv: Pllm::DIV2, }), - rtc: Some(RtcClockSource::LSE), - lsi: false, + + ls: super::LsConfig::default_lse(), pll: Some(Pll { mul: Plln::MUL12, @@ -92,13 +86,12 @@ impl Default for Config { fn default() -> Config { Config { hse: None, - lse: None, sys: Sysclk::HSI16, mux: None, pll: None, pllsai: None, - rtc: None, - lsi: false, + + ls: Default::default(), ahb1_pre: AHBPrescaler::DIV1, ahb2_pre: AHBPrescaler::DIV1, @@ -109,7 +102,9 @@ impl Default for Config { } } -pub(crate) fn compute_clocks(config: &Config) -> Clocks { +#[cfg(stm32wb)] +/// RCC initialization function +pub(crate) unsafe fn init(config: Config) { let hse_clk = config.hse.as_ref().map(|hse| hse.frequency / hse.prediv); let mux_clk = config.mux.as_ref().map(|pll_mux| { @@ -160,27 +155,6 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks { } }; - let rtc_clk = match config.rtc { - Some(RtcClockSource::LSI) => Some(LSI_FREQ), - Some(RtcClockSource::LSE) => Some(config.lse.unwrap()), - _ => None, - }; - - Clocks { - sys: sys_clk, - ahb1: ahb1_clk, - ahb2: ahb2_clk, - ahb3: ahb3_clk, - apb1: apb1_clk, - apb2: apb2_clk, - apb1_tim: apb1_tim_clk, - apb2_tim: apb2_tim_clk, - rtc: rtc_clk, - rtc_hse: None, - } -} - -pub(crate) fn configure_clocks(config: &Config) { let rcc = crate::pac::RCC; let needs_hsi = if let Some(pll_mux) = &config.mux { @@ -199,11 +173,7 @@ pub(crate) fn configure_clocks(config: &Config) { rcc.cfgr().modify(|w| w.set_stopwuck(true)); - BackupDomain::configure_ls( - config.rtc.unwrap_or(RtcClockSource::NOCLOCK), - config.lsi, - config.lse.map(|_| Default::default()), - ); + let rtc = config.ls.init(); match &config.hse { Some(hse) => { @@ -263,4 +233,16 @@ pub(crate) fn configure_clocks(config: &Config) { w.set_c2hpre(config.ahb2_pre); w.set_shdhpre(config.ahb3_pre); }); + + set_freqs(Clocks { + sys: sys_clk, + ahb1: ahb1_clk, + ahb2: ahb2_clk, + ahb3: ahb3_clk, + apb1: apb1_clk, + apb2: apb2_clk, + apb1_tim: apb1_tim_clk, + apb2_tim: apb2_tim_clk, + rtc, + }) } diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index d79b3063..ff5669ec 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -7,9 +7,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - pub use crate::pac::pwr::vals::Vos as VoltageScale; pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; @@ -43,13 +40,13 @@ impl Into for ClockSrc { } } -#[derive(Copy, Clone)] pub struct Config { pub mux: ClockSrc, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, pub apb7_pre: APBPrescaler, + pub ls: super::LsConfig, } impl Default for Config { @@ -60,6 +57,7 @@ impl Default for Config { apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, apb7_pre: APBPrescaler::DIV1, + ls: Default::default(), } } } @@ -140,6 +138,8 @@ pub(crate) unsafe fn init(config: Config) { } }; + let rtc = config.ls.init(); + set_freqs(Clocks { sys: sys_clk, ahb1: ahb_freq, @@ -150,5 +150,6 @@ pub(crate) unsafe fn init(config: Config) { apb7: apb7_freq, apb1_tim: apb1_tim_freq, apb2_tim: apb2_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 4c3fe505..366ca136 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -5,16 +5,12 @@ pub use crate::pac::rcc::vals::{ Pllsrc as PllSource, Ppre as APBPrescaler, }; use crate::pac::{FLASH, RCC}; -use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// HSE speed pub const HSE_FREQ: Hertz = Hertz(32_000_000); @@ -33,10 +29,8 @@ pub struct Config { pub shd_ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, - pub rtc_mux: RtcClockSource, - pub lse: Option, - pub lsi: bool, pub adc_clock_source: AdcClockSource, + pub ls: super::LsConfig, } impl Default for Config { @@ -48,10 +42,8 @@ impl Default for Config { shd_ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, - rtc_mux: RtcClockSource::LSI, - lsi: true, - lse: None, adc_clock_source: AdcClockSource::HSI16, + ls: Default::default(), } } } @@ -104,9 +96,6 @@ pub(crate) unsafe fn init(config: Config) { while FLASH.acr().read().latency() != ws {} - // Enables the LSI if configured - BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default())); - match config.mux { ClockSrc::HSI16 => { // Enable HSI16 @@ -129,12 +118,8 @@ pub(crate) unsafe fn init(config: Config) { w.set_msirange(range); w.set_msion(true); - if config.rtc_mux == RtcClockSource::LSE { - // If LSE is enabled, enable calibration of MSI - w.set_msipllen(true); - } else { - w.set_msipllen(false); - } + // If LSE is enabled, enable calibration of MSI + w.set_msipllen(config.ls.lse.is_some()); }); while !RCC.cr().read().msirdy() {} } @@ -156,6 +141,8 @@ pub(crate) unsafe fn init(config: Config) { // TODO: switch voltage range + let rtc = config.ls.init(); + set_freqs(Clocks { sys: sys_clk, ahb1: ahb_freq, @@ -166,6 +153,7 @@ pub(crate) unsafe fn init(config: Config) { apb3: shd_ahb_freq, apb1_tim: apb1_tim_freq, apb2_tim: apb2_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 28dde2eb..cf34d219 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -10,7 +10,6 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; -pub use crate::rcc::RtcClockSource; use crate::time::Hertz; /// refer to AN4759 to compare features of RTC2 and RTC3 @@ -184,7 +183,7 @@ impl Default for RtcCalibrationCyclePeriod { impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { - #[cfg(any(rcc_wle, rcc_wl5, rcc_g4, rcc_g0, rtc_v2l4, rtc_v2wb))] + #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] ::enable(); let mut this = Self { @@ -204,19 +203,8 @@ impl Rtc { } fn frequency() -> Hertz { - #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab))] let freqs = unsafe { crate::rcc::get_freqs() }; - - // Load the clock frequency from the rcc mod, if supported - #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab))] - match freqs.rtc { - Some(hertz) => hertz, - None => freqs.rtc_hse.unwrap(), - } - - // Assume the default value, if not supported - #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab)))] - Hertz(32_768) + freqs.rtc.unwrap() } /// Acquire a [`RtcTimeProvider`] instance. diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs index e3374600..e95ad577 100644 --- a/examples/stm32f4/src/bin/rtc.rs +++ b/examples/stm32f4/src/bin/rtc.rs @@ -5,16 +5,14 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; +use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let mut config = Config::default(); - config.rcc.lsi = true; - config.rcc.rtc = Option::Some(RtcClockSource::LSI); + let config = Config::default(); let p = embassy_stm32::init(config); info!("Hello World!"); diff --git a/examples/stm32h7/src/bin/rtc.rs b/examples/stm32h7/src/bin/rtc.rs index eeb94073..f2a19af8 100644 --- a/examples/stm32h7/src/bin/rtc.rs +++ b/examples/stm32h7/src/bin/rtc.rs @@ -5,20 +5,18 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::Lse; -use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; +use embassy_stm32::rcc::LsConfig; +use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let p = { - let mut config = Config::default(); - config.rcc.lse = Some(Lse::Oscillator); - config.rcc.rtc_mux = Some(RtcClockSource::LSE); - embassy_stm32::init(config) - }; + let mut config = Config::default(); + config.rcc.ls = LsConfig::default_lse(); + + let p = embassy_stm32::init(config); info!("Hello World!"); let now = NaiveDate::from_ymd_opt(2020, 5, 15) diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs index 7e2b8c78..33efc76b 100644 --- a/examples/stm32l4/src/bin/rtc.rs +++ b/examples/stm32l4/src/bin/rtc.rs @@ -5,7 +5,7 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::{self, ClockSrc, PLLSource, PllMul, PllPreDiv, PllRDiv}; +use embassy_stm32::rcc::{ClockSrc, LsConfig, PLLSource, PllMul, PllPreDiv, PllRDiv}; use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::time::Hertz; use embassy_stm32::Config; @@ -23,8 +23,7 @@ async fn main(_spawner: Spawner) { PllMul::MUL20, None, ); - config.rcc.lse = Some(Hertz(32_768)); - config.rcc.rtc_mux = rcc::RtcClockSource::LSE; + config.rcc.ls = LsConfig::default_lse(); embassy_stm32::init(config) }; info!("Hello World!"); diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 8db89be2..7193d1f1 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -32,7 +32,6 @@ use embedded_io::Write as bWrite; use embedded_io_async::Write; use hal::gpio::{Input, Level, Output, Speed}; use hal::i2c::{self, I2c}; -use hal::rcc::{self}; use hal::rng::{self, Rng}; use hal::{bind_interrupts, exti, pac, peripherals}; use heapless::Vec; @@ -86,7 +85,6 @@ async fn main(spawner: Spawner) { None, ); config.rcc.hsi48 = true; // needed for rng - config.rcc.rtc_mux = rcc::RtcClockSource::LSI; let dp = embassy_stm32::init(config); diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs index 6546a4bf..8c789afb 100644 --- a/examples/stm32wl/src/bin/lora_lorawan.rs +++ b/examples/stm32wl/src/bin/lora_lorawan.rs @@ -34,7 +34,6 @@ bind_interrupts!(struct Irqs{ async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; - config.rcc.rtc_mux = embassy_stm32::rcc::RtcClockSource::LSI; let p = embassy_stm32::init(config); pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)); diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs index d5b81970..7c7e8a4e 100644 --- a/examples/stm32wl/src/bin/random.rs +++ b/examples/stm32wl/src/bin/random.rs @@ -16,7 +16,6 @@ bind_interrupts!(struct Irqs{ async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; - config.rcc.rtc_mux = embassy_stm32::rcc::RtcClockSource::LSI; let p = embassy_stm32::init(config); pac::RCC.ccipr().modify(|w| { diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs index b26ddc2f..a6bb2801 100644 --- a/examples/stm32wl/src/bin/rtc.rs +++ b/examples/stm32wl/src/bin/rtc.rs @@ -5,9 +5,8 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::ClockSrc; -use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; -use embassy_stm32::time::Hertz; +use embassy_stm32::rcc::{ClockSrc, LsConfig}; +use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -17,8 +16,7 @@ async fn main(_spawner: Spawner) { let p = { let mut config = Config::default(); config.rcc.mux = ClockSrc::HSE; - config.rcc.lse = Some(Hertz(32_768)); - config.rcc.rtc_mux = RtcClockSource::LSE; + config.rcc.ls = LsConfig::default_lse(); embassy_stm32::init(config) }; info!("Hello World!"); diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index ef835eed..a1481c7c 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -10,19 +10,19 @@ stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac-adc-pin"] # Nucleo "sdmmc" stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma", "dac-adc-pin"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo -stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo +stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "not-gpdma"] # Nucleo stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac-adc-pin"] # Nucleo -stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo -stm32h563zi = ["embassy-stm32/stm32h563zi", "eth"] # Nucleo -stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board +stm32wb55rg = ["embassy-stm32/stm32wb55rg", "chrono", "not-gpdma", "ble", "mac" ] # Nucleo +stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth"] # Nucleo +stm32u585ai = ["embassy-stm32/stm32u585ai", "chrono"] # IoT board stm32l073rz = ["embassy-stm32/stm32l073rz", "not-gpdma"] # Nucleo -stm32l152re = ["embassy-stm32/stm32l152re", "not-gpdma"] # Nucleo -stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "not-gpdma"] # Nucleo -stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "not-gpdma"] # Nucleo +stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"] # Nucleo +stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "chrono", "not-gpdma"] # Nucleo +stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "chrono", "not-gpdma"] # Nucleo stm32l552ze = ["embassy-stm32/stm32l552ze", "not-gpdma"] # Nucleo -stm32f767zi = ["embassy-stm32/stm32f767zi", "not-gpdma", "eth"] # Nucleo -stm32f207zg = ["embassy-stm32/stm32f207zg", "not-gpdma", "eth"] # Nucleo -stm32f303ze = ["embassy-stm32/stm32f303ze", "not-gpdma"] # Nucleo +stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth"] # Nucleo +stm32f207zg = ["embassy-stm32/stm32f207zg", "chrono", "not-gpdma", "eth"] # Nucleo +stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"] # Nucleo stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma"] # Nucleo eth = [] diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 1f0d630c..46fdbfae 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs @@ -10,26 +10,14 @@ use chrono::{NaiveDate, NaiveDateTime}; use common::*; use defmt::assert; use embassy_executor::Spawner; -use embassy_stm32::rcc::RtcClockSource; +use embassy_stm32::rcc::LsConfig; use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_time::{Duration, Timer}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = config(); - - #[cfg(feature = "stm32h755zi")] - { - use embassy_stm32::rcc::Lse; - config.rcc.lse = Some(Lse::Oscillator); - config.rcc.rtc_mux = Some(RtcClockSource::LSE); - } - #[cfg(not(feature = "stm32h755zi"))] - { - use embassy_stm32::time::Hertz; - config.rcc.lse = Some(Hertz(32_768)); - config.rcc.rtc = Some(RtcClockSource::LSE); - } + config.rcc.ls = LsConfig::default_lse(); let p = embassy_stm32::init(config); info!("Hello World!"); diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs index 55c4aa90..929869bc 100644 --- a/tests/stm32/src/bin/stop.rs +++ b/tests/stm32/src/bin/stop.rs @@ -11,9 +11,8 @@ use common::*; use cortex_m_rt::entry; use embassy_executor::Spawner; use embassy_stm32::low_power::{stop_with_rtc, Executor}; -use embassy_stm32::rcc::RtcClockSource; +use embassy_stm32::rcc::LsConfig; use embassy_stm32::rtc::{Rtc, RtcConfig}; -use embassy_stm32::time::Hertz; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use static_cell::make_static; @@ -49,9 +48,7 @@ async fn async_main(spawner: Spawner) { let _ = config(); let mut config = Config::default(); - - config.rcc.lse = Some(Hertz(32_768)); - config.rcc.rtc = Some(RtcClockSource::LSE); + config.rcc.ls = LsConfig::default_lse(); let p = embassy_stm32::init(config); info!("Hello World!");