aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/time_driver.rs
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-09-22 00:36:21 +0000
committerGitHub <[email protected]>2023-09-22 00:36:21 +0000
commitf1488864ebee3daebdc2cc6ed3ccdf7014fa67b2 (patch)
treec2ab9527d56f0541fa8e7b91cc7b5e001116adce /embassy-stm32/src/time_driver.rs
parent02b05231992af4fec3c92d0cc6ce99ae6508bc41 (diff)
parent7cf327130e97f2569e1be73054a778ba5bf39d5b (diff)
Merge pull request #1937 from xoviat/low-power
stm32/low-power: create one critical-section for all time ops
Diffstat (limited to 'embassy-stm32/src/time_driver.rs')
-rw-r--r--embassy-stm32/src/time_driver.rs104
1 files changed, 54 insertions, 50 deletions
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 887e54f65..5b01937f5 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -266,32 +266,28 @@ impl RtcDriver {
266 f(alarm.ctx.get()); 266 f(alarm.ctx.get());
267 } 267 }
268 268
269 #[cfg(feature = "low-power")] 269 /*
270 /// Set the rtc but panic if it's already been set 270 Low-power private functions: all operate within a critical seciton
271 pub(crate) fn set_rtc(&self, rtc: &'static Rtc) { 271 */
272 critical_section::with(|cs| assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none()));
273 }
274 272
275 #[cfg(feature = "low-power")] 273 #[cfg(feature = "low-power")]
276 /// Compute the approximate amount of time until the next alarm 274 /// Compute the approximate amount of time until the next alarm
277 fn time_until_next_alarm(&self) -> embassy_time::Duration { 275 fn time_until_next_alarm(&self, cs: CriticalSection) -> embassy_time::Duration {
278 critical_section::with(|cs| { 276 let now = self.now() + 32;
279 let now = self.now() + 32; 277
280 278 embassy_time::Duration::from_ticks(
281 embassy_time::Duration::from_ticks( 279 self.alarms
282 self.alarms 280 .borrow(cs)
283 .borrow(cs) 281 .iter()
284 .iter() 282 .map(|alarm: &AlarmState| alarm.timestamp.get().saturating_sub(now))
285 .map(|alarm: &AlarmState| alarm.timestamp.get().saturating_sub(now)) 283 .min()
286 .min() 284 .unwrap_or(u64::MAX),
287 .unwrap_or(u64::MAX), 285 )
288 )
289 })
290 } 286 }
291 287
292 #[cfg(feature = "low-power")] 288 #[cfg(feature = "low-power")]
293 /// Add the given offset to the current time 289 /// Add the given offset to the current time
294 fn add_time(&self, offset: embassy_time::Duration) { 290 fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) {
295 let offset = offset.as_ticks(); 291 let offset = offset.as_ticks();
296 let cnt = T::regs_gp16().cnt().read().cnt() as u32; 292 let cnt = T::regs_gp16().cnt().read().cnt() as u32;
297 let period = self.period.load(Ordering::SeqCst); 293 let period = self.period.load(Ordering::SeqCst);
@@ -322,51 +318,57 @@ impl RtcDriver {
322 T::regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16)); 318 T::regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16));
323 319
324 // Now, recompute all alarms 320 // Now, recompute all alarms
325 critical_section::with(|cs| { 321 for i in 0..ALARM_COUNT {
326 for i in 0..ALARM_COUNT { 322 let alarm_handle = unsafe { AlarmHandle::new(i as u8) };
327 let alarm_handle = unsafe { AlarmHandle::new(i as u8) }; 323 let alarm = self.get_alarm(cs, alarm_handle);
328 let alarm = self.get_alarm(cs, alarm_handle);
329 324
330 self.set_alarm(alarm_handle, alarm.timestamp.get()); 325 self.set_alarm(alarm_handle, alarm.timestamp.get());
331 } 326 }
332 })
333 } 327 }
334 328
335 #[cfg(feature = "low-power")] 329 #[cfg(feature = "low-power")]
336 /// Stop the wakeup alarm, if enabled, and add the appropriate offset 330 /// Stop the wakeup alarm, if enabled, and add the appropriate offset
337 fn stop_wakeup_alarm(&self) { 331 fn stop_wakeup_alarm(&self, cs: CriticalSection) {
338 critical_section::with(|cs| { 332 if let Some(offset) = self.rtc.borrow(cs).get().unwrap().stop_wakeup_alarm(cs) {
339 if let Some(offset) = self.rtc.borrow(cs).get().unwrap().stop_wakeup_alarm() { 333 self.add_time(offset, cs);
340 self.add_time(offset); 334 }
341 } 335 }
342 }); 336
337 /*
338 Low-power public functions: all create a critical section
339 */
340 #[cfg(feature = "low-power")]
341 /// Set the rtc but panic if it's already been set
342 pub(crate) fn set_rtc(&self, rtc: &'static Rtc) {
343 critical_section::with(|cs| assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none()));
343 } 344 }
344 345
345 #[cfg(feature = "low-power")] 346 #[cfg(feature = "low-power")]
346 /// Pause the timer if ready; return err if not 347 /// Pause the timer if ready; return err if not
347 pub(crate) fn pause_time(&self) -> Result<(), ()> { 348 pub(crate) fn pause_time(&self) -> Result<(), ()> {
348 /* 349 critical_section::with(|cs| {
349 If the wakeup timer is currently running, then we need to stop it and 350 /*
350 add the elapsed time to the current time 351 If the wakeup timer is currently running, then we need to stop it and
351 */ 352 add the elapsed time to the current time, as this will impact the result
352 self.stop_wakeup_alarm(); 353 of `time_until_next_alarm`.
353 354 */
354 let time_until_next_alarm = self.time_until_next_alarm(); 355 self.stop_wakeup_alarm(cs);
355 if time_until_next_alarm < embassy_time::Duration::from_millis(250) { 356
356 Err(()) 357 let time_until_next_alarm = self.time_until_next_alarm(cs);
357 } else { 358 if time_until_next_alarm < embassy_time::Duration::from_millis(250) {
358 critical_section::with(|cs| { 359 Err(())
360 } else {
359 self.rtc 361 self.rtc
360 .borrow(cs) 362 .borrow(cs)
361 .get() 363 .get()
362 .unwrap() 364 .unwrap()
363 .start_wakeup_alarm(time_until_next_alarm); 365 .start_wakeup_alarm(time_until_next_alarm, cs);
364 });
365 366
366 T::regs_gp16().cr1().modify(|w| w.set_cen(false)); 367 T::regs_gp16().cr1().modify(|w| w.set_cen(false));
367 368
368 Ok(()) 369 Ok(())
369 } 370 }
371 })
370 } 372 }
371 373
372 #[cfg(feature = "low-power")] 374 #[cfg(feature = "low-power")]
@@ -378,9 +380,11 @@ impl RtcDriver {
378 return; 380 return;
379 } 381 }
380 382
381 self.stop_wakeup_alarm(); 383 critical_section::with(|cs| {
384 self.stop_wakeup_alarm(cs);
382 385
383 T::regs_gp16().cr1().modify(|w| w.set_cen(true)); 386 T::regs_gp16().cr1().modify(|w| w.set_cen(true));
387 })
384 } 388 }
385} 389}
386 390