diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 1b688eca..5258e4c7 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-172c5ea18824d7cd38decb210e4af441fa3816cb" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0f06b4c95bd9e185e4aa5f2e1d4b76ba84f1594" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -78,7 +78,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-172c5ea18824d7cd38decb210e4af441fa3816cb", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0f06b4c95bd9e185e4aa5f2e1d4b76ba84f1594", default-features = false, features = ["metadata"]} [features] diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index a2040b85..976aa3ee 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs @@ -564,7 +564,7 @@ pub trait DacPin: crate::gpio::Pin + 'static {} foreach_peripheral!( (dac, $inst:ident) => { // H7 uses single bit for both DAC1 and DAC2, this is a hack until a proper fix is implemented - #[cfg(rcc_h7)] + #[cfg(any(rcc_h7, rcc_h7rm0433))] impl crate::rcc::sealed::RccPeripheral for peripherals::$inst { fn frequency() -> crate::time::Hertz { critical_section::with(|_| unsafe { crate::rcc::get_freqs().apb1 }) @@ -590,7 +590,7 @@ foreach_peripheral!( } } - #[cfg(rcc_h7)] + #[cfg(any(rcc_h7, rcc_h7rm0433))] impl crate::rcc::RccPeripheral for peripherals::$inst {} impl crate::dac::sealed::Instance for peripherals::$inst { diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs index cec2ea01..9c784c3a 100644 --- a/embassy-stm32/src/rcc/bd.rs +++ b/embassy-stm32/src/rcc/bd.rs @@ -1,26 +1,36 @@ +#[allow(dead_code)] +#[derive(Clone, Copy)] +pub enum LseCfg { + Oscillator(LseDrive), + Bypass, +} + +impl Default for LseCfg { + fn default() -> Self { + Self::Oscillator(Default::default()) + } +} + #[allow(dead_code)] #[derive(Default, Clone, Copy)] pub enum LseDrive { - #[cfg(any(rtc_v2f7, rtc_v2l4))] Low = 0, MediumLow = 0x01, #[default] MediumHigh = 0x02, - #[cfg(any(rtc_v2f7, rtc_v2l4))] High = 0x03, } -#[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))] +// All families but these have the LSEDRV register +#[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f400, rcc_f410, rcc_l1)))] impl From for crate::pac::rcc::vals::Lsedrv { fn from(value: LseDrive) -> Self { use crate::pac::rcc::vals::Lsedrv; match value { - #[cfg(any(rtc_v2f7, rtc_v2l4))] LseDrive::Low => Lsedrv::LOW, LseDrive::MediumLow => Lsedrv::MEDIUMLOW, LseDrive::MediumHigh => Lsedrv::MEDIUMHIGH, - #[cfg(any(rtc_v2f7, rtc_v2l4))] LseDrive::High => Lsedrv::HIGH, } } @@ -87,14 +97,19 @@ impl BackupDomain { rtc_v3u5 ))] #[allow(dead_code, unused_variables)] - pub fn configure_ls(clock_source: RtcClockSource, lsi: bool, lse: Option) { + pub fn configure_ls(clock_source: RtcClockSource, lsi: bool, lse: Option) { use atomic_polyfill::{compiler_fence, Ordering}; match clock_source { RtcClockSource::LSI => assert!(lsi), - RtcClockSource::LSE => assert!(&lse.is_some()), + RtcClockSource::LSE => assert!(lse.is_some()), _ => {} }; + 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), + None => (false, false, None), + }; if lsi { #[cfg(rtc_v3u5)] @@ -131,10 +146,11 @@ impl BackupDomain { { ok &= reg.rtcen() == (clock_source != RtcClockSource::NOCLOCK); } - ok &= reg.lseon() == lse.is_some(); - #[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))] - if let Some(lse_drive) = lse { - ok &= reg.lsedrv() == lse_drive.into(); + ok &= reg.lseon() == lse_en; + ok &= reg.lsebyp() == lse_byp; + #[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 { + ok &= reg.lsedrv() == lse_drv.into(); } // if configuration is OK, we're done. @@ -153,10 +169,13 @@ impl BackupDomain { Self::modify(|w| w.set_bdrst(false)); } - if let Some(lse_drive) = lse { + if lse_en { Self::modify(|w| { - #[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))] - w.set_lsedrv(lse_drive.into()); + #[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()); + } + w.set_lsebyp(lse_byp); w.set_lseon(true); }); diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index edc5ff52..5ba958a0 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -540,7 +540,7 @@ pub(crate) unsafe fn init(config: Config) { #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] pllsai: plls.pllsaiclk.map(Hertz), - rtc: rtc, + rtc, rtc_hse: None, }); } diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 43e8db22..5f9cc1c8 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -9,6 +9,8 @@ pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; pub use crate::pac::rcc::vals::Ckpersel as PerClockSource; use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre}; 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; @@ -46,9 +48,9 @@ pub enum VoltageScale { pub enum HseMode { /// crystal/ceramic oscillator (HSEBYP=0) Oscillator, - /// external analog clock (low swing) (HSEBYP=1, HSEEXT=0) + /// external analog clock (low swing) (HSEBYP=1, HSEEXT=0) Bypass, - /// external digital clock (full swing) (HSEBYP=1, HSEEXT=1) + /// external digital clock (full swing) (HSEBYP=1, HSEEXT=1) #[cfg(any(rcc_h5, rcc_h50))] BypassDigital, } @@ -61,6 +63,15 @@ pub struct Hse { pub mode: HseMode, } +#[cfg(stm32h7)] +#[derive(Clone, Copy, Eq, PartialEq)] +pub enum Lse { + /// 32.768 kHz crystal/ceramic oscillator (LSEBYP=0) + Oscillator, + /// external clock input up to 1MHz (LSEBYP=1) + Bypass(Hertz), +} + #[derive(Clone, Copy, Eq, PartialEq)] pub enum Hsi { /// 64Mhz @@ -157,6 +168,10 @@ impl From for Timpre { pub struct Config { pub hsi: Option, pub hse: Option, + #[cfg(stm32h7)] + pub lse: Option, + #[cfg(stm32h7)] + pub lsi: bool, pub csi: bool, pub hsi48: bool, pub sys: Sysclk, @@ -181,6 +196,8 @@ pub struct Config { pub adc_clock_source: AdcClockSource, pub timer_prescaler: TimerPrescaler, pub voltage_scale: VoltageScale, + #[cfg(stm32h7)] + pub rtc_mux: Option, } impl Default for Config { @@ -188,6 +205,10 @@ impl Default for Config { Self { hsi: Some(Hsi::Mhz64), hse: None, + #[cfg(stm32h7)] + lse: None, + #[cfg(stm32h7)] + lsi: false, csi: false, hsi48: false, sys: Sysclk::HSI, @@ -210,6 +231,8 @@ 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, } } } @@ -448,6 +471,19 @@ 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); + } + #[cfg(stm32h7)] { RCC.d1cfgr().modify(|w| { @@ -512,6 +548,17 @@ 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, @@ -525,7 +572,11 @@ pub(crate) unsafe fn init(config: Config) { apb4, apb1_tim, apb2_tim, - adc: adc, + adc, + #[cfg(stm32h7)] + rtc: rtc_clk, + #[cfg(stm32h7)] + rtc_hse: None, }); } diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 6f1f7458..3a24eca8 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -420,7 +420,7 @@ pub(crate) unsafe fn init(config: Config) { w.set_msirgsel(true); w.set_msion(true); - if let RtcClockSource::LSE = config.rtc_mux { + if config.rtc_mux == RtcClockSource::LSE { // If LSE is enabled, enable calibration of MSI w.set_msipllen(true); } else { diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index ac967383..bf497ca1 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -21,7 +21,7 @@ pub use mco::*; #[cfg_attr(rcc_c0, path = "c0.rs")] #[cfg_attr(rcc_g0, path = "g0.rs")] #[cfg_attr(rcc_g4, path = "g4.rs")] -#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab), path = "h.rs")] +#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")] #[cfg_attr(rcc_l0, path = "l0.rs")] #[cfg_attr(rcc_l1, path = "l1.rs")] #[cfg_attr(rcc_l4, path = "l4.rs")] @@ -57,9 +57,9 @@ pub struct Clocks { pub apb2: Hertz, #[cfg(not(any(rcc_c0, rcc_g0)))] pub apb2_tim: Hertz, - #[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_u5))] + #[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_u5))] pub apb3: Hertz, - #[cfg(any(rcc_h7, rcc_h7ab))] + #[cfg(any(rcc_h7, rcc_h7rm0433, rcc_h7ab))] pub apb4: Hertz, #[cfg(any(rcc_wba))] pub apb7: Hertz, @@ -67,16 +67,44 @@ pub struct Clocks { // AHB pub ahb1: Hertz, #[cfg(any( - rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb, - rcc_wba, rcc_wl5, rcc_wle + rcc_l4, + rcc_l5, + rcc_f2, + rcc_f4, + rcc_f410, + rcc_f7, + rcc_h5, + rcc_h50, + rcc_h7, + rcc_h7rm0433, + rcc_h7ab, + rcc_g4, + rcc_u5, + rcc_wb, + rcc_wba, + rcc_wl5, + rcc_wle ))] pub ahb2: Hertz, #[cfg(any( - rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_u5, rcc_wb, rcc_wl5, + rcc_l4, + rcc_l5, + rcc_f2, + rcc_f4, + rcc_f410, + rcc_f7, + rcc_h5, + rcc_h50, + rcc_h7, + rcc_h7rm0433, + rcc_h7ab, + rcc_u5, + rcc_wb, + rcc_wl5, rcc_wle ))] pub ahb3: Hertz, - #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_wba))] + #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_wba))] pub ahb4: Hertz, #[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))] @@ -88,7 +116,18 @@ pub struct Clocks { #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] pub pllsai: Option, - #[cfg(any(rcc_f1, rcc_f100, rcc_f1cl, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_f3, rcc_g4))] + #[cfg(any( + rcc_f1, + rcc_f100, + rcc_f1cl, + rcc_h5, + rcc_h50, + rcc_h7, + rcc_h7rm0433, + rcc_h7ab, + rcc_f3, + rcc_g4 + ))] pub adc: Option, #[cfg(any(rcc_f3, rcc_g4))] @@ -97,11 +136,11 @@ pub struct Clocks { #[cfg(stm32f334)] pub hrtim: Option, - #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_f7))] + #[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))] + #[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, } diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 6643d278..937f5550 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -261,7 +261,7 @@ pub(crate) unsafe fn init(config: Config) { w.set_msirange(range.into()); w.set_msion(true); - if let RtcClockSource::LSE = config.rtc_mux { + if config.rtc_mux == RtcClockSource::LSE { // If LSE is enabled, enable calibration of MSI w.set_msipllen(true); } else { diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 73b78f25..28dde2eb 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -93,21 +93,50 @@ impl RtcTimeProvider { /// /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. pub fn now(&self) -> Result { - let r = RTC::regs(); - let tr = r.tr().read(); - let second = bcd2_to_byte((tr.st(), tr.su())); - let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); - let hour = bcd2_to_byte((tr.ht(), tr.hu())); - // Reading either RTC_SSR or RTC_TR locks the values in the higher-order - // calendar shadow registers until RTC_DR is read. - let dr = r.dr().read(); + // For RM0433 we use BYPSHAD=1 to work around errata ES0392 2.19.1 + #[cfg(rcc_h7rm0433)] + loop { + let r = RTC::regs(); + let ss = r.ssr().read().ss(); + let dr = r.dr().read(); + let tr = r.tr().read(); - let weekday = dr.wdu(); - let day = bcd2_to_byte((dr.dt(), dr.du())); - let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); - let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; + // If an RTCCLK edge occurs during read we may see inconsistent values + // so read ssr again and see if it has changed. (see RM0433 Rev 7 46.3.9) + let ss_after = r.ssr().read().ss(); + if ss == ss_after { + let second = bcd2_to_byte((tr.st(), tr.su())); + let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); + let hour = bcd2_to_byte((tr.ht(), tr.hu())); - self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) + let weekday = dr.wdu(); + let day = bcd2_to_byte((dr.dt(), dr.du())); + let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); + let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; + + return self::datetime::datetime(year, month, day, weekday, hour, minute, second) + .map_err(RtcError::InvalidDateTime); + } + } + + #[cfg(not(rcc_h7rm0433))] + { + let r = RTC::regs(); + let tr = r.tr().read(); + let second = bcd2_to_byte((tr.st(), tr.su())); + let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); + let hour = bcd2_to_byte((tr.ht(), tr.hu())); + // Reading either RTC_SSR or RTC_TR locks the values in the higher-order + // calendar shadow registers until RTC_DR is read. + let dr = r.dr().read(); + + let weekday = dr.wdu(); + let day = bcd2_to_byte((dr.dt(), dr.du())); + let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); + let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; + + self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) + } } } @@ -175,18 +204,18 @@ impl Rtc { } fn frequency() -> Hertz { - #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] + #[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))] + #[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)))] + #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab)))] Hertz(32_768) } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 4974f6ee..eeb23e1f 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -157,6 +157,8 @@ impl super::Rtc { w.set_fmt(stm32_metapac::rtc::vals::Fmt::TWENTY_FOUR_HOUR); w.set_osel(Osel::DISABLED); w.set_pol(Pol::HIGH); + #[cfg(rcc_h7rm0433)] + w.set_bypshad(true); }); rtc.prer().modify(|w| { diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 3a3927a9..7bcdf2b3 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "memory-x", "unstable-pac", "unstable-traits"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "memory-x", "unstable-pac", "unstable-traits", "chrono"] } embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } @@ -32,6 +32,7 @@ micromath = "2.0.0" stm32-fmc = "0.3.0" embedded-storage = "0.3.0" static_cell = { version = "1.1", features = ["nightly"]} +chrono = { version = "^0.4", default-features = false } # cargo build/run [profile.dev] diff --git a/examples/stm32h7/src/bin/rtc.rs b/examples/stm32h7/src/bin/rtc.rs new file mode 100644 index 00000000..eeb94073 --- /dev/null +++ b/examples/stm32h7/src/bin/rtc.rs @@ -0,0 +1,39 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +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::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) + }; + info!("Hello World!"); + + let now = NaiveDate::from_ymd_opt(2020, 5, 15) + .unwrap() + .and_hms_opt(10, 30, 15) + .unwrap(); + + let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); + info!("Got RTC! {:?}", now.timestamp()); + + rtc.set_datetime(now.into()).expect("datetime not set"); + + // In reality the delay would be much longer + Timer::after(Duration::from_millis(20000)).await; + + let then: NaiveDateTime = rtc.now().unwrap().into(); + info!("Got RTC! {:?}", then.timestamp()); +}