aboutsummaryrefslogtreecommitdiff
path: root/rtic-time/src/timer_queue
diff options
context:
space:
mode:
authorFinomnis <Finomnis@users.noreply.github.com>2024-04-11 00:00:38 +0200
committerGitHub <noreply@github.com>2024-04-10 22:00:38 +0000
commit8c23e178f3838bcdd13662a2ffefd39ec144e869 (patch)
treef2d2cefcd6bb2876e74ee6035b5489a4a2d9590f /rtic-time/src/timer_queue
parente4cc5fd17b8a2df332af0ee25c8bd7092e66afb0 (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.rs44
-rw-r--r--rtic-time/src/timer_queue/tick_type.rs49
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)
+ }
+}