Refactor race condition free timer helper (#850)

* Implement half_period_counter in rtic-time

* Rename compute_now to calculate_now, use it in stm32 and imxrt

* Add more tests

* Add some docs

* Fix clippy warning, add imxrt timer to monotonics tests

* Bump dependency version to make sure monotonics will build properly

* Add changelog to rtic-monotonics

* Add more docs

* Add more docs

* Finish documentation

* Fix typos

* Switch from atomic-polyfill to portable-atomic

* Some more doc fixes

* More doc fixes

* Minor doc fix

* Minor doc fix

* Fix Atomics not existing

* Fix example

* Minor example improvement

* Revert back to atomic-polyfill

* Fix cargo.toml formatting

* Remove atomic-polyfill

* Attempt to fix unused macro warning

* Remove atomics completely from half period counter

* Minor doc fix

* Doc fixes

* Doc fixes

* Remove obsolete comment

* Fix ordering in monotonic initialization sequence
This commit is contained in:
Finomnis 2023-12-04 15:53:02 +01:00 committed by GitHub
parent 3de5f793f3
commit c227a71d24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 350 additions and 49 deletions

View file

@ -35,8 +35,9 @@
//! ```
use crate::{Monotonic, TimeoutError, TimerQueue};
use atomic_polyfill::{compiler_fence, AtomicU64, Ordering};
use atomic_polyfill::{AtomicU64, Ordering};
pub use fugit::{self, ExtU64, ExtU64Ceil};
use rtic_time::half_period_counter::calculate_now;
use stm32_metapac as pac;
mod _generated {
@ -166,13 +167,14 @@ macro_rules! make_timer {
// Since this is not the case, it should be cleared.
$timer.sr().modify(|r| r.set_uif(false));
$tq.initialize(Self {});
$overflow.store(0, Ordering::SeqCst);
// Start the counter.
$timer.cr1().modify(|r| {
r.set_cen(true);
});
$tq.initialize(Self {});
// SAFETY: We take full ownership of the peripheral and interrupt vector,
// plus we are not using any external shared resources so we won't impact
// basepri/source masking based critical sections.
@ -231,18 +233,10 @@ macro_rules! make_timer {
const TICK_PERIOD: Self::Duration = Self::Duration::from_ticks(1);
fn now() -> Self::Instant {
// Credits to the `time-driver` of `embassy-stm32`.
// For more info, see the `imxrt` driver.
fn calc_now(period: u64, counter: $bits) -> u64 {
(period << ($bits::BITS - 1)) + u64::from(counter ^ (((period & 1) as $bits) << ($bits::BITS - 1)))
}
// Important: period **must** be read first.
let period = $overflow.load(Ordering::Relaxed);
compiler_fence(Ordering::Acquire);
let counter = $timer.cnt().read().cnt();
Self::Instant::from_ticks(calc_now(period, counter))
Self::Instant::from_ticks(calculate_now(
$overflow.load(Ordering::Relaxed),
|| $timer.cnt().read().cnt()
))
}
fn set_compare(instant: Self::Instant) {