diff options
Diffstat (limited to 'embassy-stm32/src/time_driver.rs')
| -rw-r--r-- | embassy-stm32/src/time_driver.rs | 104 |
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 | ||
