diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index 90b796a9..1b33fdf8 100644 --- a/embassy-rp/src/rtc/mod.rs +++ b/embassy-rp/src/rtc/mod.rs @@ -41,6 +41,36 @@ impl<'d, T: Instance> Rtc<'d, T> { }); } + /// Set the time from internal format + pub fn restore(&mut self, ymd: rp_pac::rtc::regs::Rtc1, hms: rp_pac::rtc::regs::Rtc0) { + // disable RTC while we configure it + self.inner.regs().ctrl().modify(|w| w.set_rtc_enable(false)); + while self.inner.regs().ctrl().read().rtc_active() { + core::hint::spin_loop(); + } + + self.inner.regs().setup_0().write(|w| { + *w = rp_pac::rtc::regs::Setup0(ymd.0); + }); + self.inner.regs().setup_1().write(|w| { + *w = rp_pac::rtc::regs::Setup1(hms.0); + }); + + // Load the new datetime and re-enable RTC + self.inner.regs().ctrl().write(|w| w.set_load(true)); + self.inner.regs().ctrl().write(|w| w.set_rtc_enable(true)); + while !self.inner.regs().ctrl().read().rtc_active() { + core::hint::spin_loop(); + } + } + + /// Get the time in internal format + pub fn save(&mut self) -> (rp_pac::rtc::regs::Rtc1, rp_pac::rtc::regs::Rtc0) { + let rtc_0: rp_pac::rtc::regs::Rtc0 = self.inner.regs().rtc_0().read(); + let rtc_1 = self.inner.regs().rtc_1().read(); + (rtc_1, rtc_0) + } + /// Checks to see if this Rtc is running pub fn is_running(&self) -> bool { self.inner.regs().ctrl().read().rtc_active() diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index 6300950d..2ddde325 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -4,6 +4,7 @@ use defmt::*; use embassy_executor::Spawner; +use embassy_rp::pac::rtc::regs::{Rtc0, Rtc1}; use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -11,29 +12,41 @@ use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); - info!("Hello World!"); - - let now = DateTime { - year: 2020, - month: 5, - day: 15, - day_of_week: DayOfWeek::Monday, - hour: 10, - minute: 30, - second: 50, - }; + info!("Wait for 20s"); + let mut watchdog = embassy_rp::watchdog::Watchdog::new(p.WATCHDOG); let mut rtc = Rtc::new(p.RTC); - if rtc.set_datetime(now).is_ok() { - // In reality the delay would be much longer - Timer::after(Duration::from_millis(20000)).await; - if let Ok(dt) = rtc.now() { - info!( - "Now: {}-{}-{} {}:{}:{}", - dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, - ); - } + let rtc0 = Rtc0(watchdog.get_scratch0()); + let rtc1 = Rtc1(watchdog.get_scratch1()); + if rtc1.year() >= 2020 { + rtc.restore(rtc1, rtc0); + } else { + let now = DateTime { + year: 2020, + month: 5, + day: 15, + day_of_week: DayOfWeek::Monday, + hour: 10, + minute: 30, + second: 50, + }; + rtc.set_datetime(now).unwrap(); } - info!("Done."); + + Timer::after(Duration::from_millis(20000)).await; + + if let Ok(dt) = rtc.now() { + info!( + "Now: {}-{:02}-{:02} {}:{:02}:{:02}", + dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, + ); + let (rtc1, rtc0) = rtc.save(); + watchdog.set_scratch0(rtc0.0); + watchdog.set_scratch1(rtc1.0); + } + + info!("Reboot."); + Timer::after(Duration::from_millis(200)).await; + cortex_m::peripheral::SCB::sys_reset(); }