aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmil Fresk <emil.fresk@gmail.com>2023-02-02 21:00:41 +0100
committerHenrik Tjäder <henrik@tjaders.com>2023-03-01 00:35:11 +0100
commitb6fdb9060bc2f19308d864c934078d8160a17ca3 (patch)
treed4c752d91d169d3b23c63cef61b6b864bd0534ff
parent82f2f0834943cd7f69130f30904f4372d39f92e7 (diff)
Simplify Systick Monotonic by integrating the TQ
-rw-r--r--rtic-monotonics/src/systick_monotonic.rs80
-rw-r--r--rtic/examples/async-delay.rs11
-rw-r--r--rtic/examples/async-timeout.rs30
3 files changed, 68 insertions, 53 deletions
diff --git a/rtic-monotonics/src/systick_monotonic.rs b/rtic-monotonics/src/systick_monotonic.rs
index 24deb54..a5a0aef 100644
--- a/rtic-monotonics/src/systick_monotonic.rs
+++ b/rtic-monotonics/src/systick_monotonic.rs
@@ -3,7 +3,7 @@
use super::Monotonic;
pub use super::{TimeoutError, TimerQueue};
use atomic_polyfill::{AtomicU32, Ordering};
-use core::ops::Deref;
+use core::future::Future;
use cortex_m::peripheral::SYST;
use embedded_hal_async::delay::DelayUs;
pub use fugit::ExtU32;
@@ -30,8 +30,7 @@ impl Systick {
/// `sysclk` and `TIMER_HZ`.
///
/// Note: Give the return value to `TimerQueue::initialize()` to initialize the timer queue.
- #[must_use]
- pub fn start(mut systick: cortex_m::peripheral::SYST, sysclk: u32) -> Self {
+ pub fn start(mut systick: cortex_m::peripheral::SYST, sysclk: u32) {
// + TIMER_HZ / 2 provides round to nearest instead of round to 0.
// - 1 as the counter range is inclusive [0, reload]
let reload = (sysclk + TIMER_HZ / 2) / TIMER_HZ - 1;
@@ -45,7 +44,7 @@ impl Systick {
systick.enable_interrupt();
systick.enable_counter();
- Systick {}
+ SYSTICK_TIMER_QUEUE.initialize(Systick {});
}
fn systick() -> SYST {
@@ -54,6 +53,44 @@ impl Systick {
}
static SYSTICK_CNT: AtomicU32 = AtomicU32::new(0);
+static SYSTICK_TIMER_QUEUE: TimerQueue<Systick> = TimerQueue::new();
+
+// Forward timerqueue interface
+impl Systick {
+ /// Used to access the underlying timer queue
+ #[doc(hidden)]
+ pub fn __tq() -> &'static TimerQueue<Systick> {
+ &SYSTICK_TIMER_QUEUE
+ }
+
+ /// Timeout at a specific time.
+ pub async fn timeout_at<F: Future>(
+ instant: <Self as Monotonic>::Instant,
+ future: F,
+ ) -> Result<F::Output, TimeoutError> {
+ SYSTICK_TIMER_QUEUE.timeout_at(instant, future).await
+ }
+
+ /// Timeout after a specific duration.
+ #[inline]
+ pub async fn timeout_after<F: Future>(
+ duration: <Self as Monotonic>::Duration,
+ future: F,
+ ) -> Result<F::Output, TimeoutError> {
+ SYSTICK_TIMER_QUEUE.timeout_after(duration, future).await
+ }
+
+ /// Delay for some duration of time.
+ #[inline]
+ pub async fn delay(duration: <Self as Monotonic>::Duration) {
+ SYSTICK_TIMER_QUEUE.delay(duration).await;
+ }
+
+ /// Delay to some specific time instant.
+ pub async fn delay_until(instant: <Self as Monotonic>::Instant) {
+ SYSTICK_TIMER_QUEUE.delay_until(instant).await;
+ }
+}
impl Monotonic for Systick {
type Instant = fugit::TimerInstantU32<TIMER_HZ>;
@@ -92,49 +129,28 @@ impl Monotonic for Systick {
fn disable_timer() {}
}
-/// Timer queue wrapper to implement traits on
-pub struct SystickTimerQueue(TimerQueue<Systick>);
-
-impl SystickTimerQueue {
- /// Create a new timer queue.
- pub const fn new() -> Self {
- Self(TimerQueue::new())
- }
-}
-
-impl Deref for SystickTimerQueue {
- type Target = TimerQueue<Systick>;
-
- #[inline(always)]
- fn deref(&self) -> &Self::Target {
- &self.0
- }
-}
-
-impl DelayUs for SystickTimerQueue {
+impl DelayUs for Systick {
type Error = core::convert::Infallible;
async fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
- self.delay(us.micros()).await;
+ SYSTICK_TIMER_QUEUE.delay(us.micros()).await;
Ok(())
}
async fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> {
- self.delay(ms.millis()).await;
+ SYSTICK_TIMER_QUEUE.delay(ms.millis()).await;
Ok(())
}
}
-/// Register the Systick interrupt and crate a timer queue with a specific name and speed.
+/// Register the Systick interrupt for the monotonic.
#[macro_export]
-macro_rules! make_systick_timer_queue {
- ($timer_queue_name:ident) => {
- static $timer_queue_name: SystickTimerQueue = SystickTimerQueue::new();
-
+macro_rules! make_systick_handler {
+ () => {
#[no_mangle]
#[allow(non_snake_case)]
unsafe extern "C" fn SysTick() {
- $timer_queue_name.on_monotonic_interrupt();
+ Systick::__tq().on_monotonic_interrupt();
}
};
}
diff --git a/rtic/examples/async-delay.rs b/rtic/examples/async-delay.rs
index aa673dd..0988346 100644
--- a/rtic/examples/async-delay.rs
+++ b/rtic/examples/async-delay.rs
@@ -11,7 +11,7 @@ mod app {
use cortex_m_semihosting::{debug, hprintln};
use rtic_monotonics::systick_monotonic::*;
- rtic_monotonics::make_systick_timer_queue!(TIMER);
+ rtic_monotonics::make_systick_handler!();
#[shared]
struct Shared {}
@@ -23,8 +23,7 @@ mod app {
fn init(cx: init::Context) -> (Shared, Local) {
hprintln!("init");
- let systick = Systick::start(cx.core.SYST, 12_000_000);
- TIMER.initialize(systick);
+ Systick::start(cx.core.SYST, 12_000_000);
foo::spawn().ok();
bar::spawn().ok();
@@ -45,21 +44,21 @@ mod app {
#[task]
async fn foo(_cx: foo::Context) {
hprintln!("hello from foo");
- TIMER.delay(100.millis()).await;
+ Systick::delay(100.millis()).await;
hprintln!("bye from foo");
}
#[task]
async fn bar(_cx: bar::Context) {
hprintln!("hello from bar");
- TIMER.delay(200.millis()).await;
+ Systick::delay(200.millis()).await;
hprintln!("bye from bar");
}
#[task]
async fn baz(_cx: baz::Context) {
hprintln!("hello from baz");
- TIMER.delay(300.millis()).await;
+ Systick::delay(300.millis()).await;
hprintln!("bye from baz");
debug::exit(debug::EXIT_SUCCESS);
diff --git a/rtic/examples/async-timeout.rs b/rtic/examples/async-timeout.rs
index 30fee43..a850b10 100644
--- a/rtic/examples/async-timeout.rs
+++ b/rtic/examples/async-timeout.rs
@@ -12,8 +12,9 @@ use rtic_monotonics::systick_monotonic::*;
mod app {
use super::*;
use futures::{future::FutureExt, select_biased};
+ use rtic_monotonics::Monotonic;
- rtic_monotonics::make_systick_timer_queue!(TIMER);
+ rtic_monotonics::make_systick_handler!();
#[shared]
struct Shared {}
@@ -25,8 +26,7 @@ mod app {
fn init(cx: init::Context) -> (Shared, Local) {
hprintln!("init");
- let systick = Systick::start(cx.core.SYST, 12_000_000);
- TIMER.initialize(systick);
+ Systick::start(cx.core.SYST, 12_000_000);
foo::spawn().ok();
@@ -37,37 +37,37 @@ mod app {
async fn foo(_cx: foo::Context) {
// Call hal with short relative timeout using `select_biased`
select_biased! {
- v = hal_get(&TIMER, 1).fuse() => hprintln!("hal returned {}", v),
- _ = TIMER.delay(200.millis()).fuse() => hprintln!("timeout", ), // this will finish first
+ v = hal_get(1).fuse() => hprintln!("hal returned {}", v),
+ _ = Systick::delay(200.millis()).fuse() => hprintln!("timeout", ), // this will finish first
}
// Call hal with long relative timeout using `select_biased`
select_biased! {
- v = hal_get(&TIMER, 1).fuse() => hprintln!("hal returned {}", v), // hal finish first
- _ = TIMER.delay(1000.millis()).fuse() => hprintln!("timeout", ),
+ v = hal_get(1).fuse() => hprintln!("hal returned {}", v), // hal finish first
+ _ = Systick::delay(1000.millis()).fuse() => hprintln!("timeout", ),
}
// Call hal with long relative timeout using monotonic `timeout_after`
- match TIMER.timeout_after(1000.millis(), hal_get(&TIMER, 1)).await {
+ match Systick::timeout_after(1000.millis(), hal_get(1)).await {
Ok(v) => hprintln!("hal returned {}", v),
_ => hprintln!("timeout"),
}
// get the current time instance
- let mut instant = TIMER.now();
+ let mut instant = Systick::now();
// do this 3 times
for n in 0..3 {
// exact point in time without drift
instant += 1000.millis();
- TIMER.delay_until(instant).await;
+ Systick::delay_until(instant).await;
// exact point it time for timeout
let timeout = instant + 500.millis();
- hprintln!("now is {:?}, timeout at {:?}", TIMER.now(), timeout);
+ hprintln!("now is {:?}, timeout at {:?}", Systick::now(), timeout);
- match TIMER.timeout_at(timeout, hal_get(&TIMER, n)).await {
- Ok(v) => hprintln!("hal returned {} at time {:?}", v, TIMER.now()),
+ match Systick::timeout_at(timeout, hal_get(n)).await {
+ Ok(v) => hprintln!("hal returned {} at time {:?}", v, Systick::now()),
_ => hprintln!("timeout"),
}
}
@@ -77,11 +77,11 @@ mod app {
}
// Emulate some hal
-async fn hal_get(timer: &'static SystickTimerQueue, n: u32) -> u32 {
+async fn hal_get(n: u32) -> u32 {
// emulate some delay time dependent on n
let d = 350.millis() + n * 100.millis();
hprintln!("the hal takes a duration of {:?}", d);
- timer.delay(d).await;
+ Systick::delay(d).await;
// emulate some return value
5
}