aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/rtc/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/rtc/mod.rs')
-rw-r--r--embassy-stm32/src/rtc/mod.rs121
1 files changed, 99 insertions, 22 deletions
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 92dec0960..e88bd7ab2 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -5,15 +5,19 @@ mod datetime;
5mod low_power; 5mod low_power;
6 6
7#[cfg(feature = "low-power")] 7#[cfg(feature = "low-power")]
8use core::cell::Cell; 8use core::cell::{Cell, RefCell, RefMut};
9#[cfg(feature = "low-power")]
10use core::ops;
9 11
10#[cfg(feature = "low-power")] 12#[cfg(feature = "low-power")]
11use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 13use critical_section::CriticalSection;
12#[cfg(feature = "low-power")] 14#[cfg(feature = "low-power")]
13use embassy_sync::blocking_mutex::Mutex; 15use embassy_sync::blocking_mutex::Mutex;
16#[cfg(feature = "low-power")]
17use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
14 18
15use self::datetime::{day_of_week_from_u8, day_of_week_to_u8};
16pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; 19pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
20use self::datetime::{day_of_week_from_u8, day_of_week_to_u8};
17use crate::pac::rtc::regs::{Dr, Tr}; 21use crate::pac::rtc::regs::{Dr, Tr};
18use crate::time::Hertz; 22use crate::time::Hertz;
19 23
@@ -25,8 +29,8 @@ mod _version;
25#[allow(unused_imports)] 29#[allow(unused_imports)]
26pub use _version::*; 30pub use _version::*;
27 31
28use crate::peripherals::RTC;
29use crate::Peri; 32use crate::Peri;
33use crate::peripherals::RTC;
30 34
31/// Errors that can occur on methods on [RtcClock] 35/// Errors that can occur on methods on [RtcClock]
32#[non_exhaustive] 36#[non_exhaustive]
@@ -44,11 +48,17 @@ pub enum RtcError {
44} 48}
45 49
46/// Provides immutable access to the current time of the RTC. 50/// Provides immutable access to the current time of the RTC.
51#[derive(Clone)]
47pub struct RtcTimeProvider { 52pub struct RtcTimeProvider {
48 _private: (), 53 _private: (),
49} 54}
50 55
51impl RtcTimeProvider { 56impl RtcTimeProvider {
57 /// Create a new RTC time provider instance.
58 pub(self) const fn new() -> Self {
59 Self { _private: () }
60 }
61
52 /// Return the current datetime. 62 /// Return the current datetime.
53 /// 63 ///
54 /// # Errors 64 /// # Errors
@@ -106,6 +116,50 @@ impl RtcTimeProvider {
106 } 116 }
107} 117}
108 118
119#[cfg(feature = "low-power")]
120/// Contains an RTC driver.
121pub struct RtcContainer {
122 pub(self) mutex: &'static Mutex<CriticalSectionRawMutex, RefCell<Option<Rtc>>>,
123}
124
125#[cfg(feature = "low-power")]
126impl RtcContainer {
127 pub(self) const fn new() -> Self {
128 Self {
129 mutex: &crate::time_driver::get_driver().rtc,
130 }
131 }
132
133 /// Acquire an RTC borrow.
134 pub fn borrow_mut<'a>(&self, cs: CriticalSection<'a>) -> RtcBorrow<'a> {
135 RtcBorrow {
136 ref_mut: self.mutex.borrow(cs).borrow_mut(),
137 }
138 }
139}
140
141#[cfg(feature = "low-power")]
142/// Contains an RTC borrow.
143pub struct RtcBorrow<'a> {
144 pub(self) ref_mut: RefMut<'a, Option<Rtc>>,
145}
146
147#[cfg(feature = "low-power")]
148impl<'a> ops::Deref for RtcBorrow<'a> {
149 type Target = Rtc;
150
151 fn deref(&self) -> &Self::Target {
152 self.ref_mut.as_ref().unwrap()
153 }
154}
155
156#[cfg(feature = "low-power")]
157impl<'a> ops::DerefMut for RtcBorrow<'a> {
158 fn deref_mut(&mut self) -> &mut Self::Target {
159 self.ref_mut.as_mut().unwrap()
160 }
161}
162
109/// RTC driver. 163/// RTC driver.
110pub struct Rtc { 164pub struct Rtc {
111 #[cfg(feature = "low-power")] 165 #[cfg(feature = "low-power")]
@@ -121,13 +175,21 @@ pub struct RtcConfig {
121 /// 175 ///
122 /// A high counter frequency may impact stop power consumption 176 /// A high counter frequency may impact stop power consumption
123 pub frequency: Hertz, 177 pub frequency: Hertz,
178
179 #[cfg(feature = "_allow-disable-rtc")]
180 /// Allow disabling the rtc, even when stop is configured
181 pub _disable_rtc: bool,
124} 182}
125 183
126impl Default for RtcConfig { 184impl Default for RtcConfig {
127 /// LSI with prescalers assuming 32.768 kHz. 185 /// LSI with prescalers assuming 32.768 kHz.
128 /// Raw sub-seconds in 1/256. 186 /// Raw sub-seconds in 1/256.
129 fn default() -> Self { 187 fn default() -> Self {
130 RtcConfig { frequency: Hertz(256) } 188 RtcConfig {
189 frequency: Hertz(256),
190 #[cfg(feature = "_allow-disable-rtc")]
191 _disable_rtc: false,
192 }
131 } 193 }
132} 194}
133 195
@@ -145,8 +207,19 @@ pub enum RtcCalibrationCyclePeriod {
145} 207}
146 208
147impl Rtc { 209impl Rtc {
210 #[cfg(not(feature = "low-power"))]
148 /// Create a new RTC instance. 211 /// Create a new RTC instance.
149 pub fn new(_rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> Self { 212 pub fn new(_rtc: Peri<'static, RTC>, rtc_config: RtcConfig) -> (Self, RtcTimeProvider) {
213 (Self::new_inner(rtc_config), RtcTimeProvider::new())
214 }
215
216 #[cfg(feature = "low-power")]
217 /// Create a new RTC instance.
218 pub fn new(_rtc: Peri<'static, RTC>) -> (RtcContainer, RtcTimeProvider) {
219 (RtcContainer::new(), RtcTimeProvider::new())
220 }
221
222 pub(self) fn new_inner(rtc_config: RtcConfig) -> Self {
150 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] 223 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
151 crate::rcc::enable_and_reset::<RTC>(); 224 crate::rcc::enable_and_reset::<RTC>();
152 225
@@ -165,10 +238,13 @@ impl Rtc {
165 // Wait for the clock to update after initialization 238 // Wait for the clock to update after initialization
166 #[cfg(not(rtc_v2_f2))] 239 #[cfg(not(rtc_v2_f2))]
167 { 240 {
168 let now = this.time_provider().read(|_, _, ss| Ok(ss)).unwrap(); 241 let now = RtcTimeProvider::new().read(|_, _, ss| Ok(ss)).unwrap();
169 while now == this.time_provider().read(|_, _, ss| Ok(ss)).unwrap() {} 242 while now == RtcTimeProvider::new().read(|_, _, ss| Ok(ss)).unwrap() {}
170 } 243 }
171 244
245 #[cfg(feature = "low-power")]
246 this.enable_wakeup_line();
247
172 this 248 this
173 } 249 }
174 250
@@ -177,11 +253,6 @@ impl Rtc {
177 freqs.rtc.to_hertz().unwrap() 253 freqs.rtc.to_hertz().unwrap()
178 } 254 }
179 255
180 /// Acquire a [`RtcTimeProvider`] instance.
181 pub const fn time_provider(&self) -> RtcTimeProvider {
182 RtcTimeProvider { _private: () }
183 }
184
185 /// Set the datetime to a new value. 256 /// Set the datetime to a new value.
186 /// 257 ///
187 /// # Errors 258 /// # Errors
@@ -225,15 +296,6 @@ impl Rtc {
225 Ok(()) 296 Ok(())
226 } 297 }
227 298
228 /// Return the current datetime.
229 ///
230 /// # Errors
231 ///
232 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`].
233 pub fn now(&self) -> Result<DateTime, RtcError> {
234 self.time_provider().now()
235 }
236
237 /// Check if daylight savings time is active. 299 /// Check if daylight savings time is active.
238 pub fn get_daylight_savings(&self) -> bool { 300 pub fn get_daylight_savings(&self) -> bool {
239 let cr = RTC::regs().cr().read(); 301 let cr = RTC::regs().cr().read();
@@ -315,3 +377,18 @@ trait SealedInstance {
315 377
316 // fn apply_config(&mut self, rtc_config: RtcConfig); 378 // fn apply_config(&mut self, rtc_config: RtcConfig);
317} 379}
380
381#[cfg(feature = "low-power")]
382pub(crate) fn init_rtc(cs: CriticalSection, config: RtcConfig, min_stop_pause: embassy_time::Duration) {
383 use crate::time_driver::get_driver;
384
385 #[cfg(feature = "_allow-disable-rtc")]
386 if config._disable_rtc {
387 return;
388 }
389
390 get_driver().set_rtc(cs, Rtc::new_inner(config));
391 get_driver().set_min_stop_pause(cs, min_stop_pause);
392
393 trace!("low power: stop with rtc configured");
394}