mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-23 20:22:51 +01:00
Fix monotonics race
This commit is contained in:
parent
72ae46083e
commit
0bb5814443
2 changed files with 20 additions and 4 deletions
|
@ -189,13 +189,18 @@ macro_rules! make_rtc {
|
||||||
// and the flag here.
|
// and the flag here.
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
let rtc = unsafe { &*$rtc::PTR };
|
let rtc = unsafe { &*$rtc::PTR };
|
||||||
let cnt = rtc.counter.read().bits() as u64;
|
let cnt = rtc.counter.read().bits();
|
||||||
|
// OVERFLOW HAPPENS HERE race needs to be handled
|
||||||
let ovf = if Self::is_overflow() {
|
let ovf = if Self::is_overflow() {
|
||||||
$overflow.load(Ordering::Relaxed) + 1
|
$overflow.load(Ordering::Relaxed) + 1
|
||||||
} else {
|
} else {
|
||||||
$overflow.load(Ordering::Relaxed)
|
$overflow.load(Ordering::Relaxed)
|
||||||
} as u64;
|
} as u64;
|
||||||
|
|
||||||
|
// Check and fix if above race happened
|
||||||
|
let new_cnt = rtc.counter.read().bits();
|
||||||
|
let cnt = if new_cnt >= cnt { cnt } else { new_cnt } as u64;
|
||||||
|
|
||||||
Self::Instant::from_ticks((ovf << 24) | cnt)
|
Self::Instant::from_ticks((ovf << 24) | cnt)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,6 +182,12 @@ macro_rules! make_timer {
|
||||||
pub async fn delay_until(instant: <Self as Monotonic>::Instant) {
|
pub async fn delay_until(instant: <Self as Monotonic>::Instant) {
|
||||||
$tq.delay_until(instant).await;
|
$tq.delay_until(instant).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn is_overflow() -> bool {
|
||||||
|
let timer = unsafe { &*$timer::PTR };
|
||||||
|
timer.events_compare[1].read().bits() & 1 != 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "embedded-hal-async")]
|
#[cfg(feature = "embedded-hal-async")]
|
||||||
|
@ -213,17 +219,22 @@ macro_rules! make_timer {
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
let timer = unsafe { &*$timer::PTR };
|
let timer = unsafe { &*$timer::PTR };
|
||||||
timer.tasks_capture[2].write(|w| unsafe { w.bits(1) });
|
timer.tasks_capture[2].write(|w| unsafe { w.bits(1) });
|
||||||
|
let cnt = timer.cc[2].read().bits();
|
||||||
|
|
||||||
let unhandled_overflow = if timer.events_compare[1].read().bits() & 1 != 0 {
|
let unhandled_overflow = if Self::is_overflow() {
|
||||||
// The overflow has not been handled yet, so add an extra to the read overflow.
|
// The overflow has not been handled yet, so add an extra to the read overflow.
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
timer.tasks_capture[2].write(|w| unsafe { w.bits(1) });
|
||||||
|
let new_cnt = timer.cc[2].read().bits();
|
||||||
|
let cnt = if new_cnt >= cnt { cnt } else { new_cnt } as u64;
|
||||||
|
|
||||||
Self::Instant::from_ticks(
|
Self::Instant::from_ticks(
|
||||||
(unhandled_overflow + $overflow.load(Ordering::Relaxed) as u64) << 32
|
(unhandled_overflow + $overflow.load(Ordering::Relaxed) as u64) << 32
|
||||||
| timer.cc[2].read().bits() as u64,
|
| cnt as u64,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -232,7 +243,7 @@ macro_rules! make_timer {
|
||||||
let timer = unsafe { &*$timer::PTR };
|
let timer = unsafe { &*$timer::PTR };
|
||||||
|
|
||||||
// If there is a compare match on channel 1, it is an overflow
|
// If there is a compare match on channel 1, it is an overflow
|
||||||
if timer.events_compare[1].read().bits() & 1 != 0 {
|
if Self::is_overflow() {
|
||||||
timer.events_compare[1].write(|w| w);
|
timer.events_compare[1].write(|w| w);
|
||||||
$overflow.fetch_add(1, Ordering::SeqCst);
|
$overflow.fetch_add(1, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue