diff options
| author | Finomnis <Finomnis@users.noreply.github.com> | 2024-04-11 00:00:38 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-10 22:00:38 +0000 |
| commit | 8c23e178f3838bcdd13662a2ffefd39ec144e869 (patch) | |
| tree | f2d2cefcd6bb2876e74ee6035b5489a4a2d9590f /rtic-time/src/timer_queue | |
| parent | e4cc5fd17b8a2df332af0ee25c8bd7092e66afb0 (diff) | |
Monotonic rewrite (#874)
* Rework timer_queue and monotonic architecture
Goals:
* make Monotonic purely internal
* make Monotonic purely tick passed, no fugit involved
* create a wrapper struct in the user's code via a macro that then
converts the "now" from the tick based monotonic to a fugit based
timestamp
We need to proxy the delay functions of the timer queue anyway,
so we could simply perform the conversion in those proxy functions.
* Update cargo.lock
* Update readme of rtic-time
* CI: ESP32: Redact esp_image: Too volatile
* Fixup: Changelog double entry rebase mistake
---------
Co-authored-by: Henrik Tjäder <henrik@tjaders.com>
Diffstat (limited to 'rtic-time/src/timer_queue')
| -rw-r--r-- | rtic-time/src/timer_queue/backend.rs | 44 | ||||
| -rw-r--r-- | rtic-time/src/timer_queue/tick_type.rs | 49 |
2 files changed, 93 insertions, 0 deletions
diff --git a/rtic-time/src/timer_queue/backend.rs b/rtic-time/src/timer_queue/backend.rs new file mode 100644 index 0000000..5b71b7c --- /dev/null +++ b/rtic-time/src/timer_queue/backend.rs @@ -0,0 +1,44 @@ +use super::{TimerQueue, TimerQueueTicks}; + +/// A backend definition for a monotonic clock/counter. +pub trait TimerQueueBackend: 'static + Sized { + /// The type for ticks. + type Ticks: TimerQueueTicks; + + /// Get the current time. + fn now() -> Self::Ticks; + + /// Set the compare value of the timer interrupt. + /// + /// **Note:** This method does not need to handle race conditions of the monotonic, the timer + /// queue in RTIC checks this. + fn set_compare(instant: Self::Ticks); + + /// Clear the compare interrupt flag. + fn clear_compare_flag(); + + /// Pend the timer's interrupt. + fn pend_interrupt(); + + /// Optional. Runs on interrupt before any timer queue handling. + fn on_interrupt() {} + + /// Optional. This is used to save power, this is called when the timer queue is not empty. + /// + /// Enabling and disabling the monotonic needs to propagate to `now` so that an instant + /// based of `now()` is still valid. + /// + /// NOTE: This may be called more than once. + fn enable_timer() {} + + /// Optional. This is used to save power, this is called when the timer queue is empty. + /// + /// Enabling and disabling the monotonic needs to propagate to `now` so that an instant + /// based of `now()` is still valid. + /// + /// NOTE: This may be called more than once. + fn disable_timer() {} + + /// Returns a reference to the underlying timer queue. + fn timer_queue() -> &'static TimerQueue<Self>; +} diff --git a/rtic-time/src/timer_queue/tick_type.rs b/rtic-time/src/timer_queue/tick_type.rs new file mode 100644 index 0000000..571dfc2 --- /dev/null +++ b/rtic-time/src/timer_queue/tick_type.rs @@ -0,0 +1,49 @@ +use core::cmp; + +/// The ticks of a timer. +pub trait TimerQueueTicks: Copy + PartialEq + Eq { + /// Represents a single tick. + const ONE_TICK: Self; + + /// Compares to another tick count. + /// + /// Takes into account timer wrapping; if the difference is more than + /// half the value range, the result will be flipped. + fn compare(self, other: Self) -> cmp::Ordering; + + /// True if `self` is at the same time as `other` or later. + /// + /// Takes into account timer wrapping; if the difference is more than + /// half the value range, the result will be negated. + fn is_at_least(self, other: Self) -> bool { + match self.compare(other) { + cmp::Ordering::Less => false, + cmp::Ordering::Equal => true, + cmp::Ordering::Greater => true, + } + } + + /// Wrapping addition. + fn wrapping_add(self, other: Self) -> Self; +} + +impl TimerQueueTicks for u32 { + const ONE_TICK: Self = 1; + + fn compare(self, other: Self) -> cmp::Ordering { + (self.wrapping_sub(other) as i32).cmp(&0) + } + fn wrapping_add(self, other: Self) -> Self { + u32::wrapping_add(self, other) + } +} +impl TimerQueueTicks for u64 { + const ONE_TICK: Self = 1; + + fn compare(self, other: Self) -> cmp::Ordering { + (self.wrapping_sub(other) as i64).cmp(&0) + } + fn wrapping_add(self, other: Self) -> Self { + u64::wrapping_add(self, other) + } +} |
