Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mono delay #843

Merged
merged 36 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
338ffe5
rtic-time: Compenstate for timer uncertainty
Finomnis Nov 27, 2023
efdec70
Update changelog and incorrect cargo.lock in an example
Finomnis Nov 27, 2023
09af965
Fix Monotonic impls
Finomnis Nov 27, 2023
0e0029d
Fix tests
Finomnis Nov 27, 2023
e213e05
Fix other monotonics, again
Finomnis Nov 27, 2023
117934a
Update changelog
Finomnis Nov 27, 2023
6539d77
Fix example
Finomnis Nov 27, 2023
8cf4692
Fix DelayUs and DelayMs impls
Finomnis Nov 27, 2023
619ecb1
Minor coding style fix in u64 conversions
Finomnis Nov 27, 2023
4d36f01
Fix all changelogs
Finomnis Nov 27, 2023
5d174f6
Fix changelog
Finomnis Nov 27, 2023
e94e617
Fix blocking DelayUs
Finomnis Nov 27, 2023
9008509
Minor monotonic rework
Finomnis Nov 29, 2023
a80c6df
Add delay precision test
Finomnis Nov 29, 2023
619ed23
Add more tests
Finomnis Nov 29, 2023
b15df3a
Add rust-version tags to Cargo.toml
Finomnis Nov 29, 2023
5da48c6
Merge pull request #1 from Finomnis/simplify_monotonics
Finomnis Nov 29, 2023
6c08a62
Fix imxrt, rp2040 and systick timer
Finomnis Nov 29, 2023
2cf56a4
Fix more monotonics
Finomnis Nov 29, 2023
e25f194
Fix systick monotonic
Finomnis Nov 29, 2023
ac7f7cf
Some reverts
Finomnis Nov 29, 2023
d1c3618
Fix imxrt
Finomnis Nov 29, 2023
75a56f8
Fix nrf
Finomnis Nov 29, 2023
6edb026
Fix rp2040
Finomnis Nov 29, 2023
ecc863c
Fix stm32
Finomnis Nov 29, 2023
9406de5
Fix systick
Finomnis Nov 29, 2023
05eea9d
Fix rtic-time tests
Finomnis Nov 29, 2023
f0217fa
Merge branch 'master' into fix_mono_delay
Finomnis Nov 29, 2023
35cd985
Bump to e-h.rc2
Finomnis Nov 29, 2023
e189ebb
Apply e-h.rc2 fixes to rtic-time
Finomnis Nov 29, 2023
d3db0fe
Apply fixes from arbiter
Finomnis Nov 29, 2023
08b1f66
Fix clippy warning
Finomnis Nov 29, 2023
4c6cf9c
Minor beautification
Finomnis Nov 29, 2023
92bfbf5
Revert previous changes
Finomnis Nov 29, 2023
d76d25a
Fix variable name
Finomnis Nov 29, 2023
35eb639
Add blocking tests, but disable them by default
Finomnis Nov 29, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/teensy4_blinky/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions rtic-monotonics/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!

## Unreleased

### Fixed

- **Soundness fix:** Monotonics did not wait long enough in `Duration` based delays.

## v1.3.0 - 2023-11-08

### Added
Expand Down
4 changes: 2 additions & 2 deletions rtic-monotonics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ rustdoc-flags = ["--cfg", "docsrs"]

[dependencies]
rtic-time = { version = "1.0.0", path = "../rtic-time" }
embedded-hal = { version = "1.0.0-rc.1" }
embedded-hal-async = { version = "1.0.0-rc.1", optional = true }
embedded-hal = { version = "1.0.0-rc.2" }
embedded-hal-async = { version = "1.0.0-rc.2", optional = true }
fugit = { version = "0.3.6" }
atomic-polyfill = "1"
cfg-if = "1.0.0"
Expand Down
24 changes: 5 additions & 19 deletions rtic-monotonics/src/imxrt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

use crate::{Monotonic, TimeoutError, TimerQueue};
use atomic_polyfill::{compiler_fence, AtomicU32, Ordering};
pub use fugit::{self, ExtU64};
pub use fugit::{self, ExtU64, ExtU64Ceil};

use imxrt_ral as ral;

Expand Down Expand Up @@ -216,31 +216,17 @@ macro_rules! make_timer {
}
}

#[cfg(feature = "embedded-hal-async")]
impl embedded_hal_async::delay::DelayUs for $mono_name {
#[inline]
async fn delay_us(&mut self, us: u32) {
Self::delay((us as u64).micros()).await;
}

#[inline]
async fn delay_ms(&mut self, ms: u32) {
Self::delay((ms as u64).millis()).await;
}
}
rtic_time::embedded_hal_delay_impl_fugit64!($mono_name);

impl embedded_hal::delay::DelayUs for $mono_name {
fn delay_us(&mut self, us: u32) {
let done = Self::now() + (us as u64).micros();
while Self::now() < done {}
}
}
#[cfg(feature = "embedded-hal-async")]
rtic_time::embedded_hal_async_delay_impl_fugit64!($mono_name);

impl Monotonic for $mono_name {
type Instant = fugit::TimerInstantU64<TIMER_HZ>;
type Duration = fugit::TimerDurationU64<TIMER_HZ>;

const ZERO: Self::Instant = Self::Instant::from_ticks(0);
const TICK_PERIOD: Self::Duration = Self::Duration::from_ticks(1);

fn now() -> Self::Instant {
let gpt = unsafe{ $timer::instance() };
Expand Down
23 changes: 5 additions & 18 deletions rtic-monotonics/src/nrf/rtc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use nrf9160_pac::{self as pac, Interrupt, RTC0_NS as RTC0, RTC1_NS as RTC1};
use crate::{Monotonic, TimeoutError, TimerQueue};
use atomic_polyfill::{AtomicU32, Ordering};
use core::future::Future;
pub use fugit::{self, ExtU64};
pub use fugit::{self, ExtU64, ExtU64Ceil};

#[doc(hidden)]
#[macro_export]
Expand Down Expand Up @@ -167,28 +167,15 @@ macro_rules! make_rtc {
}
}

#[cfg(feature = "embedded-hal-async")]
impl embedded_hal_async::delay::DelayUs for $mono_name {
#[inline]
async fn delay_us(&mut self, us: u32) {
Self::delay((us as u64).micros()).await;
}

#[inline]
async fn delay_ms(&mut self, ms: u32) {
Self::delay((ms as u64).millis()).await;
}
}
rtic_time::embedded_hal_delay_impl_fugit64!($mono_name);

impl embedded_hal::delay::DelayUs for $mono_name {
fn delay_us(&mut self, us: u32) {
let done = Self::now() + u64::from(us).micros();
while Self::now() < done {}
}
}
#[cfg(feature = "embedded-hal-async")]
rtic_time::embedded_hal_async_delay_impl_fugit64!($mono_name);

impl Monotonic for $mono_name {
const ZERO: Self::Instant = Self::Instant::from_ticks(0);
const TICK_PERIOD: Self::Duration = Self::Duration::from_ticks(1);

type Instant = fugit::TimerInstantU64<32_768>;
type Duration = fugit::TimerDurationU64<32_768>;
Expand Down
24 changes: 5 additions & 19 deletions rtic-monotonics/src/nrf/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
use crate::{Monotonic, TimeoutError, TimerQueue};
use atomic_polyfill::{AtomicU32, Ordering};
use core::future::Future;
pub use fugit::{self, ExtU64};
pub use fugit::{self, ExtU64, ExtU64Ceil};

#[cfg(feature = "nrf52810")]
use nrf52810_pac::{self as pac, Interrupt, TIMER0, TIMER1, TIMER2};
Expand Down Expand Up @@ -203,28 +203,14 @@ macro_rules! make_timer {
}
}

#[cfg(feature = "embedded-hal-async")]
impl embedded_hal_async::delay::DelayUs for $mono_name {
#[inline]
async fn delay_us(&mut self, us: u32) {
Self::delay((us as u64).micros()).await;
}

#[inline]
async fn delay_ms(&mut self, ms: u32) {
Self::delay((ms as u64).millis()).await;
}
}
rtic_time::embedded_hal_delay_impl_fugit64!($mono_name);

impl embedded_hal::delay::DelayUs for $mono_name {
fn delay_us(&mut self, us: u32) {
let done = Self::now() + (us as u64).micros();
while Self::now() < done {}
}
}
#[cfg(feature = "embedded-hal-async")]
rtic_time::embedded_hal_async_delay_impl_fugit64!($mono_name);

impl Monotonic for $mono_name {
const ZERO: Self::Instant = Self::Instant::from_ticks(0);
const TICK_PERIOD: Self::Duration = Self::Duration::from_ticks(1);

type Instant = fugit::TimerInstantU64<1_000_000>;
type Duration = fugit::TimerDurationU64<1_000_000>;
Expand Down
22 changes: 5 additions & 17 deletions rtic-monotonics/src/rp2040.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use super::Monotonic;

pub use super::{TimeoutError, TimerQueue};
use core::future::Future;
pub use fugit::{self, ExtU64};
pub use fugit::{self, ExtU64, ExtU64Ceil};
use rp2040_pac::{timer, Interrupt, NVIC, RESETS, TIMER};

/// Timer implementing [`Monotonic`] which runs at 1 MHz.
Expand Down Expand Up @@ -104,6 +104,7 @@ impl Monotonic for Timer {
type Duration = fugit::TimerDurationU64<1_000_000>;

const ZERO: Self::Instant = Self::Instant::from_ticks(0);
const TICK_PERIOD: Self::Duration = Self::Duration::from_ticks(1);

fn now() -> Self::Instant {
let timer = Self::timer();
Expand Down Expand Up @@ -151,23 +152,10 @@ impl Monotonic for Timer {
fn disable_timer() {}
}

#[cfg(feature = "embedded-hal-async")]
impl embedded_hal_async::delay::DelayUs for Timer {
async fn delay_us(&mut self, us: u32) {
Self::delay((us as u64).micros()).await;
}

async fn delay_ms(&mut self, ms: u32) {
Self::delay((ms as u64).millis()).await;
}
}
rtic_time::embedded_hal_delay_impl_fugit64!(Timer);

impl embedded_hal::delay::DelayUs for Timer {
fn delay_us(&mut self, us: u32) {
let done = Self::now() + u64::from(us).micros();
while Self::now() < done {}
}
}
#[cfg(feature = "embedded-hal-async")]
rtic_time::embedded_hal_async_delay_impl_fugit64!(Timer);

/// Register the Timer interrupt for the monotonic.
#[macro_export]
Expand Down
24 changes: 5 additions & 19 deletions rtic-monotonics/src/stm32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

use crate::{Monotonic, TimeoutError, TimerQueue};
use atomic_polyfill::{compiler_fence, AtomicU64, Ordering};
pub use fugit::{self, ExtU64};
pub use fugit::{self, ExtU64, ExtU64Ceil};
use stm32_metapac as pac;

mod _generated {
Expand Down Expand Up @@ -218,31 +218,17 @@ macro_rules! make_timer {
}
}

#[cfg(feature = "embedded-hal-async")]
impl embedded_hal_async::delay::DelayUs for $mono_name {
#[inline]
async fn delay_us(&mut self, us: u32) {
Self::delay((us as u64).micros()).await;
}

#[inline]
async fn delay_ms(&mut self, ms: u32) {
Self::delay((ms as u64).millis()).await;
}
}
rtic_time::embedded_hal_delay_impl_fugit64!($mono_name);

impl embedded_hal::delay::DelayUs for $mono_name {
fn delay_us(&mut self, us: u32) {
let done = Self::now() + (us as u64).micros();
while Self::now() < done {}
}
}
#[cfg(feature = "embedded-hal-async")]
rtic_time::embedded_hal_async_delay_impl_fugit64!($mono_name);

impl Monotonic for $mono_name {
type Instant = fugit::TimerInstantU64<TIMER_HZ>;
type Duration = fugit::TimerDurationU64<TIMER_HZ>;

const ZERO: Self::Instant = Self::Instant::from_ticks(0);
const TICK_PERIOD: Self::Duration = Self::Duration::from_ticks(1);

fn now() -> Self::Instant {
// Credits to the `time-driver` of `embassy-stm32`.
Expand Down
33 changes: 12 additions & 21 deletions rtic-monotonics/src/systick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ use cortex_m::peripheral::SYST;
pub use fugit;
cfg_if::cfg_if! {
if #[cfg(feature = "systick-64bit")] {
pub use fugit::ExtU64;
pub use fugit::{ExtU64, ExtU64Ceil};
use atomic_polyfill::AtomicU64;
static SYSTICK_CNT: AtomicU64 = AtomicU64::new(0);
} else {
pub use fugit::ExtU32;
pub use fugit::{ExtU32, ExtU32Ceil};
use atomic_polyfill::AtomicU32;
static SYSTICK_CNT: AtomicU32 = AtomicU32::new(0);
}
Expand Down Expand Up @@ -156,6 +156,7 @@ impl Monotonic for Systick {
}

const ZERO: Self::Instant = Self::Instant::from_ticks(0);
const TICK_PERIOD: Self::Duration = Self::Duration::from_ticks(1);

fn now() -> Self::Instant {
if Self::systick().has_wrapped() {
Expand Down Expand Up @@ -188,27 +189,17 @@ impl Monotonic for Systick {
fn disable_timer() {}
}

#[cfg(feature = "embedded-hal-async")]
impl embedded_hal_async::delay::DelayUs for Systick {
async fn delay_us(&mut self, us: u32) {
#[cfg(feature = "systick-64bit")]
let us = u64::from(us);
Self::delay(us.micros()).await;
}
cfg_if::cfg_if! {
if #[cfg(feature = "systick-64bit")] {
rtic_time::embedded_hal_delay_impl_fugit64!(Systick);

async fn delay_ms(&mut self, ms: u32) {
#[cfg(feature = "systick-64bit")]
let ms = u64::from(ms);
Self::delay(ms.millis()).await;
}
}
#[cfg(feature = "embedded-hal-async")]
rtic_time::embedded_hal_async_delay_impl_fugit64!(Systick);
} else {
rtic_time::embedded_hal_delay_impl_fugit32!(Systick);

impl embedded_hal::delay::DelayUs for Systick {
fn delay_us(&mut self, us: u32) {
#[cfg(feature = "systick-64bit")]
let us = u64::from(us);
let done = Self::now() + us.micros();
while Self::now() < done {}
#[cfg(feature = "embedded-hal-async")]
rtic_time::embedded_hal_async_delay_impl_fugit32!(Systick);
}
}

Expand Down
6 changes: 3 additions & 3 deletions rtic-sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ heapless = "0.7"
critical-section = "1"
rtic-common = { version = "1.0.0", path = "../rtic-common" }
portable-atomic = { version = "1", default-features = false }
embedded-hal = { version = "1.0.0-rc.1", optional = true }
embedded-hal-async = { version = "1.0.0-rc.1", optional = true }
embedded-hal-bus = { version = "0.1.0-rc.1", optional = true, features = ["async"] }
embedded-hal = { version = "1.0.0-rc.2", optional = true }
embedded-hal-async = { version = "1.0.0-rc.2", optional = true }
embedded-hal-bus = { version = "0.1.0-rc.2", optional = true, features = ["async"] }

[dev-dependencies]
tokio = { version = "1", features = ["rt", "macros", "time"] }
Expand Down
8 changes: 4 additions & 4 deletions rtic-sync/src/arbiter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ pub mod spi {
use super::Arbiter;
use embedded_hal::digital::OutputPin;
use embedded_hal_async::{
delay::DelayUs,
delay::DelayNs,
spi::{ErrorType, Operation, SpiBus, SpiDevice},
};
use embedded_hal_bus::spi::DeviceError;
Expand Down Expand Up @@ -229,7 +229,7 @@ pub mod spi {
Word: Copy + 'static,
BUS: SpiBus<Word>,
CS: OutputPin,
D: DelayUs,
D: DelayNs,
{
async fn transaction(
&mut self,
Expand All @@ -246,10 +246,10 @@ pub mod spi {
Operation::Write(buf) => bus.write(buf).await,
Operation::Transfer(read, write) => bus.transfer(read, write).await,
Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await,
Operation::DelayUs(us) => match bus.flush().await {
Operation::DelayNs(ns) => match bus.flush().await {
Err(e) => Err(e),
Ok(()) => {
self.delay.delay_us(*us).await;
self.delay.delay_ns(*ns).await;
Ok(())
}
},
Expand Down
1 change: 1 addition & 0 deletions rtic-time/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!

### Fixed

- **Soundness fix:** `TimerQueue` did not wait long enough in `Duration` based delays. Fixing this sadly required adding a `const TICK_PERIOD` to the `Monotonic` trait, which requires updating all existing implementations.
- If the queue was non-empty and a new instant was added that was earlier than `head`, then the queue would no pend the monotonic handler. This would cause the new `head` to be dequeued at the wrong time.

## [v1.0.0] - 2023-05-31
4 changes: 4 additions & 0 deletions rtic-time/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,9 @@ futures-util = { version = "0.3.25", default-features = false }
rtic-common = { version = "1.0.0", path = "../rtic-common" }

[dev-dependencies]
embedded-hal = { version = "1.0.0-rc.2" }
embedded-hal-async = { version = "1.0.0-rc.2" }
fugit = "0.3.7"
parking_lot = "0.12"
cassette = "0.2"
cooked-waker = "5.0.0"
Loading