aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan 'theJPster' Pallant <github@thejpster.org.uk>2025-06-14 20:57:26 +0000
committerEmil Fresk <emil.fresk@gmail.com>2025-06-15 10:43:43 +0000
commit53ff4feed23cffc1d35ab242e01552c8543a03af (patch)
tree64303363bc39ac446f14753aa29ee098d369a5cb
parent77a29b4e0c2bac40ec3b71c91772a01771f398be (diff)
Updates to "Delay and TImeout using Monotonics"
Some inconsistencies in the text caused confusion on my first few read-throughs, so I've tried to add some clarity.
-rw-r--r--book/en/src/by-example/delay.md22
1 files changed, 8 insertions, 14 deletions
diff --git a/book/en/src/by-example/delay.md b/book/en/src/by-example/delay.md
index 4b5f246..fa9ace9 100644
--- a/book/en/src/by-example/delay.md
+++ b/book/en/src/by-example/delay.md
@@ -1,4 +1,4 @@
-# Tasks with delay
+# Delay and Timeout using Monotonics
A convenient way to express miniminal timing requirements is by delaying progression.
@@ -53,7 +53,7 @@ Rust [`Future`]s (underlying Rust `async`/`await`) are composable. This makes it
[`Future`]: https://doc.rust-lang.org/std/future/trait.Future.html
-A common use case is transactions with an associated timeout. In the examples shown below, we introduce a fake HAL device that performs some transaction. We have modelled the time it takes based on the input parameter (`n`) as `350ms + n * 100ms`.
+A common use case is transactions with an associated timeout. In the examples shown below, we introduce a fake HAL device that performs some imagined transaction when you call `hal_get(n).await`. We have modelled the time it takes based on the input parameter (`n`) as `350ms + n * 100ms`.
Using the `select_biased` macro from the `futures` crate it may look like this:
@@ -65,9 +65,7 @@ Assuming the `hal_get` will take 450ms to finish, a short timeout of 200ms will
Extending the timeout to 1000ms would cause `hal_get` will to complete first.
-Using `select_biased` any number of futures can be combined, so its very powerful. However, as the timeout pattern is frequently used, more ergonomic support is baked into RTIC, provided by the [`rtic-monotonics`] and [`rtic-time`] crates.
-
-Rewriting the second example from above using `timeout_after` gives:
+Using `select_biased` any number of futures can be combined, so its very powerful. However, as the timeout pattern is frequently used, more ergonomic support is baked into RTIC, provided by the [`rtic-monotonics`] and [`rtic-time`] crates. Here's another example, using `Mono::delay_until` and `Mono::timeout_after`:
```rust,noplayground
{{#include ../../../../examples/lm3s6965/examples/async-timeout.rs:timeout_at_basic}}
@@ -75,19 +73,15 @@ Rewriting the second example from above using `timeout_after` gives:
In cases where you want exact control over time without drift we can use exact points in time using `Instant`, and spans of time using `Duration`. Operations on the `Instant` and `Duration` types come from the [`fugit`] crate.
-[fugit]: https://crates.io/crates/fugit
-
-`let mut instant = Systick::now()` sets the starting time of execution.
-
-We want to call `hal_get` after 1000ms relative to this starting time. This can be accomplished by using `Systick::delay_until(instant).await`.
+[`fugit`]: https://crates.io/crates/fugit
-Then, we define a point in time called `timeout`, and call `Systick::timeout_at(timeout, hal_get(n)).await`.
+`let mut instant = Mono::now()` sets the starting time of execution.
-For the first iteration of the loop, with `n == 0`, the `hal_get` will take 350ms (and finishes before the timeout).
+We want to call `hal_get` every 1000ms relative to this starting time. We accomplish this by incrementing our `instant` by 1000 ms and then using `Mono::delay_until(instant).await`. Any additional delays incurred as we iterate around this loop are compensated for by delaying until 'previous + 1000' as opposed to 'now + 1000' (which would cause our loop timing to drift).
-For the second iteration, with `n == 1`, the `hal_get` will take 450ms (and again succeeds to finish before the timeout).
+To show an alternative to the `select!` async timeout example above, we define a future point in time as `timeout`, and call `Mono::timeout_at(timeout, hal_get(n)).await`.
-For the third iteration, with `n == 2`, `hal_get` will take 550ms to finish, in which case we will run into a timeout.
+For the first iteration of the loop, with `n == 0`, the `hal_get` will take 350ms (as described above), and finishes before the timeout. For the second iteration, the delay is 450ms, which still finishes before the timeout. For the third iteration, with `n == 2`, `hal_get` will take 550ms to finish, in which case we will run into a timeout.
<details>
<summary>A complete example</summary>