From e3ab6eff7b23e8fdd1f2d6ea8e049500975e359a Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Tue, 30 Jul 2024 09:56:19 -0700 Subject: [PATCH 01/30] Initial WIP RTC set implementation --- esp-hal/src/rtc_cntl/mod.rs | 49 ++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index 22a99efac97..b4c8b9d1bf7 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -216,7 +216,7 @@ impl<'d> Rtc<'d> { } /// Read the current value of the rtc time registers. - pub fn get_time_raw(&self) -> u64 { + fn get_time_since_boot_raw(&self) -> u64 { #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; #[cfg(any(esp32c6, esp32h2))] @@ -255,15 +255,58 @@ impl<'d> Rtc<'d> { } /// Read the current value of the rtc time registers in microseconds. - pub fn get_time_us(&self) -> u64 { + fn get_time_since_boot_us(&self) -> u64 { self.get_time_raw() * 1_000_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 } /// Read the current value of the rtc time registers in milliseconds. - pub fn get_time_ms(&self) -> u64 { + fn get_time_since_boot_ms(&self) -> u64 { self.get_time_raw() * 1_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 } + fn get_boot_time_us(&self) -> u64 { + let rtc_cntl = unsafe { &*LPWR::ptr() }; + + // Register documentation: https://github.com/espressif/esp-idf/blob/master/components/esp_rom/esp32s3/include/esp32s3/rom/rtc.h + let boot_time_low = rtc_cntl.store2(); + let boot_time_high = rtc_cntl.store3(); + + let boot_time_low = boot_time_low.read().bits() as u64; + let boot_time_high = boot_time_high.read().bits() as u64; + + // https://github.com/espressif/esp-idf/blob/23e4823f17a8349b5e03536ff7653e3e584c9351/components/newlib/port/esp_time_impl.c#L115 + boot_time_low + (boot_time_high << 32) + } + + fn set_boot_time(&self, boot_time_us: u64) { + let rtc_cntl = unsafe { &*LPWR::ptr() }; + + // Register documentation: https://github.com/espressif/esp-idf/blob/master/components/esp_rom/esp32s3/include/esp32s3/rom/rtc.h + let boot_time_low = rtc_cntl.store2(); + let boot_time_high = rtc_cntl.store3(); + + // https://github.com/espressif/esp-idf/blob/23e4823f17a8349b5e03536ff7653e3e584c9351/components/newlib/port/esp_time_impl.c#L102-L103 + boot_time_low.write(|w| unsafe { w.bits((boot_time_us & 0xffffffff) as u32) }); + boot_time_high.write(|w| unsafe { w.bits((boot_time_us >> 32) as u32) }); + } + + pub fn get_time_us(&self) -> u64 { + // current time is boot time + time since boot + self.get_boot_time_us() + self.get_time_since_boot_us() + } + + pub fn set_time(&self, time_us: u64) { + // current time is boot time + time since boot + // so boot time = current time - time since boot + let time_since_boot = self.get_time_since_boot_us(); + if time_us < time_since_boot { + // TODO: handle this better - return a Result? + self.set_boot_time(0) + } else { + self.set_boot_time(time_us - time_since_boot) + } + } + /// Enter deep sleep and wake with the provided `wake_sources`. #[cfg(any(esp32, esp32s3, esp32c3, esp32c6))] pub fn sleep_deep(&mut self, wake_sources: &[&dyn WakeSource]) -> ! { From 461629b8edf4526983403e8a9f93aea9787ab534 Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Mon, 12 Aug 2024 09:29:56 -1000 Subject: [PATCH 02/30] Deprecate get_time_raw and add docs + some cleanup --- esp-hal/src/rtc_cntl/mod.rs | 107 ++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 24 deletions(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index b4c8b9d1bf7..4e10c9216c0 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -181,6 +181,12 @@ pub(crate) enum RtcCalSel { RtcCalInternalOsc = 3, } +#[derive(Debug)] +/// This error indicates that an overflow would've happened if +/// the rtc time was set to the requested value. See [`Rtc::set_time_us`] +/// and [`Rtc::set_time_ms`] for more info. +pub struct RtcSetOverflow; + /// Low-power Management pub struct Rtc<'d> { _inner: PeripheralRef<'d, crate::peripherals::LPWR>, @@ -215,8 +221,17 @@ impl<'d> Rtc<'d> { RtcClock::estimate_xtal_frequency() } - /// Read the current value of the rtc time registers. - fn get_time_since_boot_raw(&self) -> u64 { + #[deprecated = "This function does not take into account the boot time registers, and therefore will not react to using `set_time_us` and `set_time_ms`."] + /// Read the current raw value of the rtc time registers. + /// + /// **This function does not take into account the boot time registers, and therefore + /// will not react to using [`set_time_us`][Self::set_time_us] and [`set_time_ms`][Self::set_time_ms].** + pub fn get_time_raw(&self) -> u64 { + self.get_rtc_time_raw() + } + + /// Read the current raw value of the rtc time registers. + fn get_rtc_time_raw(&self) -> u64 { #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; #[cfg(any(esp32c6, esp32h2))] @@ -255,58 +270,102 @@ impl<'d> Rtc<'d> { } /// Read the current value of the rtc time registers in microseconds. - fn get_time_since_boot_us(&self) -> u64 { - self.get_time_raw() * 1_000_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 + fn get_rtc_time_us(&self) -> u64 { + self.get_rtc_time_raw() * 1_000_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 } /// Read the current value of the rtc time registers in milliseconds. - fn get_time_since_boot_ms(&self) -> u64 { - self.get_time_raw() * 1_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 + fn get_rtc_time_ms(&self) -> u64 { + self.get_rtc_time_raw() * 1_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 } + /// Read the current value of the boot time registers in microseconds. fn get_boot_time_us(&self) -> u64 { + #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; + #[cfg(any(esp32c6, esp32h2))] + let rtc_cntl = unsafe { &*LP_TIMER::ptr() }; // Register documentation: https://github.com/espressif/esp-idf/blob/master/components/esp_rom/esp32s3/include/esp32s3/rom/rtc.h - let boot_time_low = rtc_cntl.store2(); - let boot_time_high = rtc_cntl.store3(); + // STORE2 and STORE3 are used on all current chips: esp32, esp32p4, esp32h2, esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32s2, esp32s3 + // See https://github.com/search?q=repo%3Aespressif%2Fesp-idf+RTC_BOOT_TIME_LOW_REG+RTC_BOOT_TIME_HIGH_REG+path%3A**%2Frtc.h&type=code + let (l, h) = (rtc_cntl.store2(), rtc_cntl.store3()); - let boot_time_low = boot_time_low.read().bits() as u64; - let boot_time_high = boot_time_high.read().bits() as u64; + let l = l.read().bits() as u64; + let h = h.read().bits() as u64; // https://github.com/espressif/esp-idf/blob/23e4823f17a8349b5e03536ff7653e3e584c9351/components/newlib/port/esp_time_impl.c#L115 - boot_time_low + (boot_time_high << 32) + l + (h << 32) + } + + /// Read the current value of the rtc time registers in milliseconds. + fn get_boot_time_ms(&self) -> u64 { + self.get_boot_time_us() / 1_000 } - fn set_boot_time(&self, boot_time_us: u64) { + /// Set the current value of the boot time registers in microseconds. + fn set_boot_time_us(&self, boot_time_us: u64) { + #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; + #[cfg(any(esp32c6, esp32h2))] + let rtc_cntl = unsafe { &*LP_TIMER::ptr() }; // Register documentation: https://github.com/espressif/esp-idf/blob/master/components/esp_rom/esp32s3/include/esp32s3/rom/rtc.h - let boot_time_low = rtc_cntl.store2(); - let boot_time_high = rtc_cntl.store3(); + // STORE2 and STORE3 are used on all current chips: esp32, esp32p4, esp32h2, esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32s2, esp32s3 + // See https://github.com/search?q=repo%3Aespressif%2Fesp-idf+RTC_BOOT_TIME_LOW_REG+RTC_BOOT_TIME_HIGH_REG+path%3A**%2Frtc.h&type=code + let (l, h) = (rtc_cntl.store2(), rtc_cntl.store3()); // https://github.com/espressif/esp-idf/blob/23e4823f17a8349b5e03536ff7653e3e584c9351/components/newlib/port/esp_time_impl.c#L102-L103 - boot_time_low.write(|w| unsafe { w.bits((boot_time_us & 0xffffffff) as u32) }); - boot_time_high.write(|w| unsafe { w.bits((boot_time_us >> 32) as u32) }); + l.write(|w| unsafe { w.bits((boot_time_us & 0xffffffff) as u32) }); + h.write(|w| unsafe { w.bits((boot_time_us >> 32) as u32) }); } + /// Read the current value of the time registers in microseconds. pub fn get_time_us(&self) -> u64 { // current time is boot time + time since boot - self.get_boot_time_us() + self.get_time_since_boot_us() + self.get_boot_time_us() + self.get_rtc_time_us() } - pub fn set_time(&self, time_us: u64) { + /// Read the current value of the time registers in milliseconds. + pub fn get_time_ms(&self) -> u64 { // current time is boot time + time since boot - // so boot time = current time - time since boot - let time_since_boot = self.get_time_since_boot_us(); - if time_us < time_since_boot { - // TODO: handle this better - return a Result? - self.set_boot_time(0) + self.get_boot_time_ms() + self.get_rtc_time_ms() + } + + /// Set the current value of the time registers in microseconds. + /// + /// This function will fail if `time_us` is less than the time + /// since boot. This happens because when setting the time, we + /// have to set the boot time which is calculated by subtracting + /// `time_us` from the time since boot. However, since time is + /// stored with unsigned integers, if `time_us` is less than + /// the time since boot, the subtraction result will be negative + /// and thus an overflow will occur. + pub fn set_time_us(&self, time_us: u64) -> Result<(), RtcSetOverflow> { + // current time is boot time + time since boot (rtc time) + // so boot time = current time - time since boot (rtc time) + let rtc_time_us = self.get_rtc_time_us(); + if time_us < rtc_time_us { + // if we subtract rtc_time_us from time_us, it will be negative and an overflow will happen + Err(RtcSetOverflow) } else { - self.set_boot_time(time_us - time_since_boot) + Ok(self.set_boot_time_us(time_us - rtc_time_us)) } } + /// Set the current value of the time registers in milliseconds. + /// + /// This function will fail if `time_ms` is less than the time + /// since boot. This happens because when setting the time, we + /// have to set the boot time which is calculated by subtracting + /// `time_ms` from the time since boot. However, since time is + /// stored with unsigned integers, if `time_ms` is less than + /// the time since boot, the subtraction result will be negative + /// and thus an overflow will occur. + pub fn set_time_ms(&self, time_ms: u64) -> Result<(), RtcSetOverflow> { + self.set_time_us(time_ms * 1_000) + } + /// Enter deep sleep and wake with the provided `wake_sources`. #[cfg(any(esp32, esp32s3, esp32c3, esp32c6))] pub fn sleep_deep(&mut self, wake_sources: &[&dyn WakeSource]) -> ! { From 48075f2f1cacf4a448cf3d47e523a0cdcb3736fd Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Mon, 12 Aug 2024 09:35:24 -1000 Subject: [PATCH 03/30] Update rtc time example --- examples/src/bin/rtc_time.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/src/bin/rtc_time.rs b/examples/src/bin/rtc_time.rs index c4e9b876b06..9b0943c33c1 100644 --- a/examples/src/bin/rtc_time.rs +++ b/examples/src/bin/rtc_time.rs @@ -27,5 +27,13 @@ fn main() -> ! { loop { esp_println::println!("rtc time in milliseconds is {}", rtc.get_time_ms()); delay.delay_millis(1000); + // Set the time to 1 second past the current time after 5 seconds have passed + if (rtc.get_time_ms() > 5_000) { + let new_time = rtc.get_time_ms() + 1_000; + esp_println::println!("setting rtc time to {new_time} (milliseconds)"); + if rtc.set_time_ms(new_time).is_err() { + esp_println::println!("failed to set rtc time due to overflow"); + } + } } } From 66759b23b732198d2778c3ded4fad20612c9a5b8 Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Mon, 12 Aug 2024 09:39:35 -1000 Subject: [PATCH 04/30] Format --- esp-hal/src/rtc_cntl/mod.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index 4e10c9216c0..fe1483f5b1f 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -224,8 +224,9 @@ impl<'d> Rtc<'d> { #[deprecated = "This function does not take into account the boot time registers, and therefore will not react to using `set_time_us` and `set_time_ms`."] /// Read the current raw value of the rtc time registers. /// - /// **This function does not take into account the boot time registers, and therefore - /// will not react to using [`set_time_us`][Self::set_time_us] and [`set_time_ms`][Self::set_time_ms].** + /// **This function does not take into account the boot time registers, and + /// therefore will not react to using [`set_time_us`][Self::set_time_us] + /// and [`set_time_ms`][Self::set_time_ms].** pub fn get_time_raw(&self) -> u64 { self.get_rtc_time_raw() } @@ -287,7 +288,8 @@ impl<'d> Rtc<'d> { let rtc_cntl = unsafe { &*LP_TIMER::ptr() }; // Register documentation: https://github.com/espressif/esp-idf/blob/master/components/esp_rom/esp32s3/include/esp32s3/rom/rtc.h - // STORE2 and STORE3 are used on all current chips: esp32, esp32p4, esp32h2, esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32s2, esp32s3 + // STORE2 and STORE3 are used on all current chips: esp32, esp32p4, esp32h2, + // esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32s2, esp32s3 // See https://github.com/search?q=repo%3Aespressif%2Fesp-idf+RTC_BOOT_TIME_LOW_REG+RTC_BOOT_TIME_HIGH_REG+path%3A**%2Frtc.h&type=code let (l, h) = (rtc_cntl.store2(), rtc_cntl.store3()); @@ -311,7 +313,8 @@ impl<'d> Rtc<'d> { let rtc_cntl = unsafe { &*LP_TIMER::ptr() }; // Register documentation: https://github.com/espressif/esp-idf/blob/master/components/esp_rom/esp32s3/include/esp32s3/rom/rtc.h - // STORE2 and STORE3 are used on all current chips: esp32, esp32p4, esp32h2, esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32s2, esp32s3 + // STORE2 and STORE3 are used on all current chips: esp32, esp32p4, esp32h2, + // esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32s2, esp32s3 // See https://github.com/search?q=repo%3Aespressif%2Fesp-idf+RTC_BOOT_TIME_LOW_REG+RTC_BOOT_TIME_HIGH_REG+path%3A**%2Frtc.h&type=code let (l, h) = (rtc_cntl.store2(), rtc_cntl.store3()); @@ -346,7 +349,8 @@ impl<'d> Rtc<'d> { // so boot time = current time - time since boot (rtc time) let rtc_time_us = self.get_rtc_time_us(); if time_us < rtc_time_us { - // if we subtract rtc_time_us from time_us, it will be negative and an overflow will happen + // if we subtract rtc_time_us from time_us, it will be negative and an overflow + // will happen Err(RtcSetOverflow) } else { Ok(self.set_boot_time_us(time_us - rtc_time_us)) From 1e199336c7a473d4fdf3bb9e18fe49bfb94dbe29 Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Mon, 12 Aug 2024 09:43:49 -1000 Subject: [PATCH 05/30] Update changelog --- esp-hal/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 65fd89f3abe..ba0985fdeec 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -10,14 +10,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added new `Io::new_no_bind_interrupt` constructor (#1861) +- Added `Rtc::set_time_us` and `Rtc::set_time_ms` to allow setting RTC time (#1883) ### Changed - Peripheral driver constructors don't take `InterruptHandler`s anymore. Use `set_interrupt_handler` to explicitly set the interrupt handler now. (#1819) - Use the peripheral ref pattern for `OneShotTimer` and `PeriodicTimer` (#1855) - - Allow DMA to/from psram for esp32s3 (#1827) - DMA buffers now don't require a static lifetime. Make sure to never `mem::forget` an in-progress DMA transfer (consider using `#[deny(clippy::mem_forget)]`) (#1837) +- Deprecated `Rtc::get_time_raw` since it doesn't respect boot time and therefore won't react to setting RTC time (#1883) ### Fixed From c58310abf23f0db66c6688004f8ee1cacc21ee25 Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Mon, 12 Aug 2024 10:15:33 -1000 Subject: [PATCH 06/30] Add some comments linking the PR --- esp-hal/src/rtc_cntl/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index fe1483f5b1f..a72a6d56285 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -282,6 +282,7 @@ impl<'d> Rtc<'d> { /// Read the current value of the boot time registers in microseconds. fn get_boot_time_us(&self) -> u64 { + // For more info on about how RTC setting works, see https://github.com/esp-rs/esp-hal/pull/1883 #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; #[cfg(any(esp32c6, esp32h2))] @@ -307,6 +308,7 @@ impl<'d> Rtc<'d> { /// Set the current value of the boot time registers in microseconds. fn set_boot_time_us(&self, boot_time_us: u64) { + // For more info on about how RTC setting works, see https://github.com/esp-rs/esp-hal/pull/1883 #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; #[cfg(any(esp32c6, esp32h2))] From aa6b922e283606d6440cc48ad31cc8f67a244ced Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:01:52 -1000 Subject: [PATCH 07/30] Small compilation fixes --- esp-hal/src/rtc_cntl/mod.rs | 3 ++- esp-hal/src/rtc_cntl/sleep/esp32.rs | 2 +- esp-hal/src/rtc_cntl/sleep/esp32c3.rs | 2 +- esp-hal/src/rtc_cntl/sleep/esp32c6.rs | 2 +- esp-hal/src/rtc_cntl/sleep/esp32s3.rs | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index a72a6d56285..05e1273f06c 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -355,7 +355,8 @@ impl<'d> Rtc<'d> { // will happen Err(RtcSetOverflow) } else { - Ok(self.set_boot_time_us(time_us - rtc_time_us)) + self.set_boot_time_us(time_us - rtc_time_us); + Ok(()) } } diff --git a/esp-hal/src/rtc_cntl/sleep/esp32.rs b/esp-hal/src/rtc_cntl/sleep/esp32.rs index cfc70e67e2c..cb6348e3920 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32.rs @@ -54,7 +54,7 @@ impl WakeSource for TimerWakeupSource { let clock_hz = clock_freq.frequency().to_Hz() as u64; let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64; // "alarm" time in slow rtc ticks - let now = rtc.get_time_raw(); + let now = rtc.get_rtc_time_raw(); let time_in_ticks = now + ticks; unsafe { rtc_cntl diff --git a/esp-hal/src/rtc_cntl/sleep/esp32c3.rs b/esp-hal/src/rtc_cntl/sleep/esp32c3.rs index f8fdcf3fac1..1506efdf477 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32c3.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32c3.rs @@ -99,7 +99,7 @@ impl WakeSource for TimerWakeupSource { let clock_hz = clock_freq.frequency().to_Hz() as u64; let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64; // "alarm" time in slow rtc ticks - let now = rtc.get_time_raw(); + let now = rtc.get_rtc_time_raw(); let time_in_ticks = now + ticks; unsafe { rtc_cntl diff --git a/esp-hal/src/rtc_cntl/sleep/esp32c6.rs b/esp-hal/src/rtc_cntl/sleep/esp32c6.rs index 3336bc34372..c3b6bae02d6 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32c6.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32c6.rs @@ -46,7 +46,7 @@ impl WakeSource for TimerWakeupSource { let clock_hz = clock_freq.frequency().to_Hz() as u64; let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64; // "alarm" time in slow rtc ticks - let now = rtc.get_time_raw(); + let now = rtc.get_rtc_time_raw(); let time_in_ticks = now + ticks; unsafe { lp_timer.tar0_high().write(|w| { diff --git a/esp-hal/src/rtc_cntl/sleep/esp32s3.rs b/esp-hal/src/rtc_cntl/sleep/esp32s3.rs index 34011d6cf93..2d44fbfc790 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32s3.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32s3.rs @@ -94,7 +94,7 @@ impl WakeSource for TimerWakeupSource { let clock_hz = clock_freq.frequency().to_Hz() as u64; let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64; // "alarm" time in slow rtc ticks - let now = rtc.get_time_raw(); + let now = rtc.get_rtc_time_raw(); let time_in_ticks = now + ticks; unsafe { rtc_cntl From aef6d4ba8c0e443c63a57d17487ee9c8faa3c428 Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:00:15 -1000 Subject: [PATCH 08/30] C6 and H2 fixes --- esp-hal/src/rtc_cntl/mod.rs | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index 05e1273f06c..91c9cb8a3ae 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -81,7 +81,7 @@ use crate::efuse::Efuse; #[cfg(not(any(esp32c6, esp32h2)))] use crate::peripherals::{LPWR, TIMG0}; #[cfg(any(esp32c6, esp32h2))] -use crate::peripherals::{LP_TIMER, LP_WDT}; +use crate::peripherals::{LP_AON, LP_TIMER, LP_WDT}; #[cfg(any(esp32, esp32s3, esp32c3, esp32c6))] use crate::rtc_cntl::sleep::{RtcSleepConfig, WakeSource, WakeTriggers}; use crate::{ @@ -282,16 +282,26 @@ impl<'d> Rtc<'d> { /// Read the current value of the boot time registers in microseconds. fn get_boot_time_us(&self) -> u64 { - // For more info on about how RTC setting works, see https://github.com/esp-rs/esp-hal/pull/1883 + // For more info on about how RTC setting works and what it has to do with boot time, see https://github.com/esp-rs/esp-hal/pull/1883 + + // In terms of registers, STORE2 and STORE3 are used on all current chips + // (esp32, esp32p4, esp32h2, esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, + // esp32s2, esp32s3) + + // In terms of peripherals: + + // - LPWR is used on the following chips: esp32, esp32p4, esp32c2, esp32c3, + // esp32s2, esp32s3 + + // - LP_AON is used on the following chips: esp32c5, esp32c6, esp32c61, esp32h2 + + // For registers and peripherals used in esp-idf, see https://github.com/search?q=repo%3Aespressif%2Fesp-idf+RTC_BOOT_TIME_LOW_REG+RTC_BOOT_TIME_HIGH_REG+path%3A**%2Frtc.h&type=code + #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; #[cfg(any(esp32c6, esp32h2))] - let rtc_cntl = unsafe { &*LP_TIMER::ptr() }; + let rtc_cntl = unsafe { &*LP_AON::ptr() }; - // Register documentation: https://github.com/espressif/esp-idf/blob/master/components/esp_rom/esp32s3/include/esp32s3/rom/rtc.h - // STORE2 and STORE3 are used on all current chips: esp32, esp32p4, esp32h2, - // esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32s2, esp32s3 - // See https://github.com/search?q=repo%3Aespressif%2Fesp-idf+RTC_BOOT_TIME_LOW_REG+RTC_BOOT_TIME_HIGH_REG+path%3A**%2Frtc.h&type=code let (l, h) = (rtc_cntl.store2(), rtc_cntl.store3()); let l = l.read().bits() as u64; @@ -308,16 +318,14 @@ impl<'d> Rtc<'d> { /// Set the current value of the boot time registers in microseconds. fn set_boot_time_us(&self, boot_time_us: u64) { - // For more info on about how RTC setting works, see https://github.com/esp-rs/esp-hal/pull/1883 + // Please see `get_boot_time_ms` for documentation on registers and peripherals + // used for certain SOCs. + #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; #[cfg(any(esp32c6, esp32h2))] - let rtc_cntl = unsafe { &*LP_TIMER::ptr() }; + let rtc_cntl = unsafe { &*LP_AON::ptr() }; - // Register documentation: https://github.com/espressif/esp-idf/blob/master/components/esp_rom/esp32s3/include/esp32s3/rom/rtc.h - // STORE2 and STORE3 are used on all current chips: esp32, esp32p4, esp32h2, - // esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32s2, esp32s3 - // See https://github.com/search?q=repo%3Aespressif%2Fesp-idf+RTC_BOOT_TIME_LOW_REG+RTC_BOOT_TIME_HIGH_REG+path%3A**%2Frtc.h&type=code let (l, h) = (rtc_cntl.store2(), rtc_cntl.store3()); // https://github.com/espressif/esp-idf/blob/23e4823f17a8349b5e03536ff7653e3e584c9351/components/newlib/port/esp_time_impl.c#L102-L103 From 9505691308a319e69d8a5457afde549d0a2681e5 Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:01:47 -1000 Subject: [PATCH 09/30] Remove parantheses from if statement lol --- examples/src/bin/rtc_time.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/src/bin/rtc_time.rs b/examples/src/bin/rtc_time.rs index 9b0943c33c1..65e3f08161a 100644 --- a/examples/src/bin/rtc_time.rs +++ b/examples/src/bin/rtc_time.rs @@ -28,7 +28,7 @@ fn main() -> ! { esp_println::println!("rtc time in milliseconds is {}", rtc.get_time_ms()); delay.delay_millis(1000); // Set the time to 1 second past the current time after 5 seconds have passed - if (rtc.get_time_ms() > 5_000) { + if rtc.get_time_ms() > 5_000 { let new_time = rtc.get_time_ms() + 1_000; esp_println::println!("setting rtc time to {new_time} (milliseconds)"); if rtc.set_time_ms(new_time).is_err() { From bcd8629b227a28c69dc030aad18597113d1a1f9c Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Tue, 13 Aug 2024 17:23:26 -0700 Subject: [PATCH 10/30] Remove accidental changelog change --- esp-hal/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index a1142bd9962..7eb9b34dbe5 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -23,7 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - DMA: don't require `Sealed` to implement `ReadBuffer` and `WriteBuffer` (#1921) - Allow DMA to/from psram for esp32s3 (#1827) - DMA buffers now don't require a static lifetime. Make sure to never `mem::forget` an in-progress DMA transfer (consider using `#[deny(clippy::mem_forget)]`) (#1837) -- Peripherals (where possible) are now explicitly reset and enabled in their constructors (#1893)) (#1837) +- Peripherals (where possible) are now explicitly reset and enabled in their constructors (#1893) - Deprecated `Rtc::get_time_raw` since it doesn't respect boot time and therefore won't react to setting RTC time (#1883) ### Fixed From 974f683dbcab5e22927dddf6093f33951e8f0589 Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Tue, 13 Aug 2024 16:28:09 -1000 Subject: [PATCH 11/30] Implement boot time wrapping to avoid overflows --- esp-hal/src/rtc_cntl/mod.rs | 58 +++++++++++++++--------------------- examples/src/bin/rtc_time.rs | 13 ++++---- 2 files changed, 29 insertions(+), 42 deletions(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index df9aa7c248a..92cb64aab86 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -183,12 +183,6 @@ pub(crate) enum RtcCalSel { RtcCalInternalOsc = 3, } -#[derive(Debug)] -/// This error indicates that an overflow would've happened if -/// the rtc time was set to the requested value. See [`Rtc::set_time_us`] -/// and [`Rtc::set_time_ms`] for more info. -pub struct RtcSetOverflow; - /// Low-power Management pub struct Rtc<'d> { _inner: PeripheralRef<'d, crate::peripherals::LPWR>, @@ -338,48 +332,44 @@ impl<'d> Rtc<'d> { /// Read the current value of the time registers in microseconds. pub fn get_time_us(&self) -> u64 { // current time is boot time + time since boot - self.get_boot_time_us() + self.get_rtc_time_us() + let rtc_time_us = self.get_rtc_time_us(); + let boot_time_us = self.get_boot_time_us(); + let wrapped_boot_time_us = u64::MAX - boot_time_us; + // We can detect if we wrapped the boot time by checking if rtc time is greater + // than the amount of time we would've wrapped. + if rtc_time_us > wrapped_boot_time_us { + // We also just checked that this won't overflow + rtc_time_us - wrapped_boot_time_us + } else { + boot_time_us + rtc_time_us + } } /// Read the current value of the time registers in milliseconds. pub fn get_time_ms(&self) -> u64 { - // current time is boot time + time since boot - self.get_boot_time_ms() + self.get_rtc_time_ms() + self.get_time_us() / 1_000 } /// Set the current value of the time registers in microseconds. - /// - /// This function will fail if `time_us` is less than the time - /// since boot. This happens because when setting the time, we - /// have to set the boot time which is calculated by subtracting - /// `time_us` from the time since boot. However, since time is - /// stored with unsigned integers, if `time_us` is less than - /// the time since boot, the subtraction result will be negative - /// and thus an overflow will occur. - pub fn set_time_us(&self, time_us: u64) -> Result<(), RtcSetOverflow> { - // current time is boot time + time since boot (rtc time) - // so boot time = current time - time since boot (rtc time) + pub fn set_time_us(&self, time_us: u64) { + // Current time is boot time + time since boot (rtc time) + // So boot time = current time - time since boot (rtc time) let rtc_time_us = self.get_rtc_time_us(); if time_us < rtc_time_us { - // if we subtract rtc_time_us from time_us, it will be negative and an overflow - // will happen - Err(RtcSetOverflow) + // An overflow would happen if we subtracted rtc_time_us from time_us. + // To work around this, we can wrap around u64::MAX by subtracting the + // difference between the current time and the time since boot. + // Subtracting time since boot and adding current new time is equivalent and + // avoids overflow. We just checked that rtc_time_us is less than time_us + // so this won't overflow. + self.set_boot_time_us(u64::MAX - rtc_time_us + time_us) } else { - self.set_boot_time_us(time_us - rtc_time_us); - Ok(()) + self.set_boot_time_us(time_us - rtc_time_us) } } /// Set the current value of the time registers in milliseconds. - /// - /// This function will fail if `time_ms` is less than the time - /// since boot. This happens because when setting the time, we - /// have to set the boot time which is calculated by subtracting - /// `time_ms` from the time since boot. However, since time is - /// stored with unsigned integers, if `time_ms` is less than - /// the time since boot, the subtraction result will be negative - /// and thus an overflow will occur. - pub fn set_time_ms(&self, time_ms: u64) -> Result<(), RtcSetOverflow> { + pub fn set_time_ms(&self, time_ms: u64) { self.set_time_us(time_ms * 1_000) } diff --git a/examples/src/bin/rtc_time.rs b/examples/src/bin/rtc_time.rs index 65e3f08161a..a2f40032396 100644 --- a/examples/src/bin/rtc_time.rs +++ b/examples/src/bin/rtc_time.rs @@ -27,13 +27,10 @@ fn main() -> ! { loop { esp_println::println!("rtc time in milliseconds is {}", rtc.get_time_ms()); delay.delay_millis(1000); - // Set the time to 1 second past the current time after 5 seconds have passed - if rtc.get_time_ms() > 5_000 { - let new_time = rtc.get_time_ms() + 1_000; - esp_println::println!("setting rtc time to {new_time} (milliseconds)"); - if rtc.set_time_ms(new_time).is_err() { - esp_println::println!("failed to set rtc time due to overflow"); - } - } + + // Set the time to half a second in the past + let new_time = rtc.get_time_ms() - 500; + esp_println::println!("setting rtc time to {new_time} milliseconds"); + rtc.set_time_ms(new_time); } } From f972ba2b179d28e9a156bd13e73ef8edefa960d8 Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Tue, 13 Aug 2024 16:28:24 -1000 Subject: [PATCH 12/30] Remove unused get_rtc_time_ms and get_rtc_time_us functions --- esp-hal/src/rtc_cntl/mod.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index 92cb64aab86..f78508ff485 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -271,11 +271,6 @@ impl<'d> Rtc<'d> { self.get_rtc_time_raw() * 1_000_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 } - /// Read the current value of the rtc time registers in milliseconds. - fn get_rtc_time_ms(&self) -> u64 { - self.get_rtc_time_raw() * 1_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 - } - /// Read the current value of the boot time registers in microseconds. fn get_boot_time_us(&self) -> u64 { // For more info on about how RTC setting works and what it has to do with boot time, see https://github.com/esp-rs/esp-hal/pull/1883 @@ -307,11 +302,6 @@ impl<'d> Rtc<'d> { l + (h << 32) } - /// Read the current value of the rtc time registers in milliseconds. - fn get_boot_time_ms(&self) -> u64 { - self.get_boot_time_us() / 1_000 - } - /// Set the current value of the boot time registers in microseconds. fn set_boot_time_us(&self, boot_time_us: u64) { // Please see `get_boot_time_ms` for documentation on registers and peripherals From 358f2ed3fc152e192adbe1a9cbba1d55f27b9c44 Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Wed, 14 Aug 2024 10:54:20 -1000 Subject: [PATCH 13/30] Make get_rtc_time_us public and re-add get_rtc_time_ms as public --- esp-hal/src/rtc_cntl/mod.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index f78508ff485..16b1cbd31fd 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -267,10 +267,23 @@ impl<'d> Rtc<'d> { } /// Read the current value of the rtc time registers in microseconds. - fn get_rtc_time_us(&self) -> u64 { + /// + /// **This function does not take into account the boot time registers, and + /// therefore will not react to using [`set_time_us`][Self::set_time_us] + /// and [`set_time_ms`][Self::set_time_ms].** + pub fn get_rtc_time_us(&self) -> u64 { self.get_rtc_time_raw() * 1_000_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 } + /// Read the current value of the rtc time registers in milliseconds. + /// + /// **This function does not take into account the boot time registers, and + /// therefore will not react to using [`set_time_us`][Self::set_time_us] + /// and [`set_time_ms`][Self::set_time_ms].** + pub fn get_rtc_time_ms(&self) -> u64 { + self.get_rtc_time_raw() * 1_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 + } + /// Read the current value of the boot time registers in microseconds. fn get_boot_time_us(&self) -> u64 { // For more info on about how RTC setting works and what it has to do with boot time, see https://github.com/esp-rs/esp-hal/pull/1883 From e3899dab53f5048fd082d2475d1e827c4e88c8cb Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Wed, 14 Aug 2024 10:55:51 -1000 Subject: [PATCH 14/30] Update changelog --- esp-hal/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 7eb9b34dbe5..202a0f7b56e 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow configuration of period updating method for MCPWM timers (#1898) - Add self-testing mode for TWAI peripheral. (#1929) - Added a `PeripheralClockControl::reset` to the driver constructors where missing (#1893) -- Added `Rtc::set_time_us` and `Rtc::set_time_ms` to allow setting RTC time (#1883) +- Added `Rtc::set_time_us` and `Rtc::set_time_ms` to allow setting RTC time, and `Rtc::get_rtc_time_us` and `Rtc::get_rtc_time_ms` to allow getting the RTC time without taking into account boot time (#1883) ### Changed From b473d3acbc0f215ac3ea7594d9fdb5aada2a5c91 Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:45:22 -1000 Subject: [PATCH 15/30] Remove get_time_raw and replace with public get_rtc_time_raw --- esp-hal/CHANGELOG.md | 2 +- esp-hal/src/rtc_cntl/mod.rs | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 202a0f7b56e..4fa15ebbbd5 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -24,7 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow DMA to/from psram for esp32s3 (#1827) - DMA buffers now don't require a static lifetime. Make sure to never `mem::forget` an in-progress DMA transfer (consider using `#[deny(clippy::mem_forget)]`) (#1837) - Peripherals (where possible) are now explicitly reset and enabled in their constructors (#1893) -- Deprecated `Rtc::get_time_raw` since it doesn't respect boot time and therefore won't react to setting RTC time (#1883) +- Renamed `Rtc::get_time_raw` to `Rtc::get_rtc_time_raw` (#1883) ### Fixed diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index 16b1cbd31fd..71203e1c7b0 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -217,18 +217,12 @@ impl<'d> Rtc<'d> { RtcClock::estimate_xtal_frequency() } - #[deprecated = "This function does not take into account the boot time registers, and therefore will not react to using `set_time_us` and `set_time_ms`."] /// Read the current raw value of the rtc time registers. /// /// **This function does not take into account the boot time registers, and /// therefore will not react to using [`set_time_us`][Self::set_time_us] /// and [`set_time_ms`][Self::set_time_ms].** - pub fn get_time_raw(&self) -> u64 { - self.get_rtc_time_raw() - } - - /// Read the current raw value of the rtc time registers. - fn get_rtc_time_raw(&self) -> u64 { + pub fn get_rtc_time_raw(&self) -> u64 { #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; #[cfg(any(esp32c6, esp32h2))] From 8c887646e85a1da4d977e46d1c0f667e30c3603e Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Sat, 17 Aug 2024 21:04:26 -1000 Subject: [PATCH 16/30] Changelog reordering --- esp-hal/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 9602358031f..f72dca82377 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -14,8 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow configuration of period updating method for MCPWM timers (#1898) - Add self-testing mode for TWAI peripheral. (#1929) - Added a `PeripheralClockControl::reset` to the driver constructors where missing (#1893) -- Added `Rtc::set_time_us` and `Rtc::set_time_ms` to allow setting RTC time, and `Rtc::get_rtc_time_us` and `Rtc::get_rtc_time_ms` to allow getting the RTC time without taking into account boot time (#1883) - Added `debugger::debugger_connected`. (#1961) +- Added `Rtc::set_time_us` and `Rtc::set_time_ms` to allow setting RTC time, and `Rtc::get_rtc_time_us` and `Rtc::get_rtc_time_ms` to allow getting the RTC time without taking into account boot time (#1883) ### Changed @@ -26,8 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow DMA to/from psram for esp32s3 (#1827) - DMA buffers now don't require a static lifetime. Make sure to never `mem::forget` an in-progress DMA transfer (consider using `#[deny(clippy::mem_forget)]`) (#1837) - Peripherals (where possible) are now explicitly reset and enabled in their constructors (#1893) -- Renamed `Rtc::get_time_raw` to `Rtc::get_rtc_time_raw` (#1883) - Reset peripherals in driver constructors where missing (#1893, #1961) +- Renamed `Rtc::get_time_raw` to `Rtc::get_rtc_time_raw` (#1883) ### Fixed From c7fd0318fb9f2bf16367ef54ddf296492243684a Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Sun, 18 Aug 2024 09:51:54 -1000 Subject: [PATCH 17/30] Function renaming --- esp-hal/src/rtc_cntl/mod.rs | 59 +++++++++++---------------- esp-hal/src/rtc_cntl/sleep/esp32.rs | 2 +- esp-hal/src/rtc_cntl/sleep/esp32c3.rs | 2 +- esp-hal/src/rtc_cntl/sleep/esp32c6.rs | 2 +- esp-hal/src/rtc_cntl/sleep/esp32s3.rs | 2 +- 5 files changed, 28 insertions(+), 39 deletions(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index 71203e1c7b0..b042df30d3b 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -217,12 +217,8 @@ impl<'d> Rtc<'d> { RtcClock::estimate_xtal_frequency() } - /// Read the current raw value of the rtc time registers. - /// - /// **This function does not take into account the boot time registers, and - /// therefore will not react to using [`set_time_us`][Self::set_time_us] - /// and [`set_time_ms`][Self::set_time_ms].** - pub fn get_rtc_time_raw(&self) -> u64 { + /// Get the time since boot in the raw register units. + pub fn time_since_boot_raw(&self) -> u64 { #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; #[cfg(any(esp32c6, esp32h2))] @@ -260,26 +256,19 @@ impl<'d> Rtc<'d> { ((h as u64) << 32) | (l as u64) } - /// Read the current value of the rtc time registers in microseconds. - /// - /// **This function does not take into account the boot time registers, and - /// therefore will not react to using [`set_time_us`][Self::set_time_us] - /// and [`set_time_ms`][Self::set_time_ms].** - pub fn get_rtc_time_us(&self) -> u64 { - self.get_rtc_time_raw() * 1_000_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 + /// Get the time since boot in microseconds. + pub fn time_since_boot_us(&self) -> u64 { + self.time_since_boot_raw() * 1_000_000 + / RtcClock::get_slow_freq().frequency().to_Hz() as u64 } - /// Read the current value of the rtc time registers in milliseconds. - /// - /// **This function does not take into account the boot time registers, and - /// therefore will not react to using [`set_time_us`][Self::set_time_us] - /// and [`set_time_ms`][Self::set_time_ms].** - pub fn get_rtc_time_ms(&self) -> u64 { - self.get_rtc_time_raw() * 1_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 + /// Get the time since boot in milliseconds. + pub fn time_since_boot_ms(&self) -> u64 { + self.time_since_boot_raw() * 1_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 } /// Read the current value of the boot time registers in microseconds. - fn get_boot_time_us(&self) -> u64 { + fn boot_time_us(&self) -> u64 { // For more info on about how RTC setting works and what it has to do with boot time, see https://github.com/esp-rs/esp-hal/pull/1883 // In terms of registers, STORE2 and STORE3 are used on all current chips @@ -311,7 +300,7 @@ impl<'d> Rtc<'d> { /// Set the current value of the boot time registers in microseconds. fn set_boot_time_us(&self, boot_time_us: u64) { - // Please see `get_boot_time_ms` for documentation on registers and peripherals + // Please see `boot_time_ms` for documentation on registers and peripherals // used for certain SOCs. #[cfg(not(any(esp32c6, esp32h2)))] @@ -326,11 +315,11 @@ impl<'d> Rtc<'d> { h.write(|w| unsafe { w.bits((boot_time_us >> 32) as u32) }); } - /// Read the current value of the time registers in microseconds. - pub fn get_time_us(&self) -> u64 { + /// Get the current time in microseconds. + pub fn current_time_us(&self) -> u64 { // current time is boot time + time since boot - let rtc_time_us = self.get_rtc_time_us(); - let boot_time_us = self.get_boot_time_us(); + let rtc_time_us = self.time_since_boot_us(); + let boot_time_us = self.boot_time_us(); let wrapped_boot_time_us = u64::MAX - boot_time_us; // We can detect if we wrapped the boot time by checking if rtc time is greater // than the amount of time we would've wrapped. @@ -342,16 +331,16 @@ impl<'d> Rtc<'d> { } } - /// Read the current value of the time registers in milliseconds. - pub fn get_time_ms(&self) -> u64 { - self.get_time_us() / 1_000 + /// Get the current time in milliseconds. + pub fn current_time_ms(&self) -> u64 { + self.current_time_us() / 1_000 } - /// Set the current value of the time registers in microseconds. - pub fn set_time_us(&self, time_us: u64) { + /// Set the current time in microseconds. + pub fn set_current_time_us(&self, time_us: u64) { // Current time is boot time + time since boot (rtc time) // So boot time = current time - time since boot (rtc time) - let rtc_time_us = self.get_rtc_time_us(); + let rtc_time_us = self.time_since_boot_us(); if time_us < rtc_time_us { // An overflow would happen if we subtracted rtc_time_us from time_us. // To work around this, we can wrap around u64::MAX by subtracting the @@ -365,9 +354,9 @@ impl<'d> Rtc<'d> { } } - /// Set the current value of the time registers in milliseconds. - pub fn set_time_ms(&self, time_ms: u64) { - self.set_time_us(time_ms * 1_000) + /// Set the current time in milliseconds. + pub fn set_current_time_ms(&self, time_ms: u64) { + self.set_current_time_us(time_ms * 1_000) } /// Enter deep sleep and wake with the provided `wake_sources`. diff --git a/esp-hal/src/rtc_cntl/sleep/esp32.rs b/esp-hal/src/rtc_cntl/sleep/esp32.rs index cb6348e3920..b93d8a05006 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32.rs @@ -54,7 +54,7 @@ impl WakeSource for TimerWakeupSource { let clock_hz = clock_freq.frequency().to_Hz() as u64; let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64; // "alarm" time in slow rtc ticks - let now = rtc.get_rtc_time_raw(); + let now = rtc.time_since_boot_raw(); let time_in_ticks = now + ticks; unsafe { rtc_cntl diff --git a/esp-hal/src/rtc_cntl/sleep/esp32c3.rs b/esp-hal/src/rtc_cntl/sleep/esp32c3.rs index 6f4d41df7d4..e707b06d565 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32c3.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32c3.rs @@ -99,7 +99,7 @@ impl WakeSource for TimerWakeupSource { let clock_hz = clock_freq.frequency().to_Hz() as u64; let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64; // "alarm" time in slow rtc ticks - let now = rtc.get_rtc_time_raw(); + let now = rtc.time_since_boot_raw(); let time_in_ticks = now + ticks; unsafe { rtc_cntl diff --git a/esp-hal/src/rtc_cntl/sleep/esp32c6.rs b/esp-hal/src/rtc_cntl/sleep/esp32c6.rs index c3b6bae02d6..4e54d5a08cc 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32c6.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32c6.rs @@ -46,7 +46,7 @@ impl WakeSource for TimerWakeupSource { let clock_hz = clock_freq.frequency().to_Hz() as u64; let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64; // "alarm" time in slow rtc ticks - let now = rtc.get_rtc_time_raw(); + let now = rtc.time_since_boot_raw(); let time_in_ticks = now + ticks; unsafe { lp_timer.tar0_high().write(|w| { diff --git a/esp-hal/src/rtc_cntl/sleep/esp32s3.rs b/esp-hal/src/rtc_cntl/sleep/esp32s3.rs index bdc05129f70..0f57bdb16a4 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32s3.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32s3.rs @@ -94,7 +94,7 @@ impl WakeSource for TimerWakeupSource { let clock_hz = clock_freq.frequency().to_Hz() as u64; let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64; // "alarm" time in slow rtc ticks - let now = rtc.get_rtc_time_raw(); + let now = rtc.time_since_boot_raw(); let time_in_ticks = now + ticks; unsafe { rtc_cntl From 68de22c45d8ea8098dfed61d68c8f28180662e35 Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Sun, 18 Aug 2024 10:23:01 -1000 Subject: [PATCH 18/30] Use fugit and update changelog --- esp-hal/CHANGELOG.md | 5 ++-- esp-hal/src/rtc_cntl/mod.rs | 50 ++++++++++++++++-------------------- examples/src/bin/rtc_time.rs | 11 +++++--- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index f72dca82377..af7f0211c95 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add self-testing mode for TWAI peripheral. (#1929) - Added a `PeripheralClockControl::reset` to the driver constructors where missing (#1893) - Added `debugger::debugger_connected`. (#1961) -- Added `Rtc::set_time_us` and `Rtc::set_time_ms` to allow setting RTC time, and `Rtc::get_rtc_time_us` and `Rtc::get_rtc_time_ms` to allow getting the RTC time without taking into account boot time (#1883) +- Added `Rtc::set_current_time` to allow setting RTC time, and `Rtc::current_time` to getting RTC time while taking into account boot time (#1883) ### Changed @@ -27,7 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - DMA buffers now don't require a static lifetime. Make sure to never `mem::forget` an in-progress DMA transfer (consider using `#[deny(clippy::mem_forget)]`) (#1837) - Peripherals (where possible) are now explicitly reset and enabled in their constructors (#1893) - Reset peripherals in driver constructors where missing (#1893, #1961) -- Renamed `Rtc::get_time_raw` to `Rtc::get_rtc_time_raw` (#1883) +- Renamed and merged `Rtc::get_time_us` and `Rtc::get_time_ms` into `Rtc::time_since_boot` (#1883) ### Fixed @@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - This package no longer re-exports the `esp_hal_procmacros::main` macro (#1828) - The `AesFlavour` trait no longer has the `ENCRYPT_MODE`/`DECRYPT_MODE` associated constants (#1849) +- Removed `Rtc::get_time_raw` (#1883) ## [0.19.0] - 2024-07-15 diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index b042df30d3b..cb0e677998e 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -218,7 +218,7 @@ impl<'d> Rtc<'d> { } /// Get the time since boot in the raw register units. - pub fn time_since_boot_raw(&self) -> u64 { + fn time_since_boot_raw(&self) -> u64 { #[cfg(not(any(esp32c6, esp32h2)))] let rtc_cntl = unsafe { &*LPWR::ptr() }; #[cfg(any(esp32c6, esp32h2))] @@ -256,15 +256,12 @@ impl<'d> Rtc<'d> { ((h as u64) << 32) | (l as u64) } - /// Get the time since boot in microseconds. - pub fn time_since_boot_us(&self) -> u64 { - self.time_since_boot_raw() * 1_000_000 - / RtcClock::get_slow_freq().frequency().to_Hz() as u64 - } - - /// Get the time since boot in milliseconds. - pub fn time_since_boot_ms(&self) -> u64 { - self.time_since_boot_raw() * 1_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64 + /// Get the time since boot. + pub fn time_since_boot(&self) -> MicrosDurationU64 { + MicrosDurationU64::micros( + self.time_since_boot_raw() * 1_000_000 + / RtcClock::get_slow_freq().frequency().to_Hz() as u64, + ) } /// Read the current value of the boot time registers in microseconds. @@ -316,49 +313,46 @@ impl<'d> Rtc<'d> { } /// Get the current time in microseconds. - pub fn current_time_us(&self) -> u64 { + pub fn current_time(&self) -> MicrosDurationU64 { // current time is boot time + time since boot - let rtc_time_us = self.time_since_boot_us(); + + let rtc_time_us = self.time_since_boot().to_micros(); let boot_time_us = self.boot_time_us(); let wrapped_boot_time_us = u64::MAX - boot_time_us; + // We can detect if we wrapped the boot time by checking if rtc time is greater // than the amount of time we would've wrapped. - if rtc_time_us > wrapped_boot_time_us { + let current_time_us = if rtc_time_us > wrapped_boot_time_us { // We also just checked that this won't overflow rtc_time_us - wrapped_boot_time_us } else { boot_time_us + rtc_time_us - } - } + }; - /// Get the current time in milliseconds. - pub fn current_time_ms(&self) -> u64 { - self.current_time_us() / 1_000 + MicrosDurationU64::micros(current_time_us) } /// Set the current time in microseconds. - pub fn set_current_time_us(&self, time_us: u64) { + pub fn set_current_time(&self, current_time: MicrosDurationU64) { + let current_time_us = current_time.to_micros(); + // Current time is boot time + time since boot (rtc time) // So boot time = current time - time since boot (rtc time) - let rtc_time_us = self.time_since_boot_us(); - if time_us < rtc_time_us { + + let rtc_time_us = self.time_since_boot().to_micros(); + if current_time_us < rtc_time_us { // An overflow would happen if we subtracted rtc_time_us from time_us. // To work around this, we can wrap around u64::MAX by subtracting the // difference between the current time and the time since boot. // Subtracting time since boot and adding current new time is equivalent and // avoids overflow. We just checked that rtc_time_us is less than time_us // so this won't overflow. - self.set_boot_time_us(u64::MAX - rtc_time_us + time_us) + self.set_boot_time_us(u64::MAX - rtc_time_us + current_time_us) } else { - self.set_boot_time_us(time_us - rtc_time_us) + self.set_boot_time_us(current_time_us - rtc_time_us) } } - /// Set the current time in milliseconds. - pub fn set_current_time_ms(&self, time_ms: u64) { - self.set_current_time_us(time_ms * 1_000) - } - /// Enter deep sleep and wake with the provided `wake_sources`. #[cfg(any(esp32, esp32s3, esp32c3, esp32c6))] pub fn sleep_deep(&mut self, wake_sources: &[&dyn WakeSource]) -> ! { diff --git a/examples/src/bin/rtc_time.rs b/examples/src/bin/rtc_time.rs index a2f40032396..2fc10342a10 100644 --- a/examples/src/bin/rtc_time.rs +++ b/examples/src/bin/rtc_time.rs @@ -25,12 +25,15 @@ fn main() -> ! { let delay = Delay::new(&clocks); loop { - esp_println::println!("rtc time in milliseconds is {}", rtc.get_time_ms()); + esp_println::println!( + "rtc time in milliseconds is {}", + rtc.current_time().to_millis() + ); delay.delay_millis(1000); // Set the time to half a second in the past - let new_time = rtc.get_time_ms() - 500; - esp_println::println!("setting rtc time to {new_time} milliseconds"); - rtc.set_time_ms(new_time); + let new_time = rtc.current_time() - 500.millis(); + esp_println::println!("setting rtc time to {} milliseconds", new_time.to_millis()); + rtc.set_current_time(new_time); } } From 94830dfc4511bb635a22acf3c8e1c08677f836b4 Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Sun, 18 Aug 2024 10:28:32 -1000 Subject: [PATCH 19/30] Small typo fix --- esp-hal/src/rtc_cntl/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index cb0e677998e..28ee0508c70 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -297,7 +297,7 @@ impl<'d> Rtc<'d> { /// Set the current value of the boot time registers in microseconds. fn set_boot_time_us(&self, boot_time_us: u64) { - // Please see `boot_time_ms` for documentation on registers and peripherals + // Please see `boot_time_us` for documentation on registers and peripherals // used for certain SOCs. #[cfg(not(any(esp32c6, esp32h2)))] @@ -314,7 +314,7 @@ impl<'d> Rtc<'d> { /// Get the current time in microseconds. pub fn current_time(&self) -> MicrosDurationU64 { - // current time is boot time + time since boot + // Current time is boot time + time since boot let rtc_time_us = self.time_since_boot().to_micros(); let boot_time_us = self.boot_time_us(); From a7cb08ad7aa09650f1fa6c023a6d08ccd0c2d890 Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Sun, 18 Aug 2024 10:28:55 -1000 Subject: [PATCH 20/30] Fix changelog addition from merging --- esp-hal/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index af7f0211c95..e2e899618f0 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -13,7 +13,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added touch pad support for esp32 (#1873, #1956) - Allow configuration of period updating method for MCPWM timers (#1898) - Add self-testing mode for TWAI peripheral. (#1929) -- Added a `PeripheralClockControl::reset` to the driver constructors where missing (#1893) - Added `debugger::debugger_connected`. (#1961) - Added `Rtc::set_current_time` to allow setting RTC time, and `Rtc::current_time` to getting RTC time while taking into account boot time (#1883) From 31309c784afe07d6bc3c338d96fc522b6d689a7c Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Sat, 31 Aug 2024 17:15:04 -0700 Subject: [PATCH 21/30] Use chrono for current_time and set_current_time --- esp-hal/Cargo.toml | 1 + esp-hal/src/rtc_cntl/mod.rs | 26 +++++++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 11a516cfa89..f1374056c6f 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -19,6 +19,7 @@ bitflags = "2.6.0" bytemuck = "1.16.1" bitfield = "0.15.0" cfg-if = "1.0.0" +chrono = { version = "0.4.38", default-features = false } critical-section = "1.1.2" defmt = { version = "0.3.8", optional = true } delegate = "0.12.0" diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index 28ee0508c70..2e8d6d8cc94 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -71,6 +71,7 @@ #![allow(missing_docs)] // TODO: Remove when able +use chrono::{DateTime, NaiveDateTime}; #[cfg(not(any(esp32c6, esp32h2)))] use fugit::HertzU32; use fugit::MicrosDurationU64; @@ -312,8 +313,8 @@ impl<'d> Rtc<'d> { h.write(|w| unsafe { w.bits((boot_time_us >> 32) as u32) }); } - /// Get the current time in microseconds. - pub fn current_time(&self) -> MicrosDurationU64 { + /// Get the current time. + pub fn current_time(&self) -> NaiveDateTime { // Current time is boot time + time since boot let rtc_time_us = self.time_since_boot().to_micros(); @@ -329,19 +330,30 @@ impl<'d> Rtc<'d> { boot_time_us + rtc_time_us }; - MicrosDurationU64::micros(current_time_us) + DateTime::from_timestamp_micros(current_time_us as i64) + .unwrap() + .naive_utc() } - /// Set the current time in microseconds. - pub fn set_current_time(&self, current_time: MicrosDurationU64) { - let current_time_us = current_time.to_micros(); + /// Set the current time. + /// + /// # Panics + /// + /// Panics if `current_time` is before the Unix epoch (meaning the + /// underlying timestamp is negative). + pub fn set_current_time(&self, current_time: NaiveDateTime) { + let current_time_us: u64 = current_time + .and_utc() + .timestamp_micros() + .try_into() + .expect("current_time is negative"); // Current time is boot time + time since boot (rtc time) // So boot time = current time - time since boot (rtc time) let rtc_time_us = self.time_since_boot().to_micros(); if current_time_us < rtc_time_us { - // An overflow would happen if we subtracted rtc_time_us from time_us. + // An overflow would happen if we subtracted rtc_time_us from current_time_us. // To work around this, we can wrap around u64::MAX by subtracting the // difference between the current time and the time since boot. // Subtracting time since boot and adding current new time is equivalent and From 238bc4d5b6fe69e7cc78cbcbfda3b8a8e1ebd715 Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Wed, 4 Sep 2024 20:08:35 -0700 Subject: [PATCH 22/30] Fix changelog --- esp-hal/CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 5e2ff1270fd..0f8acf38b64 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added sleep and wakeup support for esp32c2 (#1922) - `Input`, `Output`, `OutputOpenDrain` and `Flex` now implement `Peripheral`. (#2094) - Previously unavailable memory is available via `.dram2_uninit` section (#2079) +- Added `Rtc::set_current_time` to allow setting RTC time, and `Rtc::current_time` to getting RTC time while taking into account boot time (#1883) ### Changed @@ -31,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - To avoid confusion with the `Rtc::current_time` wall clock time APIs, we've renamed `esp_hal::time::current_time` to `esp_hal::time::now`. (#2091) - Renamed `touch::Continous` to `touch::Continuous`. (#2094) - The (previously undocumented) `ErasedPin` enum has been replaced with the `ErasedPin` struct. (#2094) +- Renamed and merged `Rtc::get_time_us` and `Rtc::get_time_ms` into `Rtc::time_since_boot` (#1883) ### Fixed @@ -48,6 +50,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed `Peripherals::take`. Use `esp_hal::init` to obtain `Peripherals` (#1999) - Removed `AnyInputOnlyPin` in favour of `AnyPin`. (#2071) - Removed the following functions from `GpioPin`: `is_high`, `is_low`, `set_high`, `set_low`, `set_state`, `is_set_high`, `is_set_low`, `toggle`. (#2094) +- Removed `Rtc::get_time_raw` (#1883) ## [0.20.1] - 2024-08-30 @@ -67,7 +70,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added a `PeripheralClockControl::reset` to the driver constructors where missing (#1893) - Added `digest::Digest` implementation to SHA (#1908) - Added `debugger::debugger_connected`. (#1961) -- Added `Rtc::set_current_time` to allow setting RTC time, and `Rtc::current_time` to getting RTC time while taking into account boot time (#1883) - DMA: don't require `Sealed` to implement `ReadBuffer` and `WriteBuffer` (#1921) - Allow DMA to/from psram for esp32s3 (#1827) - Added missing methods to `SpiDmaBus` (#2016). @@ -84,7 +86,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - DMA buffers now don't require a static lifetime. Make sure to never `mem::forget` an in-progress DMA transfer (consider using `#[deny(clippy::mem_forget)]`) (#1837) - Peripherals (where possible) are now explicitly reset and enabled in their constructors (#1893) - Reset peripherals in driver constructors where missing (#1893, #1961) -- Renamed and merged `Rtc::get_time_us` and `Rtc::get_time_ms` into `Rtc::time_since_boot` (#1883) - Improve SYSTIMER API (#1871) - SHA driver now use specific structs for the hashing algorithm instead of a parameter. (#1908) - Remove `fn free(self)` in HMAC which goes against esp-hal API guidelines (#1972) @@ -110,7 +111,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - This package no longer re-exports the `esp_hal_procmacros::main` macro (#1828) - The `AesFlavour` trait no longer has the `ENCRYPT_MODE`/`DECRYPT_MODE` associated constants (#1849) -- Removed `Rtc::get_time_raw` (#1883) - Removed `FlashSafeDma` (#1856) - Remove redundant WithDmaSpi traits (#1975) - `IsFullDuplex` and `IsHalfDuplex` traits (#1985) From 0b889f7fe259e236d15853d3cfa47f7f3fdccb5c Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Wed, 4 Sep 2024 20:11:22 -0700 Subject: [PATCH 23/30] Update example --- examples/src/bin/rtc_time.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/examples/src/bin/rtc_time.rs b/examples/src/bin/rtc_time.rs index cfa80af66ec..182d045c778 100644 --- a/examples/src/bin/rtc_time.rs +++ b/examples/src/bin/rtc_time.rs @@ -5,6 +5,8 @@ #![no_std] #![no_main] +use core::time::Duration; + use esp_backtrace as _; use esp_hal::{delay::Delay, prelude::*, rtc_cntl::Rtc}; @@ -18,13 +20,16 @@ fn main() -> ! { loop { esp_println::println!( "rtc time in milliseconds is {}", - rtc.current_time().to_millis() + rtc.current_time().and_utc().timestamp_millis() ); delay.delay_millis(1000); // Set the time to half a second in the past - let new_time = rtc.current_time() - 500.millis(); - esp_println::println!("setting rtc time to {} milliseconds", new_time.to_millis()); + let new_time = rtc.current_time() - Duration::from_millis(500); + esp_println::println!( + "setting rtc time to {} milliseconds", + new_time.and_utc().timestamp_millis() + ); rtc.set_current_time(new_time); } } From 7d4e3a7e0d497f99e1762870b29b0cb3984e99a2 Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:34:19 -0700 Subject: [PATCH 24/30] Fix merge errors --- esp-hal/CHANGELOG.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 0f8acf38b64..f7d858f4215 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -80,12 +80,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Peripheral driver constructors don't take `InterruptHandler`s anymore. Use `set_interrupt_handler` to explicitly set the interrupt handler now. (#1819) - Migrate SPI driver to use DMA buffer objects (#1856, #1985) - Use the peripheral ref pattern for `OneShotTimer` and `PeriodicTimer` (#1855) -- Improve SYSTIMER API (#1870) -- DMA: don't require `Sealed` to implement `ReadBuffer` and `WriteBuffer` (#1921) -- Allow DMA to/from psram for esp32s3 (#1827) -- DMA buffers now don't require a static lifetime. Make sure to never `mem::forget` an in-progress DMA transfer (consider using `#[deny(clippy::mem_forget)]`) (#1837) -- Peripherals (where possible) are now explicitly reset and enabled in their constructors (#1893) -- Reset peripherals in driver constructors where missing (#1893, #1961) - Improve SYSTIMER API (#1871) - SHA driver now use specific structs for the hashing algorithm instead of a parameter. (#1908) - Remove `fn free(self)` in HMAC which goes against esp-hal API guidelines (#1972) From 6e7fd88167fb4e90dd08bbc30c99b4f88a81f800 Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:41:03 -0700 Subject: [PATCH 25/30] Rename `time::current_time` to `time::uptime` --- esp-hal/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index f7d858f4215..ea549c611b6 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Renamed `touch::Continous` to `touch::Continuous`. (#2094) - The (previously undocumented) `ErasedPin` enum has been replaced with the `ErasedPin` struct. (#2094) - Renamed and merged `Rtc::get_time_us` and `Rtc::get_time_ms` into `Rtc::time_since_boot` (#1883) +- Renamed `time::current_time` to `time::uptime` (#1883) ### Fixed From f3e66921ae7269c234d9deb6808c8ee000bb088b Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:28:32 -0700 Subject: [PATCH 26/30] Revert "Rename `time::current_time` to `time::uptime`" This reverts commit fe8446899747c88d5b9f945f319e1133b90773ee. --- esp-hal/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index ea549c611b6..f7d858f4215 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -33,7 +33,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Renamed `touch::Continous` to `touch::Continuous`. (#2094) - The (previously undocumented) `ErasedPin` enum has been replaced with the `ErasedPin` struct. (#2094) - Renamed and merged `Rtc::get_time_us` and `Rtc::get_time_ms` into `Rtc::time_since_boot` (#1883) -- Renamed `time::current_time` to `time::uptime` (#1883) ### Fixed From 14948fe608ee3f75ea7c92efde81d359465101aa Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:32:41 -0700 Subject: [PATCH 27/30] Format --- esp-hal/src/rtc_cntl/mod.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index 67ce522438f..97d8ed95706 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -88,7 +88,8 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::Interrupt, reset::{SleepSource, WakeupReason}, - Cpu, InterruptConfigurable, + Cpu, + InterruptConfigurable, }; // only include sleep where its been implemented #[cfg(any(esp32, esp32s3, esp32c3, esp32c6, esp32c2))] @@ -114,7 +115,7 @@ pub(crate) enum RtcFastClock { /// Main XTAL, divided by 4 RtcFastClockXtalD4 = 0, /// Internal fast RC oscillator - RtcFastClock8m = 1, + RtcFastClock8m = 1, } #[cfg(not(any(esp32c6, esp32h2)))] @@ -136,11 +137,11 @@ impl Clock for RtcFastClock { /// RTC SLOW_CLK frequency values pub enum RtcSlowClock { /// Internal slow RC oscillator - RtcSlowClockRtc = 0, + RtcSlowClockRtc = 0, /// External 32 KHz XTAL RtcSlowClock32kXtal = 1, /// Internal fast RC oscillator, divided by 256 - RtcSlowClock8mD256 = 2, + RtcSlowClock8mD256 = 2, } #[cfg(not(any(esp32c6, esp32h2)))] @@ -168,11 +169,11 @@ impl Clock for RtcSlowClock { /// Clock source to be calibrated using rtc_clk_cal function pub(crate) enum RtcCalSel { /// Currently selected RTC SLOW_CLK - RtcCalRtcMux = 0, + RtcCalRtcMux = 0, /// Internal 8 MHz RC oscillator, divided by 256 - RtcCal8mD256 = 1, + RtcCal8mD256 = 1, /// External 32 KHz XTAL - RtcCal32kXtal = 2, + RtcCal32kXtal = 2, #[cfg(not(esp32))] /// Internal 150 KHz RC oscillator RtcCalInternalOsc = 3, @@ -760,11 +761,11 @@ impl RtcClock { #[allow(unused)] #[derive(Debug, Clone, Copy)] enum RwdtStageAction { - Off = 0, - Interrupt = 1, - ResetCpu = 2, + Off = 0, + Interrupt = 1, + ResetCpu = 2, ResetSystem = 3, - ResetRtc = 4, + ResetRtc = 4, } /// RTC Watchdog Timer. From f9d875163a419cca12ef1d93883207b6025ae543 Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:41:44 -0700 Subject: [PATCH 28/30] Add info to migration guide --- esp-hal/MIGRATING-0.20.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/esp-hal/MIGRATING-0.20.md b/esp-hal/MIGRATING-0.20.md index b5fb14d45ab..2d5abc0c091 100644 --- a/esp-hal/MIGRATING-0.20.md +++ b/esp-hal/MIGRATING-0.20.md @@ -80,3 +80,13 @@ let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); .map_err(|e| e.0) .unwrap(); ``` + +## RTC Wall Clock APIs + +Instead of the `get_time_ms`, `get_time_us`, and `get_time_raw` functions, the `Rtc` struct now provides the `current_time` function, using `chrono`'s `NaiveDateTime` struct. The current time can also be set using the `set_current_time` function. + +```diff +let rtc = Rtc::new(peripherals.LPWR); +- let current_time_ms = rtc.get_time_ms(); ++ let current_time_ms = rtc.current_time().and_utc().timestamp_millis(); // assuming UTC +``` From 296412a7257eeb9546371f3926ee6aab483a713c Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:42:40 -0700 Subject: [PATCH 29/30] Fix compilation for esp32c2 --- esp-hal/src/rtc_cntl/sleep/esp32c2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-hal/src/rtc_cntl/sleep/esp32c2.rs b/esp-hal/src/rtc_cntl/sleep/esp32c2.rs index c0fe69a5094..7fb003fd11b 100644 --- a/esp-hal/src/rtc_cntl/sleep/esp32c2.rs +++ b/esp-hal/src/rtc_cntl/sleep/esp32c2.rs @@ -136,7 +136,7 @@ impl WakeSource for TimerWakeupSource { let clock_hz = clock_freq.frequency().to_Hz() as u64; let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64; // "alarm" time in slow rtc ticks - let now = rtc.get_time_raw(); + let now = rtc.time_since_boot_raw(); let time_in_ticks = now + ticks; unsafe { rtc_cntl From ea51f02911dce601f56b2630ee96b09007aed14c Mon Sep 17 00:00:00 2001 From: amsam0 <44983869+amsam0@users.noreply.github.com> Date: Fri, 6 Sep 2024 20:38:47 -0700 Subject: [PATCH 30/30] Remove information about setting RTC time from migration guide since it isn't really relevant --- esp-hal/MIGRATING-0.20.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-hal/MIGRATING-0.20.md b/esp-hal/MIGRATING-0.20.md index 2d5abc0c091..a860eb6f4bc 100644 --- a/esp-hal/MIGRATING-0.20.md +++ b/esp-hal/MIGRATING-0.20.md @@ -83,7 +83,7 @@ let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); ## RTC Wall Clock APIs -Instead of the `get_time_ms`, `get_time_us`, and `get_time_raw` functions, the `Rtc` struct now provides the `current_time` function, using `chrono`'s `NaiveDateTime` struct. The current time can also be set using the `set_current_time` function. +Instead of the `get_time_ms`, `get_time_us`, and `get_time_raw` functions, the `Rtc` struct now provides the `current_time` function, using `chrono`'s `NaiveDateTime` struct. ```diff let rtc = Rtc::new(peripherals.LPWR);