diff options
| author | Emil Fresk <emil.fresk@gmail.com> | 2021-09-22 13:22:45 +0200 |
|---|---|---|
| committer | Emil Fresk <emil.fresk@gmail.com> | 2021-09-23 16:11:04 +0200 |
| commit | b71df58f2fb4ed85d4c8cf806d5837ce63c73f31 (patch) | |
| tree | de4cbe4b43d399d4dcf2021c33225ccd00627434 /book/en/src/by-example/tasks.md | |
| parent | c8621d78b9b1c0c67dff31404ade873a9d7b426e (diff) | |
The great docs update
Diffstat (limited to 'book/en/src/by-example/tasks.md')
| -rw-r--r-- | book/en/src/by-example/tasks.md | 118 |
1 files changed, 0 insertions, 118 deletions
diff --git a/book/en/src/by-example/tasks.md b/book/en/src/by-example/tasks.md deleted file mode 100644 index 8558a54..0000000 --- a/book/en/src/by-example/tasks.md +++ /dev/null @@ -1,118 +0,0 @@ -# Software tasks - -In addition to hardware tasks, which are invoked by the hardware in response to -hardware events, RTIC also supports *software* tasks which can be spawned by the -application from any execution context. - -Software tasks can also be assigned priorities and, under the hood, are -dispatched from interrupt handlers. RTIC requires that free interrupts are -declared in the `dispatchers` app argument when using software tasks; some of these free -interrupts will be used to dispatch the software tasks. An advantage of software -tasks over hardware tasks is that many tasks can be mapped to a single interrupt -handler. - -Software tasks are also declared using the `task` attribute but the `binds` -argument must be omitted. - -The example below showcases three software tasks that run at 2 different -priorities. The three software tasks are mapped to 2 interrupts handlers. - -``` rust -{{#include ../../../../examples/task.rs}} -``` - -``` console -$ cargo run --example task -{{#include ../../../../ci/expected/task.run}} -``` - -## Message passing - -The other advantage of software tasks is that messages can be passed to these -tasks when spawning them. The type of the message payload must be specified in -the signature of the task handler. - -The example below showcases three tasks, two of them expect a message. - -``` rust -{{#include ../../../../examples/message.rs}} -``` - -``` console -$ cargo run --example message -{{#include ../../../../ci/expected/message.run}} -``` - -## Capacity - -RTIC does *not* perform any form of heap-based memory allocation. The memory -required to store messages is statically reserved. By default the framework -minimizes the memory footprint of the application so each task has a message -"capacity" of 1: meaning that at most one message can be posted to the task -before it gets a chance to run. This default can be overridden for each task -using the `capacity` argument. This argument takes a positive integer that -indicates how many messages the task message buffer can hold. - -The example below sets the capacity of the software task `foo` to 4. If the -capacity is not specified then the second `spawn.foo` call in `UART0` would -fail (panic). - -``` rust -{{#include ../../../../examples/capacity.rs}} -``` - -``` console -$ cargo run --example capacity -{{#include ../../../../ci/expected/capacity.run}} -``` - -## Error handling - -The `spawn` API returns the `Err` variant when there's no space to send the -message. In most scenarios spawning errors are handled in one of two ways: - -- Panicking, using `unwrap`, `expect`, etc. This approach is used to catch the - programmer error (i.e. bug) of selecting a capacity that was too small. When - this panic is encountered during testing choosing a bigger capacity and - recompiling the program may fix the issue but sometimes it's necessary to dig - deeper and perform a timing analysis of the application to check if the - platform can deal with peak payload or if the processor needs to be replaced - with a faster one. - -- Ignoring the result. In soft real-time and non real-time applications it may - be OK to occasionally lose data or fail to respond to some events during event - bursts. In those scenarios silently letting a `spawn` call fail may be - acceptable. - -It should be noted that retrying a `spawn` call is usually the wrong approach as -this operation will likely never succeed in practice. Because there are only -context switches towards *higher* priority tasks retrying the `spawn` call of a -lower priority task will never let the scheduler dispatch said task meaning that -its message buffer will never be emptied. This situation is depicted in the -following snippet: - -``` rust -#[rtic::app(..)] -mod app { - #[init(spawn = [foo, bar])] - fn init(cx: init::Context) { - cx.spawn.foo().unwrap(); - cx.spawn.bar().unwrap(); - } - - #[task(priority = 2, spawn = [bar])] - fn foo(cx: foo::Context) { - // .. - - // the program will get stuck here - while cx.spawn.bar(payload).is_err() { - // retry the spawn call if it failed - } - } - - #[task(priority = 1)] - fn bar(cx: bar::Context, payload: i32) { - // .. - } -} -``` |
