aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-08-21 17:44:38 -0500
committerxoviat <[email protected]>2023-08-21 17:44:38 -0500
commitf723982beccc1306a74560e6455f38834ea95689 (patch)
tree728f067be4926bae704c6f2db69b522d248e6cdf
parent3a3f3b492f95ac54b3cae2ea1ba9f61d2ab6496d (diff)
rtc: impl. draft rtcinstant api
-rw-r--r--embassy-stm32/src/rtc/v2.rs123
1 files changed, 97 insertions, 26 deletions
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index 5cd5adef6..ba881e3f3 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -5,6 +5,63 @@ use crate::pac::rtc::Rtc;
5use crate::peripherals::RTC; 5use crate::peripherals::RTC;
6use crate::rtc::sealed::Instance; 6use crate::rtc::sealed::Instance;
7 7
8#[cfg(all(feature = "time", any(stm32wb, stm32f4)))]
9pub struct RtcInstant {
10 ssr: u16,
11 st: u8,
12}
13
14#[cfg(all(feature = "time", any(stm32wb, stm32f4)))]
15impl RtcInstant {
16 pub fn now() -> Self {
17 // TODO: read value twice
18 use crate::rtc::bcd2_to_byte;
19
20 let tr = RTC::regs().tr().read();
21 let ssr = RTC::regs().ssr().read().ss();
22
23 let st = bcd2_to_byte((tr.st(), tr.su()));
24
25 let _ = RTC::regs().dr().read();
26
27 trace!("ssr: {}", ssr);
28 trace!("st: {}", st);
29
30 Self { ssr, st }
31 }
32}
33
34#[cfg(all(feature = "time", any(stm32wb, stm32f4)))]
35impl core::ops::Sub for RtcInstant {
36 type Output = embassy_time::Duration;
37
38 fn sub(self, rhs: Self) -> Self::Output {
39 use embassy_time::{Duration, TICK_HZ};
40
41 trace!("self st: {}", self.st);
42 trace!("other st: {}", rhs.st);
43
44 let st = if self.st < rhs.st { self.st + 60 } else { self.st };
45
46 trace!("self st: {}", st);
47
48 let self_ticks = (st as u32 * 256 + self.ssr as u32);
49 let other_ticks = (rhs.st as u32 * 256 + rhs.ssr as u32);
50 let rtc_ticks = self_ticks - other_ticks;
51
52 trace!("self ticks: {}", self_ticks);
53 trace!("other ticks: {}", other_ticks);
54 trace!("rtc ticks: {}", rtc_ticks);
55
56 // TODO: read prescaler
57
58 Duration::from_ticks(
59 ((((st as u32 * 256 + self.ssr as u32) - (rhs.st as u32 * 256 + rhs.ssr as u32)) * TICK_HZ as u32) as u32
60 / 256u32) as u64,
61 )
62 }
63}
64
8#[derive(Clone, Copy)] 65#[derive(Clone, Copy)]
9pub(crate) enum WakeupPrescaler { 66pub(crate) enum WakeupPrescaler {
10 Div2, 67 Div2,
@@ -13,7 +70,7 @@ pub(crate) enum WakeupPrescaler {
13 Div16, 70 Div16,
14} 71}
15 72
16#[cfg(stm32wb)] 73#[cfg(any(stm32wb, stm32f4))]
17impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { 74impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
18 fn from(val: WakeupPrescaler) -> Self { 75 fn from(val: WakeupPrescaler) -> Self {
19 use crate::pac::rtc::vals::Wucksel; 76 use crate::pac::rtc::vals::Wucksel;
@@ -27,7 +84,7 @@ impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
27 } 84 }
28} 85}
29 86
30#[cfg(stm32wb)] 87#[cfg(any(stm32wb, stm32f4))]
31impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler { 88impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
32 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { 89 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self {
33 use crate::pac::rtc::vals::Wucksel; 90 use crate::pac::rtc::vals::Wucksel;
@@ -86,11 +143,14 @@ impl super::Rtc {
86 } 143 }
87 144
88 #[allow(dead_code)] 145 #[allow(dead_code)]
89 #[cfg(all(feature = "time", stm32wb))] 146 #[cfg(all(feature = "time", any(stm32wb, stm32f4)))]
90 /// start the wakeup alarm and return the actual duration of the alarm 147 /// start the wakeup alarm and return the actual duration of the alarm
91 /// the actual duration will be the closest value possible that is less 148 /// the actual duration will be the closest value possible that is less
92 /// than the requested duration. 149 /// than the requested duration.
93 pub(crate) fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> embassy_time::Duration { 150 ///
151 /// note: this api is exposed for testing purposes until low power is implemented.
152 /// it is not intended to be public
153 pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant {
94 use embassy_time::{Duration, TICK_HZ}; 154 use embassy_time::{Duration, TICK_HZ};
95 155
96 use crate::interrupt::typelevel::Interrupt; 156 use crate::interrupt::typelevel::Interrupt;
@@ -103,8 +163,8 @@ impl super::Rtc {
103 163
104 // adjust the rtc ticks to the prescaler 164 // adjust the rtc ticks to the prescaler
105 let rtc_ticks = rtc_ticks / (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64); 165 let rtc_ticks = rtc_ticks / (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64);
106 let rtc_ticks = if rtc_ticks > u16::MAX as u64 { 166 let rtc_ticks = if rtc_ticks >= u16::MAX as u64 {
107 u16::MAX 167 u16::MAX - 1
108 } else { 168 } else {
109 rtc_ticks as u16 169 rtc_ticks as u16
110 }; 170 };
@@ -113,8 +173,10 @@ impl super::Rtc {
113 rtc_ticks as u64 * TICK_HZ * (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64) / rtc_hz, 173 rtc_ticks as u64 * TICK_HZ * (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64) / rtc_hz,
114 ); 174 );
115 175
116 crate::interrupt::typelevel::RTC_WKUP::unpend(); 176 trace!("set wakeup timer for {} ms", duration.as_millis());
117 unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; 177
178 RTC::regs().wpr().write(|w| w.set_key(0xca));
179 RTC::regs().wpr().write(|w| w.set_key(0x53));
118 180
119 RTC::regs().wutr().modify(|w| w.set_wut(rtc_ticks)); 181 RTC::regs().wutr().modify(|w| w.set_wut(rtc_ticks));
120 182
@@ -125,36 +187,45 @@ impl super::Rtc {
125 w.set_wute(true); 187 w.set_wute(true);
126 }); 188 });
127 189
128 duration 190 if !RTC::regs().cr().read().wute() {
191 trace!("wakeup timer not enabled");
192 } else {
193 trace!("wakeup timer enabled");
194 }
195
196 crate::interrupt::typelevel::RTC_WKUP::unpend();
197 unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() };
198
199 RtcInstant::now()
129 } 200 }
130 201
131 #[allow(dead_code)] 202 #[allow(dead_code)]
132 #[cfg(all(feature = "time", stm32wb))] 203 #[cfg(all(feature = "time", any(stm32wb, stm32f4)))]
133 // stop the wakeup alarm and return the time remaining 204 /// stop the wakeup alarm and return the time remaining
134 pub(crate) fn stop_wakeup_alarm() -> embassy_time::Duration { 205 ///
135 use embassy_time::{Duration, TICK_HZ}; 206 /// note: this api is exposed for testing purposes until low power is implemented.
136 207 /// it is not intended to be public
208 pub fn stop_wakeup_alarm() -> RtcInstant {
137 use crate::interrupt::typelevel::Interrupt; 209 use crate::interrupt::typelevel::Interrupt;
138 use crate::rcc::get_freqs; 210
211 crate::interrupt::typelevel::RTC_WKUP::disable();
212
213 trace!("disable wakeup timer...");
139 214
140 RTC::regs().cr().modify(|w| { 215 RTC::regs().cr().modify(|w| {
141 w.set_wute(false); 216 w.set_wute(false);
142 }); 217 });
143 218
144 // Wait for the wakeup timer to stop 219 trace!("wait for wakeup timer stop...");
145 while !RTC::regs().isr().read().wutf() {}
146
147 RTC::regs().isr().modify(|w| w.set_wutf(false));
148 220
149 crate::interrupt::typelevel::RTC_WKUP::disable(); 221 // Wait for the wakeup timer to stop
222 // while !RTC::regs().isr().read().wutf() {}
223 //
224 // RTC::regs().isr().modify(|w| w.set_wutf(false));
150 225
151 let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; 226 trace!("wait for wakeup timer stop...done");
152 let prescaler: WakeupPrescaler = RTC::regs().cr().read().wucksel().into();
153 let rtc_ticks = RTC::regs().wutr().read().wut();
154 227
155 Duration::from_ticks( 228 RtcInstant::now()
156 rtc_ticks as u64 * TICK_HZ * (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64) / rtc_hz,
157 )
158 } 229 }
159 230
160 #[allow(dead_code)] 231 #[allow(dead_code)]