mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-23 12:12:50 +01:00
[monotonics] Fix STM32 read-modify-write race condition (#984)
* Fix stm32 read-modify-write problem The `SR` register for STM32 clears when writing a zero to a bit. Therefore, all registers that should not be cleared need to be `1`. `modify` here caused a read-modify-write error that could clear unrelated flags. * Add changelog * Make initialization more deterministic * Update changelog * Beautification in comments --------- Co-authored-by: Martin Stumpf <martin.stumpf@vected.de>
This commit is contained in:
parent
0f532c6b48
commit
3dfef74a4c
2 changed files with 28 additions and 6 deletions
|
@ -15,6 +15,11 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
|
||||||
|
|
||||||
- Update `esp32c3` dependency
|
- Update `esp32c3` dependency
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- STM32: Make initialization more deterministic
|
||||||
|
- STM32: Fix race condition that caused missed interrupts
|
||||||
|
|
||||||
## v2.0.2 - 2024-07-05
|
## v2.0.2 - 2024-07-05
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -246,9 +246,17 @@ macro_rules! make_timer {
|
||||||
// Trigger an update event to load the prescaler value to the clock.
|
// Trigger an update event to load the prescaler value to the clock.
|
||||||
$timer.egr().write(|r| r.set_ug(true));
|
$timer.egr().write(|r| r.set_ug(true));
|
||||||
|
|
||||||
// The above line raises an update event which will indicate that the timer is already finished.
|
// Clear timer value so it is known that we are at the first half period
|
||||||
// Since this is not the case, it should be cleared.
|
$timer.cnt().write(|r| r.set_cnt(1));
|
||||||
$timer.sr().modify(|r| r.set_uif(false));
|
|
||||||
|
// Triggering the update event might have raised overflow interrupts.
|
||||||
|
// Clear them to return to a known state.
|
||||||
|
$timer.sr().write(|r| {
|
||||||
|
r.0 = !0;
|
||||||
|
r.set_uif(false);
|
||||||
|
r.set_ccif(0, false);
|
||||||
|
r.set_ccif(1, false);
|
||||||
|
});
|
||||||
|
|
||||||
$tq.initialize(Self {});
|
$tq.initialize(Self {});
|
||||||
$overflow.store(0, Ordering::SeqCst);
|
$overflow.store(0, Ordering::SeqCst);
|
||||||
|
@ -294,7 +302,10 @@ macro_rules! make_timer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_compare_flag() {
|
fn clear_compare_flag() {
|
||||||
$timer.sr().modify(|r| r.set_ccif(1, false));
|
$timer.sr().write(|r| {
|
||||||
|
r.0 = !0;
|
||||||
|
r.set_ccif(1, false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pend_interrupt() {
|
fn pend_interrupt() {
|
||||||
|
@ -312,13 +323,19 @@ macro_rules! make_timer {
|
||||||
fn on_interrupt() {
|
fn on_interrupt() {
|
||||||
// Full period
|
// Full period
|
||||||
if $timer.sr().read().uif() {
|
if $timer.sr().read().uif() {
|
||||||
$timer.sr().modify(|r| r.set_uif(false));
|
$timer.sr().write(|r| {
|
||||||
|
r.0 = !0;
|
||||||
|
r.set_uif(false);
|
||||||
|
});
|
||||||
let prev = $overflow.fetch_add(1, Ordering::Relaxed);
|
let prev = $overflow.fetch_add(1, Ordering::Relaxed);
|
||||||
assert!(prev % 2 == 1, "Monotonic must have missed an interrupt!");
|
assert!(prev % 2 == 1, "Monotonic must have missed an interrupt!");
|
||||||
}
|
}
|
||||||
// Half period
|
// Half period
|
||||||
if $timer.sr().read().ccif(0) {
|
if $timer.sr().read().ccif(0) {
|
||||||
$timer.sr().modify(|r| r.set_ccif(0, false));
|
$timer.sr().write(|r| {
|
||||||
|
r.0 = !0;
|
||||||
|
r.set_ccif(0, false);
|
||||||
|
});
|
||||||
let prev = $overflow.fetch_add(1, Ordering::Relaxed);
|
let prev = $overflow.fetch_add(1, Ordering::Relaxed);
|
||||||
assert!(prev % 2 == 0, "Monotonic must have missed an interrupt!");
|
assert!(prev % 2 == 0, "Monotonic must have missed an interrupt!");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue