aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/rtc
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-08-27 21:15:57 -0500
committerxoviat <[email protected]>2023-08-27 21:15:57 -0500
commite981cd496827c01cba11fd6ba40b2b7ed482e49b (patch)
tree7c0676bdb67f803af1165ec63d4318e687daab9a /embassy-stm32/src/rtc
parent9f928010a86be9e0f8b5fa4257c3edd70261c0dc (diff)
stm32: fix rtc wakeup timing and add dbg
Diffstat (limited to 'embassy-stm32/src/rtc')
-rw-r--r--embassy-stm32/src/rtc/mod.rs14
-rw-r--r--embassy-stm32/src/rtc/v2.rs43
2 files changed, 46 insertions, 11 deletions
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 8bda0926e..496ad5c1e 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -47,6 +47,18 @@ struct RtcInstant {
47 subsecond: u16, 47 subsecond: u16,
48} 48}
49 49
50#[cfg(all(feature = "low-power", feature = "defmt"))]
51impl defmt::Format for RtcInstant {
52 fn format(&self, fmt: defmt::Formatter) {
53 defmt::write!(
54 fmt,
55 "{}:{}",
56 self.second,
57 RTC::regs().prer().read().prediv_s() - self.subsecond,
58 )
59 }
60}
61
50#[cfg(feature = "low-power")] 62#[cfg(feature = "low-power")]
51impl core::ops::Sub for RtcInstant { 63impl core::ops::Sub for RtcInstant {
52 type Output = embassy_time::Duration; 64 type Output = embassy_time::Duration;
@@ -174,7 +186,7 @@ impl Rtc {
174 let second = bcd2_to_byte((tr.st(), tr.su())); 186 let second = bcd2_to_byte((tr.st(), tr.su()));
175 187
176 // Unlock the registers 188 // Unlock the registers
177 r.dr(); 189 r.dr().read();
178 190
179 RtcInstant { second, subsecond } 191 RtcInstant { second, subsecond }
180 } 192 }
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index 62b398689..7eb8a96c4 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -1,7 +1,5 @@
1use stm32_metapac::rtc::vals::{Init, Osel, Pol}; 1use stm32_metapac::rtc::vals::{Init, Osel, Pol};
2 2
3#[cfg(feature = "low-power")]
4use super::RtcInstant;
5use super::{sealed, RtcConfig}; 3use super::{sealed, RtcConfig};
6use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
7use crate::peripherals::RTC; 5use crate::peripherals::RTC;
@@ -77,6 +75,21 @@ impl super::Rtc {
77 /// start the wakeup alarm and wtih a duration that is as close to but less than 75 /// start the wakeup alarm and wtih a duration that is as close to but less than
78 /// the requested duration, and record the instant the wakeup alarm was started 76 /// the requested duration, and record the instant the wakeup alarm was started
79 pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) { 77 pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) {
78 #[cfg(feature = "rtc-debug")]
79 if critical_section::with(|cs| {
80 if let Some(instant) = self.stop_time.borrow(cs).take() {
81 self.stop_time.borrow(cs).replace(Some(instant));
82
83 Some(())
84 } else {
85 None
86 }
87 })
88 .is_some()
89 {
90 return;
91 }
92
80 use embassy_time::{Duration, TICK_HZ}; 93 use embassy_time::{Duration, TICK_HZ};
81 94
82 use crate::rcc::get_freqs; 95 use crate::rcc::get_freqs;
@@ -86,17 +99,14 @@ impl super::Rtc {
86 let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; 99 let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ;
87 let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); 100 let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32);
88 101
89 // adjust the rtc ticks to the prescaler 102 // adjust the rtc ticks to the prescaler and subtract one rtc tick
90 let rtc_ticks = rtc_ticks / (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64); 103 let rtc_ticks = rtc_ticks / (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64);
91 let rtc_ticks = if rtc_ticks >= u16::MAX as u64 { 104 let rtc_ticks = if rtc_ticks >= u16::MAX as u64 {
92 u16::MAX - 1 105 u16::MAX - 1
93 } else { 106 } else {
94 rtc_ticks as u16 107 rtc_ticks as u16
95 }; 108 }
96 109 .saturating_sub(1);
97 let duration = Duration::from_ticks(
98 rtc_ticks as u64 * TICK_HZ * (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64) / rtc_hz,
99 );
100 110
101 self.write(false, |regs| { 111 self.write(false, |regs| {
102 regs.cr().modify(|w| w.set_wute(false)); 112 regs.cr().modify(|w| w.set_wute(false));
@@ -104,11 +114,21 @@ impl super::Rtc {
104 while !regs.isr().read().wutwf() {} 114 while !regs.isr().read().wutwf() {}
105 115
106 regs.cr().modify(|w| w.set_wucksel(prescaler.into())); 116 regs.cr().modify(|w| w.set_wucksel(prescaler.into()));
117 regs.wutr().write(|w| w.set_wut(rtc_ticks));
107 regs.cr().modify(|w| w.set_wute(true)); 118 regs.cr().modify(|w| w.set_wute(true));
108 regs.cr().modify(|w| w.set_wutie(true)); 119 regs.cr().modify(|w| w.set_wutie(true));
109 }); 120 });
110 121
111 trace!("rtc: start wakeup alarm for {} ms", duration.as_millis()); 122 trace!(
123 "rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}",
124 Duration::from_ticks(
125 rtc_ticks as u64 * TICK_HZ * (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64) / rtc_hz,
126 )
127 .as_millis(),
128 <WakeupPrescaler as Into<u32>>::into(prescaler),
129 rtc_ticks,
130 self.instant(),
131 );
112 132
113 critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none())) 133 critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none()))
114 } 134 }
@@ -119,7 +139,10 @@ impl super::Rtc {
119 pub(crate) fn stop_wakeup_alarm(&self) -> Option<embassy_time::Duration> { 139 pub(crate) fn stop_wakeup_alarm(&self) -> Option<embassy_time::Duration> {
120 use crate::interrupt::typelevel::Interrupt; 140 use crate::interrupt::typelevel::Interrupt;
121 141
122 trace!("rtc: stop wakeup alarm..."); 142 trace!("rtc: stop wakeup alarm at {}", self.instant());
143
144 #[cfg(feature = "rtc-debug")]
145 return None;
123 146
124 self.write(false, |regs| { 147 self.write(false, |regs| {
125 regs.cr().modify(|w| w.set_wutie(false)); 148 regs.cr().modify(|w| w.set_wutie(false));