mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-10-02 22:54:52 +00:00
Fix race condition in RTC alarm by using AtomicBool flag
This commit is contained in:
parent
ac32f43c3d
commit
dd10e372d2
@ -2,7 +2,7 @@
|
|||||||
mod filter;
|
mod filter;
|
||||||
|
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
use embassy_hal_internal::{Peri, PeripheralType};
|
use embassy_hal_internal::{Peri, PeripheralType};
|
||||||
@ -21,6 +21,8 @@ use crate::interrupt::{self, InterruptExt};
|
|||||||
|
|
||||||
// Static waker for the interrupt handler
|
// Static waker for the interrupt handler
|
||||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||||
|
// Static flag to indicate if an alarm has occurred
|
||||||
|
static ALARM_OCCURRED: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
/// A reference to the real time clock of the system
|
/// A reference to the real time clock of the system
|
||||||
pub struct Rtc<'d, T: Instance> {
|
pub struct Rtc<'d, T: Instance> {
|
||||||
@ -257,10 +259,15 @@ impl<'d, T: Instance> Rtc<'d, T> {
|
|||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
WAKER.register(cx.waker());
|
WAKER.register(cx.waker());
|
||||||
|
|
||||||
// Check hardware interrupt status directly
|
// Atomically check and clear the alarm occurred flag to prevent race conditions
|
||||||
if self.inner.regs().ints().read().rtc() {
|
if critical_section::with(|_| {
|
||||||
// Clear the interrupt status and disable the alarm
|
let occurred = ALARM_OCCURRED.load(Ordering::SeqCst);
|
||||||
self.inner.regs().ints().write(|w| w.set_rtc(true));
|
if occurred {
|
||||||
|
ALARM_OCCURRED.store(false, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
occurred
|
||||||
|
}) {
|
||||||
|
// Clear the interrupt and disable the alarm
|
||||||
self.clear_interrupt();
|
self.clear_interrupt();
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
@ -284,7 +291,8 @@ impl crate::interrupt::typelevel::Handler<crate::interrupt::typelevel::RTC_IRQ>
|
|||||||
let rtc = crate::pac::RTC;
|
let rtc = crate::pac::RTC;
|
||||||
rtc.irq_setup_0().modify(|w| w.set_match_ena(false));
|
rtc.irq_setup_0().modify(|w| w.set_match_ena(false));
|
||||||
|
|
||||||
// Wake the waker - interrupt status will be checked directly by polling future
|
// Set the alarm occurred flag and wake the waker
|
||||||
|
ALARM_OCCURRED.store(true, Ordering::SeqCst);
|
||||||
WAKER.wake();
|
WAKER.wake();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user