From 55a5e9b3a51b537b7de80221d501be423af43303 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Thu, 22 Jun 2023 22:37:24 +0200 Subject: [PATCH 1/6] RP: Add RTC example to rp2040. --- examples/rp/src/bin/rtc.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 examples/rp/src/bin/rtc.rs diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs new file mode 100644 index 000000000..a49c8f627 --- /dev/null +++ b/examples/rp/src/bin/rtc.rs @@ -0,0 +1,33 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::rtc::{DateTime, DayOfWeek, RealTimeClock}; +use embassy_time::{Duration, Timer}; +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, + }; + + let rtc_result = RealTimeClock::new(p.RTC, now); + if let Ok(rtc) = rtc_result { + // In reality the delay would be much longer + Timer::after(Duration::from_millis(20000)).await; + + let _then: DateTime = rtc.now().unwrap(); + } +} From 029b156563e70e00cf0ffdf9d5ec23964e5ecc77 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Mon, 26 Jun 2023 08:48:04 +0200 Subject: [PATCH 2/6] RP: Add scratchN registers to watchdog. Add Clone and Debug to DateTime --- embassy-rp/src/rtc/datetime_no_deps.rs | 1 + embassy-rp/src/watchdog.rs | 96 ++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/embassy-rp/src/rtc/datetime_no_deps.rs b/embassy-rp/src/rtc/datetime_no_deps.rs index 92770e984..ea899c339 100644 --- a/embassy-rp/src/rtc/datetime_no_deps.rs +++ b/embassy-rp/src/rtc/datetime_no_deps.rs @@ -25,6 +25,7 @@ pub enum Error { } /// Structure containing date and time information +#[derive(Clone, Debug)] pub struct DateTime { /// 0..4095 pub year: u16, diff --git a/embassy-rp/src/watchdog.rs b/embassy-rp/src/watchdog.rs index d37795cc9..7b36bb5a8 100644 --- a/embassy-rp/src/watchdog.rs +++ b/embassy-rp/src/watchdog.rs @@ -107,4 +107,100 @@ impl Watchdog { w.set_trigger(true); }) } + + pub fn set_scratch0(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch0().write(|w| { + *w = value; + }) + } + + pub fn get_scratch0(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch0().read() + } + + pub fn set_scratch1(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch1().write(|w| { + *w = value; + }) + } + + pub fn get_scratch1(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch1().read() + } + + pub fn set_scratch2(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch2().write(|w| { + *w = value; + }) + } + + pub fn get_scratch2(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch2().read() + } + + pub fn set_scratch3(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch3().write(|w| { + *w = value; + }) + } + + pub fn get_scratch3(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch3().read() + } + + pub fn set_scratch4(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch4().write(|w| { + *w = value; + }) + } + + pub fn get_scratch4(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch4().read() + } + + pub fn set_scratch5(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch5().write(|w| { + *w = value; + }) + } + + pub fn get_scratch5(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch5().read() + } + + pub fn set_scratch6(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch6().write(|w| { + *w = value; + }) + } + + pub fn get_scratch6(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch6().read() + } + + pub fn set_scratch7(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch7().write(|w| { + *w = value; + }) + } + + pub fn get_scratch7(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch7().read() + } } From a93714327eb85b02c7c4a419f2a76df579258975 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Tue, 11 Jul 2023 18:41:45 +0200 Subject: [PATCH 3/6] RP: Rename Rtc to match STM32 impl. Remove setting RTC in new(). --- embassy-rp/src/rtc/mod.rs | 20 +++++++++----------- examples/rp/src/bin/rtc.rs | 14 ++++++++++---- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index b18f12fc4..90b796a9c 100644 --- a/embassy-rp/src/rtc/mod.rs +++ b/embassy-rp/src/rtc/mod.rs @@ -12,26 +12,24 @@ pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; use crate::clocks::clk_rtc_freq; /// A reference to the real time clock of the system -pub struct RealTimeClock<'d, T: Instance> { +pub struct Rtc<'d, T: Instance> { inner: PeripheralRef<'d, T>, } -impl<'d, T: Instance> RealTimeClock<'d, T> { +impl<'d, T: Instance> Rtc<'d, T> { /// Create a new instance of the real time clock, with the given date as an initial value. /// /// # Errors /// /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. - pub fn new(inner: impl Peripheral

+ 'd, initial_date: DateTime) -> Result { + pub fn new(inner: impl Peripheral

+ 'd) -> Self { into_ref!(inner); // Set the RTC divider inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1)); - let mut result = Self { inner }; - result.set_leap_year_check(true); // should be on by default, make sure this is the case. - result.set_datetime(initial_date)?; - Ok(result) + let result = Self { inner }; + result } /// Enable or disable the leap year check. The rp2040 chip will always add a Feb 29th on every year that is divisable by 4, but this may be incorrect (e.g. on century years). This function allows you to disable this check. @@ -43,7 +41,7 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { }); } - /// Checks to see if this RealTimeClock is running + /// Checks to see if this Rtc is running pub fn is_running(&self) -> bool { self.inner.regs().ctrl().read().rtc_active() } @@ -113,8 +111,8 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { /// # fn main() { } /// # #[cfg(not(feature = "chrono"))] /// # fn main() { - /// # use embassy_rp::rtc::{RealTimeClock, DateTimeFilter}; - /// # let mut real_time_clock: RealTimeClock = unsafe { core::mem::zeroed() }; + /// # use embassy_rp::rtc::{Rtc, DateTimeFilter}; + /// # let mut real_time_clock: Rtc = unsafe { core::mem::zeroed() }; /// let now = real_time_clock.now().unwrap(); /// real_time_clock.schedule_alarm( /// DateTimeFilter::default() @@ -150,7 +148,7 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { } } -/// Errors that can occur on methods on [RealTimeClock] +/// Errors that can occur on methods on [Rtc] #[derive(Clone, Debug, PartialEq, Eq)] pub enum RtcError { /// An invalid DateTime was given or stored on the hardware. diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index a49c8f627..6300950d4 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::rtc::{DateTime, DayOfWeek, RealTimeClock}; +use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -23,11 +23,17 @@ async fn main(_spawner: Spawner) { second: 50, }; - let rtc_result = RealTimeClock::new(p.RTC, now); - if let Ok(rtc) = rtc_result { + 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; - let _then: DateTime = rtc.now().unwrap(); + if let Ok(dt) = rtc.now() { + info!( + "Now: {}-{}-{} {}:{}:{}", + dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, + ); + } } + info!("Done."); } From 466a391b52836f79fafad5780ad2eb0a07d82513 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Wed, 12 Jul 2023 14:13:19 +0200 Subject: [PATCH 4/6] RP: Add save/restore to Rtc. Example use. --- embassy-rp/src/rtc/mod.rs | 30 +++++++++++++++++++++ examples/rp/src/bin/rtc.rs | 55 +++++++++++++++++++++++--------------- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index 90b796a9c..1b33fdf8d 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 6300950d4..2ddde3257 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(); } From 6d402fe3932ac04ff939379e6520322476f683dc Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Wed, 12 Jul 2023 15:16:56 +0200 Subject: [PATCH 5/6] RP: Don't reset RTC in Clock::init. Updated example. --- embassy-rp/src/clocks.rs | 2 ++ examples/rp/src/bin/rtc.rs | 26 +++++++++----------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index ddd61d224..acb21dce5 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -308,6 +308,7 @@ pub(crate) unsafe fn init(config: ClockConfig) { // - QSPI (we're using it to run this code!) // - PLLs (it may be suicide if that's what's clocking us) // - USB, SYSCFG (breaks usb-to-swd on core1) + // - RTC (else there would be no more time...) let mut peris = reset::ALL_PERIPHERALS; peris.set_io_qspi(false); // peris.set_io_bank0(false); // might be suicide if we're clocked from gpin @@ -317,6 +318,7 @@ pub(crate) unsafe fn init(config: ClockConfig) { // TODO investigate if usb should be unreset here peris.set_usbctrl(false); peris.set_syscfg(false); + peris.set_rtc(false); reset::reset(peris); // Disable resus that may be enabled from previous software diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index 2ddde3257..d569f598f 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -4,7 +4,6 @@ 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 _}; @@ -14,22 +13,18 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); info!("Wait for 20s"); - let mut watchdog = embassy_rp::watchdog::Watchdog::new(p.WATCHDOG); let mut rtc = Rtc::new(p.RTC); - let rtc0 = Rtc0(watchdog.get_scratch0()); - let rtc1 = Rtc1(watchdog.get_scratch1()); - if rtc1.year() >= 2020 { - rtc.restore(rtc1, rtc0); - } else { + if !rtc.is_running() { + info!("Start RTC"); let now = DateTime { - year: 2020, - month: 5, - day: 15, - day_of_week: DayOfWeek::Monday, - hour: 10, - minute: 30, - second: 50, + year: 2000, + month: 1, + day: 1, + day_of_week: DayOfWeek::Saturday, + hour: 0, + minute: 0, + second: 0, }; rtc.set_datetime(now).unwrap(); } @@ -41,9 +36,6 @@ async fn main(_spawner: Spawner) { "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."); From ff2daaff679ab79c856164d19b1bd15c7526991f Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Wed, 12 Jul 2023 16:41:35 +0200 Subject: [PATCH 6/6] RP: Watchdog scratch set/get with index: usize. --- embassy-rp/src/watchdog.rs | 116 +++++++++---------------------------- 1 file changed, 26 insertions(+), 90 deletions(-) diff --git a/embassy-rp/src/watchdog.rs b/embassy-rp/src/watchdog.rs index 7b36bb5a8..f1e986ec7 100644 --- a/embassy-rp/src/watchdog.rs +++ b/embassy-rp/src/watchdog.rs @@ -108,99 +108,35 @@ impl Watchdog { }) } - pub fn set_scratch0(&mut self, value: u32) { + /// Store data in scratch register + pub fn set_scratch(&mut self, index: usize, value: u32) { let watchdog = pac::WATCHDOG; - watchdog.scratch0().write(|w| { - *w = value; - }) + match index { + 0 => watchdog.scratch0().write(|w| *w = value), + 1 => watchdog.scratch1().write(|w| *w = value), + 2 => watchdog.scratch2().write(|w| *w = value), + 3 => watchdog.scratch3().write(|w| *w = value), + 4 => watchdog.scratch4().write(|w| *w = value), + 5 => watchdog.scratch5().write(|w| *w = value), + 6 => watchdog.scratch6().write(|w| *w = value), + 7 => watchdog.scratch7().write(|w| *w = value), + _ => panic!("Invalid watchdog scratch index"), + } } - pub fn get_scratch0(&mut self) -> u32 { + /// Read data from scratch register + pub fn get_scratch(&mut self, index: usize) -> u32 { let watchdog = pac::WATCHDOG; - watchdog.scratch0().read() - } - - pub fn set_scratch1(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch1().write(|w| { - *w = value; - }) - } - - pub fn get_scratch1(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch1().read() - } - - pub fn set_scratch2(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch2().write(|w| { - *w = value; - }) - } - - pub fn get_scratch2(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch2().read() - } - - pub fn set_scratch3(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch3().write(|w| { - *w = value; - }) - } - - pub fn get_scratch3(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch3().read() - } - - pub fn set_scratch4(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch4().write(|w| { - *w = value; - }) - } - - pub fn get_scratch4(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch4().read() - } - - pub fn set_scratch5(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch5().write(|w| { - *w = value; - }) - } - - pub fn get_scratch5(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch5().read() - } - - pub fn set_scratch6(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch6().write(|w| { - *w = value; - }) - } - - pub fn get_scratch6(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch6().read() - } - - pub fn set_scratch7(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch7().write(|w| { - *w = value; - }) - } - - pub fn get_scratch7(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch7().read() + match index { + 0 => watchdog.scratch0().read(), + 1 => watchdog.scratch1().read(), + 2 => watchdog.scratch2().read(), + 3 => watchdog.scratch3().read(), + 4 => watchdog.scratch4().read(), + 5 => watchdog.scratch5().read(), + 6 => watchdog.scratch6().read(), + 7 => watchdog.scratch7().read(), + _ => panic!("Invalid watchdog scratch index"), + } } }