diff options
| author | 1-rafael-1 <[email protected]> | 2025-09-15 21:57:41 +0200 |
|---|---|---|
| committer | 1-rafael-1 <[email protected]> | 2025-09-15 21:57:41 +0200 |
| commit | dd10e372d2e656dc71fa460564d405ba6a5b5d4b (patch) | |
| tree | e8e4c6cd9826082f2dde10f7f459032582c458a8 /embassy-rp/src/rtc/mod.rs | |
| parent | ac32f43c3dc915b78e71328855189b8aacfec8c3 (diff) | |
Fix race condition in RTC alarm by using AtomicBool flag
Diffstat (limited to 'embassy-rp/src/rtc/mod.rs')
| -rw-r--r-- | embassy-rp/src/rtc/mod.rs | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index 8e6aa66c9..8b0deed21 100644 --- a/embassy-rp/src/rtc/mod.rs +++ b/embassy-rp/src/rtc/mod.rs | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | mod filter; | 2 | mod filter; |
| 3 | 3 | ||
| 4 | use core::future::poll_fn; | 4 | use core::future::poll_fn; |
| 5 | use core::sync::atomic::{compiler_fence, Ordering}; | 5 | use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; |
| 6 | use core::task::Poll; | 6 | use core::task::Poll; |
| 7 | 7 | ||
| 8 | use embassy_hal_internal::{Peri, PeripheralType}; | 8 | use embassy_hal_internal::{Peri, PeripheralType}; |
| @@ -21,6 +21,8 @@ use crate::interrupt::{self, InterruptExt}; | |||
| 21 | 21 | ||
| 22 | // Static waker for the interrupt handler | 22 | // Static waker for the interrupt handler |
| 23 | static WAKER: AtomicWaker = AtomicWaker::new(); | 23 | static WAKER: AtomicWaker = AtomicWaker::new(); |
| 24 | // Static flag to indicate if an alarm has occurred | ||
| 25 | static ALARM_OCCURRED: AtomicBool = AtomicBool::new(false); | ||
| 24 | 26 | ||
| 25 | /// A reference to the real time clock of the system | 27 | /// A reference to the real time clock of the system |
| 26 | pub struct Rtc<'d, T: Instance> { | 28 | pub struct Rtc<'d, T: Instance> { |
| @@ -257,10 +259,15 @@ impl<'d, T: Instance> Rtc<'d, T> { | |||
| 257 | poll_fn(|cx| { | 259 | poll_fn(|cx| { |
| 258 | WAKER.register(cx.waker()); | 260 | WAKER.register(cx.waker()); |
| 259 | 261 | ||
| 260 | // Check hardware interrupt status directly | 262 | // Atomically check and clear the alarm occurred flag to prevent race conditions |
| 261 | if self.inner.regs().ints().read().rtc() { | 263 | if critical_section::with(|_| { |
| 262 | // Clear the interrupt status and disable the alarm | 264 | let occurred = ALARM_OCCURRED.load(Ordering::SeqCst); |
| 263 | self.inner.regs().ints().write(|w| w.set_rtc(true)); | 265 | if occurred { |
| 266 | ALARM_OCCURRED.store(false, Ordering::SeqCst); | ||
| 267 | } | ||
| 268 | occurred | ||
| 269 | }) { | ||
| 270 | // Clear the interrupt and disable the alarm | ||
| 264 | self.clear_interrupt(); | 271 | self.clear_interrupt(); |
| 265 | 272 | ||
| 266 | compiler_fence(Ordering::SeqCst); | 273 | compiler_fence(Ordering::SeqCst); |
| @@ -284,7 +291,8 @@ impl crate::interrupt::typelevel::Handler<crate::interrupt::typelevel::RTC_IRQ> | |||
| 284 | let rtc = crate::pac::RTC; | 291 | let rtc = crate::pac::RTC; |
| 285 | rtc.irq_setup_0().modify(|w| w.set_match_ena(false)); | 292 | rtc.irq_setup_0().modify(|w| w.set_match_ena(false)); |
| 286 | 293 | ||
| 287 | // Wake the waker - interrupt status will be checked directly by polling future | 294 | // Set the alarm occurred flag and wake the waker |
| 295 | ALARM_OCCURRED.store(true, Ordering::SeqCst); | ||
| 288 | WAKER.wake(); | 296 | WAKER.wake(); |
| 289 | } | 297 | } |
| 290 | } | 298 | } |
