Docs: By-example Monotonics

This commit is contained in:
Henrik Tjäder 2021-12-16 21:34:46 +01:00
parent c55016f4b2
commit 833e22da51

View file

@ -1,33 +1,38 @@
# Monotonic & spawn_{at/after}
The understanding of time is an important concept in embedded systems, and to be able to run tasks
based on time is very useful. For this use-case the framework provides the static methods
based on time is useful. For this use-case the framework provides the static methods
`task::spawn_after(/* duration */)` and `task::spawn_at(/* specific time instant */)`.
Mostly one uses `spawn_after`, but in cases where it's needed to have spawns happen without drift or
to a fixed baseline `spawn_at` is available.
`spawn_after` is more commonly used, but in cases where it's needed to have spawns happen
without drift or to a fixed baseline `spawn_at` is available.
To support this the `#[monotonic]` attribute exists which is applied to a type alias definition.
The `#[monotonic]` attribute, applied to a type alias definition, exists to support this.
This type alias must point to a type which implements the [`rtic_monotonic::Monotonic`] trait.
This is generally some timer which handles the timing of the system. One or more monotonics can be
used in the same system, for example a slow timer that is used to wake the system from sleep and another
that is used for high granularity scheduling while the system is awake.
This is generally some timer which handles the timing of the system.
One or more monotonics can coexist in the same system, for example a slow timer that wakes the
system from sleep and another which purpose is for high granularity scheduling while the
system is awake.
[`rtic_monotonic::Monotonic`]: https://docs.rs/rtic-monotonic
The attribute has one required parameter and two optional parameters, `binds`, `default` and
`priority` respectively. `binds = InterruptName` defines which interrupt vector is associated to
the timer's interrupt, `default = true` enables a shorthand API when spawning and accessing the
time (`monotonics::now()` vs `monotonics::MyMono::now()`), and `priority` sets the priority the
interrupt vector has.
`priority` respectively.
The required parameter, `binds = InterruptName`, associates an interrupt vector to the timer's
interrupt, while `default = true` enables a shorthand API when spawning and accessing
time (`monotonics::now()` vs `monotonics::MyMono::now()`), and `priority` sets the priority
of the interrupt vector.
> By default `priority` is set to the **maximum priority** of the system but a lower priority
> can be selected if a high priority task cannot take the jitter introduced by the scheduling.
> This can however introduce jitter and delays into the scheduling, making it a trade-off.
> The default `priority` is the **maximum priority** of the system.
> If your system has a high priority task with tight scheduling requirements,
> it might be desirable to demote the `monotonic` task to a lower priority
> to reduce scheduling jitter for the high priority task.
> This however might introduce jitter and delays into scheduling via the `monotonic`,
> making it a trade-off.
Finally, the monotonics must be initialized in `#[init]` and returned in the `init::Monotonic( ... )` tuple.
This moves the monotonics into the active state which makes it possible to use them.
The monotonics are initialized in `#[init]` and returned within the `init::Monotonic( ... )` tuple.
This activates the monotonics making it possible to use them.
An example is provided below:
See the following example:
``` rust
{{#include ../../../../examples/schedule.rs}}
@ -40,8 +45,8 @@ $ cargo run --target thumbv7m-none-eabi --example message
## Canceling or rescheduling a scheduled task
Tasks spawned using `task::spawn_after` and `task::spawn_at` has as returns a `SpawnHandle`,
where the `SpawnHandle` can be used to cancel or reschedule a task that will run in the future.
Tasks spawned using `task::spawn_after` and `task::spawn_at` returns a `SpawnHandle`,
which allows canceling or rescheduling of the task scheduled to run in the future.
If `cancel` or `reschedule_at`/`reschedule_after` returns an `Err` it means that the operation was
too late and that the task is already sent for execution. The following example shows this in action: