diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 150014afe..d0ada97a3 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -58,7 +58,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-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9a61a1f090462df8bd1751f89951f04934fdceb3" } 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-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-9a61a1f090462df8bd1751f89951f04934fdceb3", default-features = false, features = ["metadata"]} [features] default = ["rt"] diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs new file mode 100644 index 000000000..0fc116ed8 --- /dev/null +++ b/embassy-stm32/src/rcc/bd.rs @@ -0,0 +1,151 @@ +#[derive(Copy, Clone, Debug, PartialEq)] +#[repr(u8)] +#[allow(dead_code)] +pub enum RtcClockSource { + /// 00: No clock + NoClock = 0b00, + /// 01: LSE oscillator clock used as RTC clock + LSE = 0b01, + /// 10: LSI oscillator clock used as RTC clock + LSI = 0b10, + /// 11: HSE oscillator clock divided by 32 used as RTC clock + HSE = 0b11, +} + +#[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; + +#[allow(dead_code)] +pub struct BackupDomain {} + +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))] + 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(); + + // TODO: Missing from PAC for l0 and f0? + #[cfg(not(any(rtc_v2f0, rtc_v2l0, rtc_v3u5)))] + { + cr.modify(|w| w.set_dbp(true)); + while !cr.read().dbp() {} + } + + #[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 + } + + #[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 set_rtc_clock_source(clock_source: RtcClockSource) { + let clock_source = clock_source as u8; + #[cfg(any( + all(not(any(rtc_v3, rtc_v3u5)), not(rtc_v2wb)), + all(any(rtc_v3, rtc_v3u5), not(any(rcc_wl5, rcc_wle))) + ))] + let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source); + + #[cfg(not(rtc_v2wb))] + Self::modify(|w| { + // Select RTC source + w.set_rtcsel(clock_source); + }); + } + + #[cfg(any( + rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb + ))] + #[allow(dead_code)] + pub fn enable_rtc() { + let reg = Self::read(); + + #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] + assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); + + if !reg.rtcen() { + #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] + Self::modify(|w| w.set_bdrst(true)); + + Self::modify(|w| { + // Reset + #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + w.set_bdrst(false); + + w.set_rtcen(true); + w.set_rtcsel(reg.rtcsel()); + + // Restore bcdr + #[cfg(any(rtc_v2l4, rtc_v2wb))] + w.set_lscosel(reg.lscosel()); + #[cfg(any(rtc_v2l4, rtc_v2wb))] + w.set_lscoen(reg.lscoen()); + + w.set_lseon(reg.lseon()); + + #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] + w.set_lsedrv(reg.lsedrv()); + w.set_lsebyp(reg.lsebyp()); + }); + } + } + + #[cfg(any(rtc_v3, rtc_v3u5))] + #[allow(dead_code)] + pub fn enable_rtc() { + let reg = Self::read(); + assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); + + if !reg.rtcen() { + Self::modify(|w| w.set_bdrst(true)); + + Self::modify(|w| { + w.set_bdrst(false); + + w.set_rtcen(true); + w.set_rtcsel(reg.rtcsel()); + + // Restore bcdr + w.set_lscosel(reg.lscosel()); + w.set_lscoen(reg.lscoen()); + + w.set_lseon(reg.lseon()); + w.set_lsedrv(reg.lsedrv()); + w.set_lsebyp(reg.lsebyp()); + }); + } + } +} diff --git a/embassy-stm32/src/rcc/common.rs b/embassy-stm32/src/rcc/bus.rs similarity index 100% rename from embassy-stm32/src/rcc/common.rs rename to embassy-stm32/src/rcc/bus.rs diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index 6a9326347..d85790797 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -1,4 +1,4 @@ -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw}; use crate::pac::{FLASH, RCC}; diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs index ec4ed99b8..9d9bc59fd 100644 --- a/embassy-stm32/src/rcc/f2.rs +++ b/embassy-stm32/src/rcc/f2.rs @@ -1,7 +1,7 @@ use core::convert::TryFrom; use core::ops::{Div, Mul}; -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw}; use crate::pac::{FLASH, RCC}; @@ -201,7 +201,7 @@ pub struct PLLClocks { pub pll48_freq: Hertz, } -pub use super::common::VoltageScale; +pub use super::bus::VoltageScale; impl VoltageScale { const fn wait_states(&self, ahb_freq: Hertz) -> Option { diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs index 321270a70..7480c0393 100644 --- a/embassy-stm32/src/rcc/f3.rs +++ b/embassy-stm32/src/rcc/f3.rs @@ -201,9 +201,9 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) { // Calculates the Multiplier and the Divisor to arrive at // the required System clock from PLL source frequency let get_mul_div = |sysclk, pllsrcclk| { - let common_div = gcd(sysclk, pllsrcclk); - let mut multiplier = sysclk / common_div; - let mut divisor = pllsrcclk / common_div; + let bus_div = gcd(sysclk, pllsrcclk); + let mut multiplier = sysclk / bus_div; + let mut divisor = pllsrcclk / bus_div; // Minimum PLL multiplier is two if multiplier == 1 { multiplier *= 2; diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index ee9cb2897..10d3322aa 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -8,8 +8,8 @@ use crate::gpio::sealed::AFType; use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; +use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; -use crate::rtc::{Rtc, RtcClockSource}; use crate::time::Hertz; use crate::{peripherals, Peripheral}; @@ -470,7 +470,7 @@ pub(crate) unsafe fn init(config: Config) { } config.rtc.map(|clock_source| { - Rtc::set_clock_source(clock_source); + BackupDomain::set_rtc_clock_source(clock_source); }); let rtc = match config.rtc { diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index bf2d5199e..7fdbcb00c 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -1,4 +1,4 @@ -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index dff04023e..3b044cd11 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -2,7 +2,7 @@ use stm32_metapac::flash::vals::Latency; use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw}; use stm32_metapac::FLASH; -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::{PWR, RCC}; use crate::rcc::sealed::RccPeripheral; use crate::rcc::{set_freqs, Clocks}; diff --git a/embassy-stm32/src/rcc/h5.rs b/embassy-stm32/src/rcc/h5.rs index 2e72b1931..5741cdf92 100644 --- a/embassy-stm32/src/rcc/h5.rs +++ b/embassy-stm32/src/rcc/h5.rs @@ -26,7 +26,7 @@ const VCO_MAX: u32 = 420_000_000; const VCO_WIDE_MIN: u32 = 128_000_000; const VCO_WIDE_MAX: u32 = 560_000_000; -pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale}; +pub use super::bus::{AHBPrescaler, APBPrescaler, VoltageScale}; pub enum HseMode { /// crystal/ceramic oscillator (HSEBYP=0) diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs index 7fb4fb95b..a6e694618 100644 --- a/embassy-stm32/src/rcc/h7.rs +++ b/embassy-stm32/src/rcc/h7.rs @@ -24,7 +24,7 @@ pub const HSI48_FREQ: Hertz = Hertz(48_000_000); /// LSI speed pub const LSI_FREQ: Hertz = Hertz(32_000); -pub use super::common::VoltageScale; +pub use super::bus::VoltageScale; #[derive(Clone, Copy)] pub enum AdcClockSource { diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs index 46b58ca7c..7f9ab01f1 100644 --- a/embassy-stm32/src/rcc/l0.rs +++ b/embassy-stm32/src/rcc/l0.rs @@ -1,4 +1,4 @@ -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; use crate::pac::RCC; #[cfg(crs)] diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs index bdfc5b87a..ed949ea6f 100644 --- a/embassy-stm32/src/rcc/l1.rs +++ b/embassy-stm32/src/rcc/l1.rs @@ -1,4 +1,4 @@ -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index b34b8caab..c6bccfd26 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -4,13 +4,13 @@ use embassy_hal_internal::into_ref; use stm32_metapac::rcc::regs::Cfgr; use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel}; -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::gpio::sealed::AFType; use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; +use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; -use crate::rtc::{Rtc, RtcClockSource as RCS}; use crate::time::Hertz; use crate::{peripherals, Peripheral}; @@ -254,16 +254,11 @@ impl Default for Config { pllsai1: None, #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] hsi48: false, - rtc_mux: RtcClockSource::LSI32, + rtc_mux: RtcClockSource::LSI, } } } -pub enum RtcClockSource { - LSE32, - LSI32, -} - pub enum McoClock { DIV1, DIV2, @@ -413,7 +408,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.apb1enr1().modify(|w| w.set_pwren(true)); match config.rtc_mux { - RtcClockSource::LSE32 => { + RtcClockSource::LSE => { // 1. Unlock the backup domain PWR.cr1().modify(|w| w.set_dbp(true)); @@ -429,17 +424,18 @@ pub(crate) unsafe fn init(config: Config) { // Wait until LSE is running while !RCC.bdcr().read().lserdy() {} - Rtc::set_clock_source(RCS::LSE); + BackupDomain::set_rtc_clock_source(RtcClockSource::LSE); } - RtcClockSource::LSI32 => { + RtcClockSource::LSI => { // Turn on the internal 32 kHz LSI oscillator RCC.csr().modify(|w| w.set_lsion(true)); // Wait until LSI is running while !RCC.csr().read().lsirdy() {} - Rtc::set_clock_source(RCS::LSI); + BackupDomain::set_rtc_clock_source(RtcClockSource::LSI); } + _ => unreachable!(), } let (sys_clk, sw) = match config.mux { @@ -451,7 +447,7 @@ pub(crate) unsafe fn init(config: Config) { w.set_msirgsel(true); w.set_msion(true); - if let RtcClockSource::LSE32 = config.rtc_mux { + if let RtcClockSource::LSE = config.rtc_mux { // If LSE is enabled, enable calibration of MSI w.set_msipllen(true); } else { diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs index a85e14889..9e4e0fc75 100644 --- a/embassy-stm32/src/rcc/l5.rs +++ b/embassy-stm32/src/rcc/l5.rs @@ -1,6 +1,6 @@ use stm32_metapac::PWR; -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 45a4d880d..9f1b3b663 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -1,9 +1,10 @@ #![macro_use] -pub mod common; - +pub(crate) mod bd; +pub mod bus; use core::mem::MaybeUninit; +pub use crate::rcc::bd::RtcClockSource; use crate::time::Hertz; #[cfg_attr(rcc_f0, path = "f0.rs")] diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index b5feeb0c4..4aca9cd3d 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -1,6 +1,6 @@ use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllsrc, Sw}; -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -11,7 +11,7 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000); /// LSI speed pub const LSI_FREQ: Hertz = Hertz(32_000); -pub use super::common::VoltageScale; +pub use super::bus::VoltageScale; #[derive(Copy, Clone)] pub enum ClockSrc { diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index ae708b37f..6a3eab707 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -1,6 +1,6 @@ -pub use super::common::{AHBPrescaler, APBPrescaler}; +pub use super::bus::{AHBPrescaler, APBPrescaler}; +use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::Clocks; -use crate::rtc::{Rtc, RtcClockSource}; use crate::time::{khz, mhz, Hertz}; /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, @@ -375,5 +375,7 @@ pub(crate) fn configure_clocks(config: &Config) { w.set_shdhpre(config.ahb3_pre.into()); }); - config.rtc.map(|clock_source| Rtc::set_clock_source(clock_source)); + config + .rtc + .map(|clock_source| BackupDomain::set_rtc_clock_source(clock_source)); } diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index f1dd2bd7e..e33690d10 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -1,8 +1,7 @@ -pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale}; -use crate::pac::pwr::vals::Dbp; +pub use super::bus::{AHBPrescaler, APBPrescaler, VoltageScale}; use crate::pac::{FLASH, PWR, RCC}; +use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; -use crate::rtc::{Rtc, RtcClockSource as RCS}; use crate::time::Hertz; /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, @@ -130,16 +129,11 @@ impl Default for Config { apb2_pre: APBPrescaler::NotDivided, enable_lsi: false, enable_rtc_apb: false, - rtc_mux: RtcClockSource::LSI32, + rtc_mux: RtcClockSource::LSI, } } } -pub enum RtcClockSource { - LSE32, - LSI32, -} - #[repr(u8)] pub enum Lsedrv { Low = 0, @@ -215,9 +209,9 @@ pub(crate) unsafe fn init(config: Config) { while FLASH.acr().read().latency() != ws {} match config.rtc_mux { - RtcClockSource::LSE32 => { + RtcClockSource::LSE => { // 1. Unlock the backup domain - PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); + PWR.cr1().modify(|w| w.set_dbp(true)); // 2. Setup the LSE RCC.bdcr().modify(|w| { @@ -231,17 +225,18 @@ pub(crate) unsafe fn init(config: Config) { // Wait until LSE is running while !RCC.bdcr().read().lserdy() {} - Rtc::set_clock_source(RCS::LSE); + BackupDomain::set_rtc_clock_source(RtcClockSource::LSE); } - RtcClockSource::LSI32 => { + RtcClockSource::LSI => { // Turn on the internal 32 kHz LSI oscillator RCC.csr().modify(|w| w.set_lsion(true)); // Wait until LSI is running while !RCC.csr().read().lsirdy() {} - Rtc::set_clock_source(RCS::LSI); + BackupDomain::set_rtc_clock_source(RtcClockSource::LSI); } + _ => unreachable!(), } match config.mux { @@ -266,7 +261,7 @@ pub(crate) unsafe fn init(config: Config) { w.set_msirange(range.into()); w.set_msion(true); - if let RtcClockSource::LSE32 = config.rtc_mux { + if let RtcClockSource::LSE = config.rtc_mux { // If LSE is enabled, enable calibration of MSI w.set_msipllen(true); } else { diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index a9c48d88d..3efe9be5d 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs @@ -89,7 +89,7 @@ pub enum DayOfWeek { #[cfg(feature = "chrono")] impl From for DayOfWeek { fn from(weekday: Weekday) -> Self { - day_of_week_from_u8(weekday.number_from_monday() as u8).unwrap() + day_of_week_from_u8(weekday.num_days_from_monday() as u8).unwrap() } } diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 1f1abb78d..c408b2d61 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -10,6 +10,8 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; +use crate::rcc::bd::BackupDomain; +pub use crate::rcc::RtcClockSource; /// refer to AN4759 to compare features of RTC2 and RTC3 #[cfg_attr(any(rtc_v1), path = "v1.rs")] @@ -107,19 +109,6 @@ pub struct Rtc { stop_time: Mutex>>, } -#[derive(Copy, Clone, Debug, PartialEq)] -#[repr(u8)] -pub enum RtcClockSource { - /// 00: No clock - NoClock = 0b00, - /// 01: LSE oscillator clock used as RTC clock - LSE = 0b01, - /// 10: LSI oscillator clock used as RTC clock - LSI = 0b10, - /// 11: HSE oscillator clock divided by 32 used as RTC clock - HSE = 0b11, -} - #[derive(Copy, Clone, PartialEq)] pub struct RtcConfig { /// Asynchronous prescaler factor @@ -189,7 +178,7 @@ impl Rtc { stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), }; - Self::enable(); + BackupDomain::enable_rtc(); rtc_struct.configure(rtc_config); rtc_struct.rtc_config = rtc_config; diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index bf926f986..1e0ca9b48 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -2,7 +2,7 @@ use stm32_metapac::rtc::vals::{Init, Osel, Pol}; #[cfg(feature = "low-power")] use super::RtcInstant; -use super::{sealed, RtcClockSource, RtcConfig}; +use super::{sealed, RtcConfig}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; @@ -73,22 +73,6 @@ impl WakeupPrescaler { } impl super::Rtc { - fn unlock_registers() { - #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] - let cr = crate::pac::PWR.cr(); - #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - let cr = crate::pac::PWR.cr1(); - - // TODO: Missing from PAC for l0 and f0? - #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] - { - if !cr.read().dbp() { - cr.modify(|w| w.set_dbp(true)); - while !cr.read().dbp() {} - } - } - } - #[cfg(feature = "low-power")] /// start the wakeup alarm and wtih a duration that is as close to but less than /// the requested duration, and record the instant the wakeup alarm was started @@ -155,69 +139,6 @@ impl super::Rtc { }) } - #[allow(dead_code)] - pub(crate) fn set_clock_source(clock_source: RtcClockSource) { - #[cfg(not(rtc_v2wb))] - use stm32_metapac::rcc::vals::Rtcsel; - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - Self::unlock_registers(); - - cr.modify(|w| { - // Select RTC source - #[cfg(not(rtc_v2wb))] - w.set_rtcsel(Rtcsel::from_bits(clock_source as u8)); - #[cfg(rtc_v2wb)] - w.set_rtcsel(clock_source as u8); - }); - } - - pub(super) fn enable() { - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let reg = crate::pac::RCC.bdcr().read(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let reg = crate::pac::RCC.csr().read(); - - #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - - if !reg.rtcen() { - Self::unlock_registers(); - - #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] - crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - cr.modify(|w| { - // Reset - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - w.set_bdrst(false); - - w.set_rtcen(true); - w.set_rtcsel(reg.rtcsel()); - - // Restore bcdr - #[cfg(any(rtc_v2l4, rtc_v2wb))] - w.set_lscosel(reg.lscosel()); - #[cfg(any(rtc_v2l4, rtc_v2wb))] - w.set_lscoen(reg.lscoen()); - - w.set_lseon(reg.lseon()); - - #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } - } - /// Applies the RTC config /// It this changes the RTC clock source the time will be reset pub(super) fn configure(&mut self, rtc_config: RtcConfig) { diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 3297303ee..12952b15a 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -1,74 +1,11 @@ use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; -use super::{sealed, RtcCalibrationCyclePeriod, RtcClockSource, RtcConfig}; +use super::{sealed, RtcCalibrationCyclePeriod, RtcConfig}; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; use crate::rtc::sealed::Instance; impl super::Rtc { - fn unlock_registers() { - // Unlock the backup domain - #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))] - { - if !crate::pac::PWR.cr1().read().dbp() { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(true)); - while !crate::pac::PWR.cr1().read().dbp() {} - } - } - #[cfg(any(rcc_wl5, rcc_wle))] - { - use crate::pac::pwr::vals::Dbp; - - if crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED { - crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); - while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {} - } - } - } - - #[allow(dead_code)] - pub(crate) fn set_clock_source(clock_source: RtcClockSource) { - let clock_source = clock_source as u8; - #[cfg(not(any(rcc_wl5, rcc_wle)))] - let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source); - - Self::unlock_registers(); - - crate::pac::RCC.bdcr().modify(|w| { - // Select RTC source - w.set_rtcsel(clock_source); - }); - } - - pub(super) fn enable() { - let bdcr = crate::pac::RCC.bdcr(); - - let reg = bdcr.read(); - assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); - - if !reg.rtcen() { - Self::unlock_registers(); - - bdcr.modify(|w| w.set_bdrst(true)); - - bdcr.modify(|w| { - // Reset - w.set_bdrst(false); - - w.set_rtcen(true); - w.set_rtcsel(reg.rtcsel()); - - // Restore bcdr - w.set_lscosel(reg.lscosel()); - w.set_lscoen(reg.lscoen()); - - w.set_lseon(reg.lseon()); - w.set_lsedrv(reg.lsedrv()); - w.set_lsebyp(reg.lsebyp()); - }); - } - } - /// Applies the RTC config /// It this changes the RTC clock source the time will be reset pub(super) fn configure(&mut self, rtc_config: RtcConfig) { diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs index 0eca58203..23ff8ac47 100644 --- a/examples/stm32f4/src/bin/rtc.rs +++ b/examples/stm32f4/src/bin/rtc.rs @@ -5,13 +5,17 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rtc::{Rtc, RtcConfig}; +use embassy_stm32::rtc::{Rtc, RtcClockSource, 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 = embassy_stm32::init(Default::default()); + let mut config = Config::default(); + config.rcc.rtc = Option::Some(RtcClockSource::LSI); + let p = embassy_stm32::init(config); + info!("Hello World!"); let now = NaiveDate::from_ymd_opt(2020, 5, 15) @@ -23,8 +27,11 @@ async fn main(_spawner: Spawner) { rtc.set_datetime(now.into()).expect("datetime not set"); - // In reality the delay would be much longer - Timer::after(Duration::from_millis(20000)).await; + loop { + let now: NaiveDateTime = rtc.now().unwrap().into(); - let _then: NaiveDateTime = rtc.now().unwrap().into(); + info!("{}", now.timestamp()); + + Timer::after(Duration::from_millis(1000)).await; + } } diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs index 294ea456c..f3f8aa46f 100644 --- a/examples/stm32l4/src/bin/rtc.rs +++ b/examples/stm32l4/src/bin/rtc.rs @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { PLLMul::Mul20, None, ); - config.rcc.rtc_mux = rcc::RtcClockSource::LSE32; + config.rcc.rtc_mux = rcc::RtcClockSource::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 148c58771..0a677be76 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -84,7 +84,7 @@ async fn main(spawner: Spawner) { None, ); config.rcc.hsi48 = true; // needed for rng - config.rcc.rtc_mux = rcc::RtcClockSource::LSI32; + config.rcc.rtc_mux = rcc::RtcClockSource::LSI; let dp = embassy_stm32::init(config); diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs index fb1bc6e3d..2be6c7b93 100644 --- a/examples/stm32wl/src/bin/rtc.rs +++ b/examples/stm32wl/src/bin/rtc.rs @@ -5,8 +5,8 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::{self, ClockSrc}; -use embassy_stm32::rtc::{Rtc, RtcConfig}; +use embassy_stm32::rcc::ClockSrc; +use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { let p = { let mut config = Config::default(); config.rcc.mux = ClockSrc::HSE32; - config.rcc.rtc_mux = rcc::RtcClockSource::LSE32; + config.rcc.rtc_mux = RtcClockSource::LSE; config.rcc.enable_rtc_apb = true; embassy_stm32::init(config) }; diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 7df415b44..1a64dd387 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs @@ -10,7 +10,8 @@ use chrono::{NaiveDate, NaiveDateTime}; use common::*; use defmt::assert; use embassy_executor::Spawner; -use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; +use embassy_stm32::rcc::RtcClockSource; +use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_time::{Duration, Timer}; #[embassy_executor::main] diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs index 4a49bde9d..0b3f4a300 100644 --- a/tests/stm32/src/bin/stop.rs +++ b/tests/stm32/src/bin/stop.rs @@ -11,7 +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::rtc::{Rtc, RtcClockSource, RtcConfig}; +use embassy_stm32::rcc::RtcClockSource; +use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_time::{Duration, Timer}; use static_cell::make_static;