mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-19 06:15:45 +01:00
Fix mono delay (#843)
* rtic-time: Compenstate for timer uncertainty * Update changelog and incorrect cargo.lock in an example * Fix Monotonic impls * Fix tests * Fix other monotonics, again * Update changelog * Fix example * Fix DelayUs and DelayMs impls * Minor coding style fix in u64 conversions * Fix all changelogs * Fix changelog * Fix blocking DelayUs * Minor monotonic rework * Add delay precision test * Add more tests * Add rust-version tags to Cargo.toml * Fix imxrt, rp2040 and systick timer * Fix more monotonics * Fix systick monotonic * Some reverts * Fix imxrt * Fix nrf * Fix rp2040 * Fix stm32 * Fix systick * Fix rtic-time tests * Bump to e-h.rc2 * Apply e-h.rc2 fixes to rtic-time * Apply fixes from arbiter * Fix clippy warning * Minor beautification * Revert previous changes * Fix variable name * Add blocking tests, but disable them by default
This commit is contained in:
parent
9f5820da1d
commit
612a47ef4d
19 changed files with 560 additions and 141 deletions
|
|
@ -181,22 +181,36 @@ impl<Mono: Monotonic> TimerQueue<Mono> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Timeout after a specific duration.
|
||||
/// Timeout after at least a specific duration.
|
||||
#[inline]
|
||||
pub async fn timeout_after<F: Future>(
|
||||
&self,
|
||||
duration: Mono::Duration,
|
||||
future: F,
|
||||
) -> Result<F::Output, TimeoutError> {
|
||||
self.timeout_at(Mono::now() + duration, future).await
|
||||
let now = Mono::now();
|
||||
let mut timeout = now + duration;
|
||||
if now != timeout {
|
||||
timeout = timeout + Mono::TICK_PERIOD;
|
||||
}
|
||||
|
||||
// Wait for one period longer, because by definition timers have an uncertainty
|
||||
// of one period, so waiting for 'at least' needs to compensate for that.
|
||||
self.timeout_at(timeout, future).await
|
||||
}
|
||||
|
||||
/// Delay for some duration of time.
|
||||
/// Delay for at least some duration of time.
|
||||
#[inline]
|
||||
pub async fn delay(&self, duration: Mono::Duration) {
|
||||
let now = Mono::now();
|
||||
let mut timeout = now + duration;
|
||||
if now != timeout {
|
||||
timeout = timeout + Mono::TICK_PERIOD;
|
||||
}
|
||||
|
||||
self.delay_until(now + duration).await;
|
||||
// Wait for one period longer, because by definition timers have an uncertainty
|
||||
// of one period, so waiting for 'at least' needs to compensate for that.
|
||||
self.delay_until(timeout).await;
|
||||
}
|
||||
|
||||
/// Delay to some specific time instant.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ pub trait Monotonic {
|
|||
/// The time at time zero.
|
||||
const ZERO: Self::Instant;
|
||||
|
||||
/// The duration between two timer ticks.
|
||||
const TICK_PERIOD: Self::Duration;
|
||||
|
||||
/// The type for instant, defining an instant in time.
|
||||
///
|
||||
/// **Note:** In all APIs in RTIC that use instants from this monotonic, this type will be used.
|
||||
|
|
@ -65,3 +68,153 @@ pub trait Monotonic {
|
|||
/// NOTE: This may be called more than once.
|
||||
fn disable_timer() {}
|
||||
}
|
||||
|
||||
/// Creates impl blocks for `embedded_hal::delay::DelayUs`,
|
||||
/// based on `fugit::ExtU64Ceil`.
|
||||
#[macro_export]
|
||||
macro_rules! embedded_hal_delay_impl_fugit64 {
|
||||
($t:ty) => {
|
||||
impl ::embedded_hal::delay::DelayNs for $t {
|
||||
fn delay_ns(&mut self, ns: u32) {
|
||||
use ::fugit::ExtU64Ceil;
|
||||
|
||||
let now = Self::now();
|
||||
let mut done = now + u64::from(ns).nanos_at_least();
|
||||
if now != done {
|
||||
// Compensate for sub-tick uncertainty
|
||||
done += Self::TICK_PERIOD;
|
||||
}
|
||||
|
||||
while Self::now() < done {}
|
||||
}
|
||||
|
||||
fn delay_us(&mut self, us: u32) {
|
||||
use ::fugit::ExtU64Ceil;
|
||||
|
||||
let now = Self::now();
|
||||
let mut done = now + u64::from(us).micros_at_least();
|
||||
if now != done {
|
||||
// Compensate for sub-tick uncertainty
|
||||
done += Self::TICK_PERIOD;
|
||||
}
|
||||
|
||||
while Self::now() < done {}
|
||||
}
|
||||
|
||||
fn delay_ms(&mut self, ms: u32) {
|
||||
use ::fugit::ExtU64Ceil;
|
||||
|
||||
let now = Self::now();
|
||||
let mut done = now + u64::from(ms).millis_at_least();
|
||||
if now != done {
|
||||
// Compensate for sub-tick uncertainty
|
||||
done += Self::TICK_PERIOD;
|
||||
}
|
||||
|
||||
while Self::now() < done {}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Creates impl blocks for `embedded_hal_async::delay::DelayUs`,
|
||||
/// based on `fugit::ExtU64Ceil`.
|
||||
#[macro_export]
|
||||
macro_rules! embedded_hal_async_delay_impl_fugit64 {
|
||||
($t:ty) => {
|
||||
impl ::embedded_hal_async::delay::DelayNs for $t {
|
||||
#[inline]
|
||||
async fn delay_ns(&mut self, ns: u32) {
|
||||
use ::fugit::ExtU64Ceil;
|
||||
Self::delay(u64::from(ns).nanos_at_least()).await;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
async fn delay_us(&mut self, us: u32) {
|
||||
use ::fugit::ExtU64Ceil;
|
||||
Self::delay(u64::from(us).micros_at_least()).await;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
async fn delay_ms(&mut self, ms: u32) {
|
||||
use ::fugit::ExtU64Ceil;
|
||||
Self::delay(u64::from(ms).millis_at_least()).await;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Creates impl blocks for `embedded_hal::delay::DelayUs`,
|
||||
/// based on `fugit::ExtU32Ceil`.
|
||||
#[macro_export]
|
||||
macro_rules! embedded_hal_delay_impl_fugit32 {
|
||||
($t:ty) => {
|
||||
impl ::embedded_hal::delay::DelayNs for $t {
|
||||
fn delay_ns(&mut self, ns: u32) {
|
||||
use ::fugit::ExtU32Ceil;
|
||||
|
||||
let now = Self::now();
|
||||
let mut done = now + ns.nanos_at_least();
|
||||
if now != done {
|
||||
// Compensate for sub-tick uncertainty
|
||||
done += Self::TICK_PERIOD;
|
||||
}
|
||||
|
||||
while Self::now() < done {}
|
||||
}
|
||||
|
||||
fn delay_us(&mut self, us: u32) {
|
||||
use ::fugit::ExtU32Ceil;
|
||||
|
||||
let now = Self::now();
|
||||
let mut done = now + us.micros_at_least();
|
||||
if now != done {
|
||||
// Compensate for sub-tick uncertainty
|
||||
done += Self::TICK_PERIOD;
|
||||
}
|
||||
|
||||
while Self::now() < done {}
|
||||
}
|
||||
|
||||
fn delay_ms(&mut self, ms: u32) {
|
||||
use ::fugit::ExtU32Ceil;
|
||||
|
||||
let now = Self::now();
|
||||
let mut done = now + ms.millis_at_least();
|
||||
if now != done {
|
||||
// Compensate for sub-tick uncertainty
|
||||
done += Self::TICK_PERIOD;
|
||||
}
|
||||
|
||||
while Self::now() < done {}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Creates impl blocks for `embedded_hal_async::delay::DelayUs`,
|
||||
/// based on `fugit::ExtU32Ceil`.
|
||||
#[macro_export]
|
||||
macro_rules! embedded_hal_async_delay_impl_fugit32 {
|
||||
($t:ty) => {
|
||||
impl ::embedded_hal_async::delay::DelayNs for $t {
|
||||
#[inline]
|
||||
async fn delay_ns(&mut self, ns: u32) {
|
||||
use ::fugit::ExtU32Ceil;
|
||||
Self::delay(ns.nanos_at_least()).await;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
async fn delay_us(&mut self, us: u32) {
|
||||
use ::fugit::ExtU32Ceil;
|
||||
Self::delay(us.micros_at_least()).await;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
async fn delay_ms(&mut self, ms: u32) {
|
||||
use ::fugit::ExtU32Ceil;
|
||||
Self::delay(ms.millis_at_least()).await;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue