Docs: By-example App priorities and message passing

This commit is contained in:
Henrik Tjäder 2021-12-16 11:54:13 +01:00
parent 2ac0e1b29d
commit c55016f4b2
2 changed files with 57 additions and 25 deletions

View file

@ -2,26 +2,41 @@
## Priorities
The static priority of each handler can be declared in the `task` attribute
using the `priority` argument. For Cortex-M, tasks can have priorities in the range `1..=(1 <<
NVIC_PRIO_BITS)` where `NVIC_PRIO_BITS` is a constant defined in the `device`
crate. When the `priority` argument is omitted, the priority is assumed to be
`1`. The `idle` task has a non-configurable static priority of `0`, the lowest priority.
The `priority` argument declares the static priority of each `task`.
For Cortex-M, tasks can have priorities in the range `1..=(1 << NVIC_PRIO_BITS)`
where `NVIC_PRIO_BITS` is a constant defined in the `device` crate.
Omitting the `priority` argument the task priority defaults to `1`.
The `idle` task has a non-configurable static priority of `0`, the lowest priority.
> A higher number means a higher priority in RTIC, which is the opposite from what
> Cortex-M does in the NVIC peripheral.
> Explicitly, this means that number `10` has a **higher** priority than number `9`.
When several tasks are ready to be executed the one with highest static
priority will be executed first. Task prioritization can be observed in the
following scenario: during the execution of a low
priority task a higher priority task is spawned; this puts the higher priority task in the pending state.
The difference in priority results in the higher priority task preempting the
lower priority one: the execution of the lower priority task is suspended and
the higher priority task is executed to completion. Once the higher priority
task has terminated the lower priority task is resumed.
The highest static priority task takes precedence when more than one
task are ready to execute.
The following example showcases the priority based scheduling of tasks.
The following scenario demonstrates task prioritization:
Spawning a higher priority task A during execution of a lower priority task B pends
task A. Task A has higher priority thus preempting task B which gets suspended
until task A completes execution. Thus, when task A completes task B resumes execution.
```text
Task Priority
┌────────────────────────────────────────────────────────┐
│ │
│ │
3 │ Preempts │
2 │ A─────────► │
1 │ B─────────► - - - - B────────► │
0 │Idle┌─────► Resumes ┌──────────► │
├────┴──────────────────────────────────┴────────────────┤
│ │
└────────────────────────────────────────────────────────┘Time
```
The following example showcases the priority based scheduling of tasks:
``` rust
{{#include ../../../../examples/preempt.rs}}
@ -33,13 +48,24 @@ $ cargo run --target thumbv7m-none-eabi --example preempt
```
Note that the task `bar` does *not* preempt task `baz` because its priority
is the *same* as `baz`'s. However, once `baz` returns, the execution of
task `bar` is prioritized over `foo` due to its higher priority. `foo`
is resumed only after `bar` returns.
is the *same* as `baz`'s. The higher priority task `bar` runs before `foo`
when `baz`returns. When `bar` returns `foo` can resume.
One more note about priorities: choosing a priority higher than what the device
supports will result in a compile error. Due to
limitations in the language, the error message is currently far from helpful: it
will say something along the lines of "evaluation of constant value failed" and
the span of the error will *not* point out to the problematic interrupt value --
we are sorry about this!
supports will result in a compilation error.
The error is cryptic due to limitations in the language,
if `priority = 9` for task `uart0_interrupt` in `example/common.rs` this looks like:
```text
error[E0080]: evaluation of constant value failed
--> examples/common.rs:10:1
|
10 | #[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `8_usize - 9_usize`, which would overflow
|
= note: this error originates in the attribute macro `rtic::app` (in Nightly builds, run with -Z macro-backtrace for more info)
```
The error message incorrectly points to the starting point of the macro, but at least the
value subtracted (in this case 9) will suggest which task causes the error.

View file

@ -1,8 +1,14 @@
# Message passing & capacity
Software tasks have support for message passing, this means that they can be spawned with an argument
as `foo::spawn(1)` which will run the task `foo` with the argument `1`. The number of arguments is not
limited and is exemplified in the following:
Software tasks support message passing, this means that software tasks can be spawned
with an argument: `foo::spawn(1)` which will run the task `foo` with the argument `1`.
Capacity sets the size of the spawn queue for the task, if not specified capacity defaults to 1.
In the example below, the capacity of task `foo` is `3`, allowing three simultaneous
pending spawns of `foo`. Exceeding this capacity is an `Error`.
The number of arguments to a task is not limited:
``` rust
{{#include ../../../../examples/message_passing.rs}}