aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/rtc
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-05-30 13:26:14 +0200
committerDario Nieuwenhuis <[email protected]>2024-05-30 13:26:14 +0200
commit2c691baadd28f0072c606a843ba14db1ea08ef86 (patch)
tree3a44ea990b8f9690bcd505a787023d533eb70d9b /embassy-stm32/src/rtc
parentc46172acac0be14b99148c2ec7aa38c9ac605fe1 (diff)
stm32/rtc: move lowpower stuff to a separate mod.
Diffstat (limited to 'embassy-stm32/src/rtc')
-rw-r--r--embassy-stm32/src/rtc/datetime.rs59
-rw-r--r--embassy-stm32/src/rtc/low_power.rs230
-rw-r--r--embassy-stm32/src/rtc/mod.rs196
3 files changed, 236 insertions, 249 deletions
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs
index 77d89293d..32732e96e 100644
--- a/embassy-stm32/src/rtc/datetime.rs
+++ b/embassy-stm32/src/rtc/datetime.rs
@@ -1,65 +1,6 @@
1#[cfg(feature = "chrono")] 1#[cfg(feature = "chrono")]
2use chrono::{Datelike, NaiveDate, Timelike, Weekday}; 2use chrono::{Datelike, NaiveDate, Timelike, Weekday};
3 3
4#[cfg(any(feature = "defmt", feature = "time"))]
5use crate::peripherals::RTC;
6#[cfg(any(feature = "defmt", feature = "time"))]
7use crate::rtc::SealedInstance;
8
9/// Represents an instant in time that can be substracted to compute a duration
10pub struct RtcInstant {
11 /// 0..59
12 pub second: u8,
13 /// 0..256
14 pub subsecond: u16,
15}
16
17impl RtcInstant {
18 #[cfg(not(rtc_v2f2))]
19 pub(super) const fn from(second: u8, subsecond: u16) -> Result<Self, Error> {
20 if second > 59 {
21 Err(Error::InvalidSecond)
22 } else {
23 Ok(Self { second, subsecond })
24 }
25 }
26}
27
28#[cfg(feature = "defmt")]
29impl defmt::Format for RtcInstant {
30 fn format(&self, fmt: defmt::Formatter) {
31 defmt::write!(
32 fmt,
33 "{}:{}",
34 self.second,
35 RTC::regs().prer().read().prediv_s() - self.subsecond,
36 )
37 }
38}
39
40#[cfg(feature = "time")]
41impl core::ops::Sub for RtcInstant {
42 type Output = embassy_time::Duration;
43
44 fn sub(self, rhs: Self) -> Self::Output {
45 use embassy_time::{Duration, TICK_HZ};
46
47 let second = if self.second < rhs.second {
48 self.second + 60
49 } else {
50 self.second
51 };
52
53 let psc = RTC::regs().prer().read().prediv_s() as u32;
54
55 let self_ticks = second as u32 * (psc + 1) + (psc - self.subsecond as u32);
56 let other_ticks = rhs.second as u32 * (psc + 1) + (psc - rhs.subsecond as u32);
57 let rtc_ticks = self_ticks - other_ticks;
58
59 Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / (psc + 1)) as u64)
60 }
61}
62
63/// Errors regarding the [`DateTime`] struct. 4/// Errors regarding the [`DateTime`] struct.
64#[derive(Clone, Debug, PartialEq, Eq)] 5#[derive(Clone, Debug, PartialEq, Eq)]
65pub enum Error { 6pub enum Error {
diff --git a/embassy-stm32/src/rtc/low_power.rs b/embassy-stm32/src/rtc/low_power.rs
new file mode 100644
index 000000000..a4ff1acbc
--- /dev/null
+++ b/embassy-stm32/src/rtc/low_power.rs
@@ -0,0 +1,230 @@
1use super::{bcd2_to_byte, DateTimeError, Rtc, RtcError};
2use crate::peripherals::RTC;
3use crate::rtc::SealedInstance;
4
5/// Represents an instant in time that can be substracted to compute a duration
6pub(super) struct RtcInstant {
7 /// 0..59
8 second: u8,
9 /// 0..256
10 subsecond: u16,
11}
12
13impl RtcInstant {
14 #[cfg(not(rtc_v2f2))]
15 const fn from(second: u8, subsecond: u16) -> Result<Self, DateTimeError> {
16 if second > 59 {
17 Err(DateTimeError::InvalidSecond)
18 } else {
19 Ok(Self { second, subsecond })
20 }
21 }
22}
23
24#[cfg(feature = "defmt")]
25impl defmt::Format for RtcInstant {
26 fn format(&self, fmt: defmt::Formatter) {
27 defmt::write!(
28 fmt,
29 "{}:{}",
30 self.second,
31 RTC::regs().prer().read().prediv_s() - self.subsecond,
32 )
33 }
34}
35
36#[cfg(feature = "time")]
37impl core::ops::Sub for RtcInstant {
38 type Output = embassy_time::Duration;
39
40 fn sub(self, rhs: Self) -> Self::Output {
41 use embassy_time::{Duration, TICK_HZ};
42
43 let second = if self.second < rhs.second {
44 self.second + 60
45 } else {
46 self.second
47 };
48
49 let psc = RTC::regs().prer().read().prediv_s() as u32;
50
51 let self_ticks = second as u32 * (psc + 1) + (psc - self.subsecond as u32);
52 let other_ticks = rhs.second as u32 * (psc + 1) + (psc - rhs.subsecond as u32);
53 let rtc_ticks = self_ticks - other_ticks;
54
55 Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / (psc + 1)) as u64)
56 }
57}
58
59#[repr(u8)]
60#[derive(Clone, Copy, Debug)]
61pub(crate) enum WakeupPrescaler {
62 Div2 = 2,
63 Div4 = 4,
64 Div8 = 8,
65 Div16 = 16,
66}
67
68#[cfg(any(stm32f4, stm32l0, stm32g4, stm32l5, stm32wb, stm32h5, stm32g0))]
69impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
70 fn from(val: WakeupPrescaler) -> Self {
71 use crate::pac::rtc::vals::Wucksel;
72
73 match val {
74 WakeupPrescaler::Div2 => Wucksel::DIV2,
75 WakeupPrescaler::Div4 => Wucksel::DIV4,
76 WakeupPrescaler::Div8 => Wucksel::DIV8,
77 WakeupPrescaler::Div16 => Wucksel::DIV16,
78 }
79 }
80}
81
82#[cfg(any(stm32f4, stm32l0, stm32g4, stm32l5, stm32wb, stm32h5, stm32g0))]
83impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
84 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self {
85 use crate::pac::rtc::vals::Wucksel;
86
87 match val {
88 Wucksel::DIV2 => WakeupPrescaler::Div2,
89 Wucksel::DIV4 => WakeupPrescaler::Div4,
90 Wucksel::DIV8 => WakeupPrescaler::Div8,
91 Wucksel::DIV16 => WakeupPrescaler::Div16,
92 _ => unreachable!(),
93 }
94 }
95}
96
97impl WakeupPrescaler {
98 pub fn compute_min(val: u32) -> Self {
99 *[
100 WakeupPrescaler::Div2,
101 WakeupPrescaler::Div4,
102 WakeupPrescaler::Div8,
103 WakeupPrescaler::Div16,
104 ]
105 .iter()
106 .find(|psc| **psc as u32 > val)
107 .unwrap_or(&WakeupPrescaler::Div16)
108 }
109}
110
111impl Rtc {
112 /// Return the current instant.
113 fn instant(&self) -> Result<RtcInstant, RtcError> {
114 self.time_provider().read(|_, tr, ss| {
115 let second = bcd2_to_byte((tr.st(), tr.su()));
116
117 RtcInstant::from(second, ss).map_err(RtcError::InvalidDateTime)
118 })
119 }
120
121 /// start the wakeup alarm and with a duration that is as close to but less than
122 /// the requested duration, and record the instant the wakeup alarm was started
123 pub(crate) fn start_wakeup_alarm(
124 &self,
125 requested_duration: embassy_time::Duration,
126 cs: critical_section::CriticalSection,
127 ) {
128 use embassy_time::{Duration, TICK_HZ};
129
130 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
131 use crate::pac::rtc::vals::Calrf;
132
133 // Panic if the rcc mod knows we're not using low-power rtc
134 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
135 unsafe { crate::rcc::get_freqs() }.rtc.unwrap();
136
137 let requested_duration = requested_duration.as_ticks().clamp(0, u32::MAX as u64);
138 let rtc_hz = Self::frequency().0 as u64;
139 let rtc_ticks = requested_duration * rtc_hz / TICK_HZ;
140 let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32);
141
142 // adjust the rtc ticks to the prescaler and subtract one rtc tick
143 let rtc_ticks = rtc_ticks / prescaler as u64;
144 let rtc_ticks = rtc_ticks.clamp(0, (u16::MAX - 1) as u64).saturating_sub(1) as u16;
145
146 self.write(false, |regs| {
147 regs.cr().modify(|w| w.set_wute(false));
148
149 #[cfg(any(
150 rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb
151 ))]
152 {
153 regs.isr().modify(|w| w.set_wutf(false));
154 while !regs.isr().read().wutwf() {}
155 }
156
157 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
158 {
159 regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR));
160 while !regs.icsr().read().wutwf() {}
161 }
162
163 regs.cr().modify(|w| w.set_wucksel(prescaler.into()));
164 regs.wutr().write(|w| w.set_wut(rtc_ticks));
165 regs.cr().modify(|w| w.set_wute(true));
166 regs.cr().modify(|w| w.set_wutie(true));
167 });
168
169 let instant = self.instant().unwrap();
170 trace!(
171 "rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}",
172 Duration::from_ticks(rtc_ticks as u64 * TICK_HZ * prescaler as u64 / rtc_hz).as_millis(),
173 prescaler as u32,
174 rtc_ticks,
175 instant,
176 );
177
178 assert!(self.stop_time.borrow(cs).replace(Some(instant)).is_none())
179 }
180
181 /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm`
182 /// was called, otherwise none
183 pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> {
184 use crate::interrupt::typelevel::Interrupt;
185 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
186 use crate::pac::rtc::vals::Calrf;
187
188 let instant = self.instant().unwrap();
189 if RTC::regs().cr().read().wute() {
190 trace!("rtc: stop wakeup alarm at {}", instant);
191
192 self.write(false, |regs| {
193 regs.cr().modify(|w| w.set_wutie(false));
194 regs.cr().modify(|w| w.set_wute(false));
195
196 #[cfg(any(
197 rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb
198 ))]
199 regs.isr().modify(|w| w.set_wutf(false));
200
201 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
202 regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR));
203
204 // Check RM for EXTI and/or NVIC section, "Event event input mapping" or "EXTI interrupt/event mapping" or something similar,
205 // there is a table for every "Event input" / "EXTI Line".
206 // If you find the EXTI line related to "RTC wakeup" marks as "Configurable" (not "Direct"),
207 // then write 1 to related field of Pending Register, to clean it's pending state.
208 #[cfg(any(exti_v1, stm32h7, stm32wb))]
209 crate::pac::EXTI
210 .pr(0)
211 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
212
213 <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
214 });
215 }
216
217 self.stop_time.borrow(cs).take().map(|stop_time| instant - stop_time)
218 }
219
220 pub(crate) fn enable_wakeup_line(&self) {
221 use crate::interrupt::typelevel::Interrupt;
222 use crate::pac::EXTI;
223
224 <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
225 unsafe { <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::enable() };
226
227 EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
228 EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
229 }
230}
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 92a58ee9a..cb9c10676 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -2,6 +2,9 @@
2mod datetime; 2mod datetime;
3 3
4#[cfg(feature = "low-power")] 4#[cfg(feature = "low-power")]
5mod low_power;
6
7#[cfg(feature = "low-power")]
5use core::cell::Cell; 8use core::cell::Cell;
6 9
7#[cfg(feature = "low-power")] 10#[cfg(feature = "low-power")]
@@ -9,8 +12,6 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
9#[cfg(feature = "low-power")] 12#[cfg(feature = "low-power")]
10use embassy_sync::blocking_mutex::Mutex; 13use embassy_sync::blocking_mutex::Mutex;
11 14
12#[cfg(not(rtc_v2f2))]
13use self::datetime::RtcInstant;
14use self::datetime::{day_of_week_from_u8, day_of_week_to_u8}; 15use self::datetime::{day_of_week_from_u8, day_of_week_to_u8};
15pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; 16pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
16use crate::pac::rtc::regs::{Dr, Tr}; 17use crate::pac::rtc::regs::{Dr, Tr};
@@ -32,60 +33,6 @@ use embassy_hal_internal::Peripheral;
32 33
33use crate::peripherals::RTC; 34use crate::peripherals::RTC;
34 35
35#[allow(dead_code)]
36#[repr(u8)]
37#[derive(Clone, Copy, Debug)]
38pub(crate) enum WakeupPrescaler {
39 Div2 = 2,
40 Div4 = 4,
41 Div8 = 8,
42 Div16 = 16,
43}
44
45#[cfg(any(stm32f4, stm32l0, stm32g4, stm32l5, stm32wb, stm32h5, stm32g0))]
46impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
47 fn from(val: WakeupPrescaler) -> Self {
48 use crate::pac::rtc::vals::Wucksel;
49
50 match val {
51 WakeupPrescaler::Div2 => Wucksel::DIV2,
52 WakeupPrescaler::Div4 => Wucksel::DIV4,
53 WakeupPrescaler::Div8 => Wucksel::DIV8,
54 WakeupPrescaler::Div16 => Wucksel::DIV16,
55 }
56 }
57}
58
59#[cfg(any(stm32f4, stm32l0, stm32g4, stm32l5, stm32wb, stm32h5, stm32g0))]
60impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
61 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self {
62 use crate::pac::rtc::vals::Wucksel;
63
64 match val {
65 Wucksel::DIV2 => WakeupPrescaler::Div2,
66 Wucksel::DIV4 => WakeupPrescaler::Div4,
67 Wucksel::DIV8 => WakeupPrescaler::Div8,
68 Wucksel::DIV16 => WakeupPrescaler::Div16,
69 _ => unreachable!(),
70 }
71 }
72}
73
74#[cfg(feature = "low-power")]
75impl WakeupPrescaler {
76 pub fn compute_min(val: u32) -> Self {
77 *[
78 WakeupPrescaler::Div2,
79 WakeupPrescaler::Div4,
80 WakeupPrescaler::Div8,
81 WakeupPrescaler::Div16,
82 ]
83 .iter()
84 .find(|psc| **psc as u32 > val)
85 .unwrap_or(&WakeupPrescaler::Div16)
86 }
87}
88
89/// Errors that can occur on methods on [RtcClock] 36/// Errors that can occur on methods on [RtcClock]
90#[non_exhaustive] 37#[non_exhaustive]
91#[derive(Clone, Debug, PartialEq, Eq)] 38#[derive(Clone, Debug, PartialEq, Eq)]
@@ -106,15 +53,6 @@ pub struct RtcTimeProvider {
106} 53}
107 54
108impl RtcTimeProvider { 55impl RtcTimeProvider {
109 #[cfg(not(rtc_v2f2))]
110 pub(crate) fn instant(&self) -> Result<RtcInstant, RtcError> {
111 self.read(|_, tr, ss| {
112 let second = bcd2_to_byte((tr.st(), tr.su()));
113
114 RtcInstant::from(second, ss).map_err(RtcError::InvalidDateTime)
115 })
116 }
117
118 /// Return the current datetime. 56 /// Return the current datetime.
119 /// 57 ///
120 /// # Errors 58 /// # Errors
@@ -165,8 +103,7 @@ impl RtcTimeProvider {
165/// RTC driver. 103/// RTC driver.
166pub struct Rtc { 104pub struct Rtc {
167 #[cfg(feature = "low-power")] 105 #[cfg(feature = "low-power")]
168 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>, 106 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<low_power::RtcInstant>>>,
169 #[cfg(not(feature = "low-power"))]
170 _private: (), 107 _private: (),
171} 108}
172 109
@@ -210,7 +147,6 @@ impl Rtc {
210 let mut this = Self { 147 let mut this = Self {
211 #[cfg(feature = "low-power")] 148 #[cfg(feature = "low-power")]
212 stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), 149 stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)),
213 #[cfg(not(feature = "low-power"))]
214 _private: (), 150 _private: (),
215 }; 151 };
216 152
@@ -223,9 +159,8 @@ impl Rtc {
223 // Wait for the clock to update after initialization 159 // Wait for the clock to update after initialization
224 #[cfg(not(rtc_v2f2))] 160 #[cfg(not(rtc_v2f2))]
225 { 161 {
226 let now = this.instant().unwrap(); 162 let now = this.time_provider().read(|_, _, ss| Ok(ss)).unwrap();
227 163 while now == this.time_provider().read(|_, _, ss| Ok(ss)).unwrap() {}
228 while this.instant().unwrap().subsecond == now.subsecond {}
229 } 164 }
230 165
231 this 166 this
@@ -284,12 +219,6 @@ impl Rtc {
284 Ok(()) 219 Ok(())
285 } 220 }
286 221
287 #[cfg(not(rtc_v2f2))]
288 /// Return the current instant.
289 fn instant(&self) -> Result<RtcInstant, RtcError> {
290 self.time_provider().instant()
291 }
292
293 /// Return the current datetime. 222 /// Return the current datetime.
294 /// 223 ///
295 /// # Errors 224 /// # Errors
@@ -330,119 +259,6 @@ impl Rtc {
330 pub fn write_backup_register(&self, register: usize, value: u32) { 259 pub fn write_backup_register(&self, register: usize, value: u32) {
331 RTC::write_backup_register(RTC::regs(), register, value) 260 RTC::write_backup_register(RTC::regs(), register, value)
332 } 261 }
333
334 #[cfg(feature = "low-power")]
335 /// start the wakeup alarm and with a duration that is as close to but less than
336 /// the requested duration, and record the instant the wakeup alarm was started
337 pub(crate) fn start_wakeup_alarm(
338 &self,
339 requested_duration: embassy_time::Duration,
340 cs: critical_section::CriticalSection,
341 ) {
342 use embassy_time::{Duration, TICK_HZ};
343
344 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
345 use crate::pac::rtc::vals::Calrf;
346
347 // Panic if the rcc mod knows we're not using low-power rtc
348 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
349 unsafe { crate::rcc::get_freqs() }.rtc.unwrap();
350
351 let requested_duration = requested_duration.as_ticks().clamp(0, u32::MAX as u64);
352 let rtc_hz = Self::frequency().0 as u64;
353 let rtc_ticks = requested_duration * rtc_hz / TICK_HZ;
354 let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32);
355
356 // adjust the rtc ticks to the prescaler and subtract one rtc tick
357 let rtc_ticks = rtc_ticks / prescaler as u64;
358 let rtc_ticks = rtc_ticks.clamp(0, (u16::MAX - 1) as u64).saturating_sub(1) as u16;
359
360 self.write(false, |regs| {
361 regs.cr().modify(|w| w.set_wute(false));
362
363 #[cfg(any(
364 rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb
365 ))]
366 {
367 regs.isr().modify(|w| w.set_wutf(false));
368 while !regs.isr().read().wutwf() {}
369 }
370
371 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
372 {
373 regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR));
374 while !regs.icsr().read().wutwf() {}
375 }
376
377 regs.cr().modify(|w| w.set_wucksel(prescaler.into()));
378 regs.wutr().write(|w| w.set_wut(rtc_ticks));
379 regs.cr().modify(|w| w.set_wute(true));
380 regs.cr().modify(|w| w.set_wutie(true));
381 });
382
383 let instant = self.instant().unwrap();
384 trace!(
385 "rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}",
386 Duration::from_ticks(rtc_ticks as u64 * TICK_HZ * prescaler as u64 / rtc_hz).as_millis(),
387 prescaler as u32,
388 rtc_ticks,
389 instant,
390 );
391
392 assert!(self.stop_time.borrow(cs).replace(Some(instant)).is_none())
393 }
394
395 #[cfg(feature = "low-power")]
396 /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm`
397 /// was called, otherwise none
398 pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> {
399 use crate::interrupt::typelevel::Interrupt;
400 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
401 use crate::pac::rtc::vals::Calrf;
402
403 let instant = self.instant().unwrap();
404 if RTC::regs().cr().read().wute() {
405 trace!("rtc: stop wakeup alarm at {}", instant);
406
407 self.write(false, |regs| {
408 regs.cr().modify(|w| w.set_wutie(false));
409 regs.cr().modify(|w| w.set_wute(false));
410
411 #[cfg(any(
412 rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb
413 ))]
414 regs.isr().modify(|w| w.set_wutf(false));
415
416 #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
417 regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR));
418
419 // Check RM for EXTI and/or NVIC section, "Event event input mapping" or "EXTI interrupt/event mapping" or something similar,
420 // there is a table for every "Event input" / "EXTI Line".
421 // If you find the EXTI line related to "RTC wakeup" marks as "Configurable" (not "Direct"),
422 // then write 1 to related field of Pending Register, to clean it's pending state.
423 #[cfg(any(exti_v1, stm32h7, stm32wb))]
424 crate::pac::EXTI
425 .pr(0)
426 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
427
428 <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
429 });
430 }
431
432 self.stop_time.borrow(cs).take().map(|stop_time| instant - stop_time)
433 }
434
435 #[cfg(feature = "low-power")]
436 pub(crate) fn enable_wakeup_line(&self) {
437 use crate::interrupt::typelevel::Interrupt;
438 use crate::pac::EXTI;
439
440 <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
441 unsafe { <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::enable() };
442
443 EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
444 EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
445 }
446} 262}
447 263
448pub(crate) fn byte_to_bcd2(byte: u8) -> (u8, u8) { 264pub(crate) fn byte_to_bcd2(byte: u8) -> (u8, u8) {