aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/rtc/mod.rs
diff options
context:
space:
mode:
author1-rafael-1 <[email protected]>2025-09-15 21:57:41 +0200
committer1-rafael-1 <[email protected]>2025-09-15 21:57:41 +0200
commitdd10e372d2e656dc71fa460564d405ba6a5b5d4b (patch)
treee8e4c6cd9826082f2dde10f7f459032582c458a8 /embassy-rp/src/rtc/mod.rs
parentac32f43c3dc915b78e71328855189b8aacfec8c3 (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.rs20
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 @@
2mod filter; 2mod filter;
3 3
4use core::future::poll_fn; 4use core::future::poll_fn;
5use core::sync::atomic::{compiler_fence, Ordering}; 5use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
6use core::task::Poll; 6use core::task::Poll;
7 7
8use embassy_hal_internal::{Peri, PeripheralType}; 8use 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
23static WAKER: AtomicWaker = AtomicWaker::new(); 23static WAKER: AtomicWaker = AtomicWaker::new();
24// Static flag to indicate if an alarm has occurred
25static 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
26pub struct Rtc<'d, T: Instance> { 28pub 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}