aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--book/en/src/by-example/delay.md49
-rw-r--r--rtic/examples/async-timeout.rs4
2 files changed, 28 insertions, 25 deletions
diff --git a/book/en/src/by-example/delay.md b/book/en/src/by-example/delay.md
index 8d05d7ce..f2863633 100644
--- a/book/en/src/by-example/delay.md
+++ b/book/en/src/by-example/delay.md
@@ -6,13 +6,14 @@ This can be achieved by instantiating a monotonic timer:
``` rust
...
-rtic_monotonics::make_systick_timer_queue!(TIMER);
+rtic_monotonics::make_systick_handler!();
#[init]
-fn init(cx: init::Context) -> (Shared, Local) {
- let systick = Systick::start(cx.core.SYST, 12_000_000);
- TIMER.initialize(systick);
- ...
+fn init(cx: init::Context) -> (Shared, Local) {
+ hprintln!("init");
+
+ Systick::start(cx.core.SYST, 12_000_000);
+ ...
```
A *software* task can `await` the delay to expire:
@@ -21,8 +22,10 @@ A *software* task can `await` the delay to expire:
#[task]
async fn foo(_cx: foo::Context) {
...
- TIMER.delay(100.millis()).await;
+ Systick::delay(100.millis()).await;
...
+}
+
```
Technically, the timer queue is implemented as a list based priority queue, where list-nodes are statically allocated as part of the underlying task `Future`. Thus, the timer queue is infallible at run-time (its size and allocation is determined at compile time).
@@ -51,21 +54,21 @@ A common use case is transactions with associated timeout. In the examples shown
Using the `select_biased` macro from the `futures` crate it may look like this:
-```rust
+``` rust
// 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
}
```
Assuming the `hal_get` will take 450ms to finish, a short timeout of 200ms will expire.
-```rust
+``` rust
// 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", ),
}
```
@@ -73,9 +76,9 @@ By extending the timeout to 1000ms, the `hal_get` will finish first.
Using `select_biased` any number of futures can be combined, so its very powerful. However, as the timeout pattern is frequently used, it is directly supported by the RTIC [rtc-monotonics] and [rtic-time] crates. The second example from above using `timeout_after`:
-```rust
+``` rust
// 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"),
}
@@ -85,28 +88,28 @@ In cases you want exact control over time without drift. For this purpose we can
[fugit]: https://crates.io/crates/fugit
-```rust
+``` rust
// 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
+ // absolute point in time without drift
instant += 1000.millis();
- TIMER.delay_until(instant).await;
+ Systick::delay_until(instant).await;
- // exact point it time for timeout
+ // absolute 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"),
}
}
```
-`instant = TIMER.now()` gives the baseline (i.e., the exact current point in time). We want to call `hal_get` after 1000ms relative to this exact point in time. This can be accomplished by `TIMER.delay_until(instant).await;`. We define the absolute point in time for the `timeout`, and call `TIMER.timeout_at(timeout, hal_get(&TIMER, n)).await`. For the first loop iteration `n == 0`, and the `hal_get` will take 350ms (and finishes before the timeout). For the second iteration `n == 1`, and `hal_get` will take 450ms (and again succeeds to finish before the timeout). For the third iteration `n == 2` (`hal_get` will take 5500ms to finish). In this case we will run into a timeout.
+`instant = Systick::now()` gives the baseline (i.e., the absolute current point in time). We want to call `hal_get` after 1000ms relative to this absolute point in time. This can be accomplished by `Systick::delay_until(instant).await;`. We define the absolute point in time for the `timeout`, and call `Systick::timeout_at(timeout, hal_get(n)).await`. For the first loop iteration `n == 0`, and the `hal_get` will take 350ms (and finishes before the timeout). For the second iteration `n == 1`, and `hal_get` will take 450ms (and again succeeds to finish before the timeout). For the third iteration `n == 2` (`hal_get` will take 5500ms to finish). In this case we will run into a timeout.
The complete example:
diff --git a/rtic/examples/async-timeout.rs b/rtic/examples/async-timeout.rs
index fda385aa..cdccb3a4 100644
--- a/rtic/examples/async-timeout.rs
+++ b/rtic/examples/async-timeout.rs
@@ -61,11 +61,11 @@ mod app {
// do this 3 times
for n in 0..3 {
- // exact point in time without drift
+ // absolute point in time without drift
instant += 1000.millis();
Systick::delay_until(instant).await;
- // exact point it time for timeout
+ // absolute point it time for timeout
let timeout = instant + 500.millis();
hprintln!("now is {:?}, timeout at {:?}", Systick::now(), timeout);