aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bors[bot] <26634292+bors[bot]@users.noreply.github.com> 2021-12-21 19:02:49 +0000
committerGravatar GitHub <noreply@github.com> 2021-12-21 19:02:49 +0000
commitc78177c37e3192c7a41a3ea8e7c139751c1a8989 (patch)
treed5092fa9f154994c27f710f3ec4cacdb651fd96d
parent37facfb5bf9aca11c43868cb8880b12b9f6b336a (diff)
parente249813ad7a5670dd9a1a70d46b72aa02ce4dce0 (diff)
downloadrtic-c78177c37e3192c7a41a3ea8e7c139751c1a8989.tar.gz
rtic-c78177c37e3192c7a41a3ea8e7c139751c1a8989.tar.zst
rtic-c78177c37e3192c7a41a3ea8e7c139751c1a8989.zip
Merge #563
563: Docs touchup r=korken89 a=AfoHT Unleashed some language linters on the book Co-authored-by: Henrik Tjäder <henrik@grepit.se> Co-authored-by: perlindgren <per.lindgren@ltu.se>
-rw-r--r--book/en/src/awesome_rtic.md7
-rw-r--r--book/en/src/by-example.md14
-rw-r--r--book/en/src/by-example/app.md14
-rw-r--r--book/en/src/by-example/app_idle.md18
-rw-r--r--book/en/src/by-example/app_init.md22
-rw-r--r--book/en/src/by-example/app_priorities.md70
-rw-r--r--book/en/src/by-example/app_task.md15
-rw-r--r--book/en/src/by-example/hardware_tasks.md25
-rw-r--r--book/en/src/by-example/message_passing.md12
-rw-r--r--book/en/src/by-example/monotonic.md43
-rw-r--r--book/en/src/by-example/resources.md41
-rw-r--r--book/en/src/by-example/software_tasks.md42
-rw-r--r--book/en/src/by-example/starting_a_project.md6
-rw-r--r--book/en/src/by-example/tips_destructureing.md5
-rw-r--r--book/en/src/by-example/tips_from_ram.md3
-rw-r--r--book/en/src/by-example/tips_indirection.md5
-rw-r--r--book/en/src/by-example/tips_monotonic_impl.md26
-rw-r--r--book/en/src/by-example/tips_static_lifetimes.md16
-rw-r--r--book/en/src/by-example/tips_view_code.md8
-rw-r--r--book/en/src/migration.md2
-rw-r--r--book/en/src/migration/migration_v4.md76
-rw-r--r--book/en/src/migration/migration_v5.md10
-rw-r--r--book/en/src/preface.md2
23 files changed, 294 insertions, 188 deletions
diff --git a/book/en/src/awesome_rtic.md b/book/en/src/awesome_rtic.md
index 925cd3fd..36d38e62 100644
--- a/book/en/src/awesome_rtic.md
+++ b/book/en/src/awesome_rtic.md
@@ -1 +1,8 @@
# Awesome RTIC examples
+
+See the [`rtic-rs/rtic-examples`][rticexamples] repository for community
+provided complete examples.
+
+Pull-requests to this repo are welcome!
+
+[rticexamples]: https://github.com/rtic-rs/rtic-examples
diff --git a/book/en/src/by-example.md b/book/en/src/by-example.md
index fef6872e..84f00193 100644
--- a/book/en/src/by-example.md
+++ b/book/en/src/by-example.md
@@ -3,15 +3,15 @@
This part of the book introduces the Real-Time Interrupt-driven Concurrency (RTIC) framework
to new users by walking them through examples of increasing complexity.
-All examples in this part of the book can be found in the GitHub [repository] of
-the project. The examples can be run on QEMU (emulating a Cortex M3 target) so no special hardware
-is required to follow along.
+All examples in this part of the book are accessible at the
+[GitHub repository][repoexamples].
+The examples are runnable on QEMU (emulating a Cortex M3 target),
+thus no special hardware required to follow along.
-[repository]: https://github.com/rtic-rs/cortex-m-rtic
+[repoexamples]: https://github.com/rtic-rs/cortex-m-rtic/tree/master/examples
-To run the examples on your computer you'll need the `qemu-system-arm`
-program. Check [the embedded Rust book] for instructions on how to set up an
+To run the examples with QEMU you will need the `qemu-system-arm` program.
+Check [the embedded Rust book] for instructions on how to set up an
embedded development environment that includes QEMU.
[the embedded Rust book]: https://rust-embedded.github.io/book/intro/install.html
-
diff --git a/book/en/src/by-example/app.md b/book/en/src/by-example/app.md
index 09f3371e..2c6aca7a 100644
--- a/book/en/src/by-example/app.md
+++ b/book/en/src/by-example/app.md
@@ -3,14 +3,14 @@
## Requirements on the `app` attribute
All RTIC applications use the [`app`] attribute (`#[app(..)]`). This attribute
-must be applied to a `mod`-item containing the RTIC application. The `app`
-attribute has a mandatory `device`
-argument that takes a *path* as a value. This must be a full path pointing to a
+only applies to a `mod`-item containing the RTIC application. The `app`
+attribute has a mandatory `device` argument that takes a *path* as a value.
+This must be a full path pointing to a
*peripheral access crate* (PAC) generated using [`svd2rust`] **v0.14.x** or
newer.
-The `app` attribute will expand into a suitable entry point so it's not required
-to use the [`cortex_m_rt::entry`] attribute.
+The `app` attribute will expand into a suitable entry point and thus replaces
+the use of the [`cortex_m_rt::entry`] attribute.
[`app`]: ../../../api/cortex_m_rtic_macros/attr.app.html
[`svd2rust`]: https://crates.io/crates/svd2rust
@@ -18,9 +18,9 @@ to use the [`cortex_m_rt::entry`] attribute.
## An RTIC application example
-To give a flavor of RTIC, the following example contains commonly used features. In the following sections we will go through each feature in detail.
+To give a flavour of RTIC, the following example contains commonly used features.
+In the following sections we will go through each feature in detail.
``` rust
{{#include ../../../../examples/common.rs}}
```
-
diff --git a/book/en/src/by-example/app_idle.md b/book/en/src/by-example/app_idle.md
index 66f40497..537902a4 100644
--- a/book/en/src/by-example/app_idle.md
+++ b/book/en/src/by-example/app_idle.md
@@ -1,14 +1,18 @@
# The background task `#[idle]`
A function marked with the `idle` attribute can optionally appear in the
-module. This function is used as the special *idle task* and must have
-signature `fn(idle::Context) -> !`.
+module. This becomes the special *idle task* and must have signature
+`fn(idle::Context) -> !`.
When present, the runtime will execute the `idle` task after `init`. Unlike
-`init`, `idle` will run *with interrupts enabled* and it's not allowed to return
-so it must run forever.
+`init`, `idle` will run *with interrupts enabled* and must never return,
+as the `-> !` function signature indicates.
+[The Rust type `!` means “never”][nevertype].
-Like in `init`, locally declared resources will have `'static` lifetimes that are safe to access.
+[nevertype]: https://doc.rust-lang.org/core/primitive.never.html
+
+Like in `init`, locally declared resources will have `'static` lifetimes that
+are safe to access.
The example below shows that `idle` runs after `init`.
@@ -21,9 +25,9 @@ $ cargo run --target thumbv7m-none-eabi --example idle
{{#include ../../../../ci/expected/idle.run}}
```
-By default the RTIC `idle` task does not try to optimise for any specific targets.
+By default, the RTIC `idle` task does not try to optimize for any specific targets.
-A common useful optimisation is to enable the [SLEEPONEXIT] and allow the MCU
+A common useful optimization is to enable the [SLEEPONEXIT] and allow the MCU
to enter sleep when reaching `idle`.
>**Caution** some hardware unless configured disables the debug unit during sleep mode.
diff --git a/book/en/src/by-example/app_init.md b/book/en/src/by-example/app_init.md
index 3112ccf9..615c2991 100644
--- a/book/en/src/by-example/app_init.md
+++ b/book/en/src/by-example/app_init.md
@@ -1,14 +1,22 @@
# App initialization and the `#[init]` task
-An RTIC application is required an `init` task setting up the system. The corresponding function must have the signature `fn(init::Context) -> (Shared, Local, init::Monotonics)`, where `Shared` and `Local` are the resource structures defined by the user.
+An RTIC application requires an `init` task setting up the system. The corresponding `init` function must have the
+signature `fn(init::Context) -> (Shared, Local, init::Monotonics)`, where `Shared` and `Local` are the resource
+structures defined by the user.
-On system reset, the `init` task is executed (after the optionally defined `pre-init` and internal RTIC initialization). The `init` task runs *with interrupts disabled* and has exclusive access to Cortex-M (the `bare_metal::CriticalSection` token is available as `cs`) while device specific peripherals are available through the `core` and `device` fields of `init::Context`.
+The `init` task executes after system reset (after the optionally defined `pre-init` and internal RTIC
+initialization). The `init` task runs *with interrupts disabled* and has exclusive access to Cortex-M (the
+`bare_metal::CriticalSection` token is available as `cs`) while device specific peripherals are available through
+the `core` and `device` fields of `init::Context`.
## Example
-The example below shows the types of the `core`, `device` and `cs` fields, and showcases the use of a `local` variable with `'static` lifetime. As we will see later, such variables can later be delegated from `init` to other tasks of the RTIC application.
+The example below shows the types of the `core`, `device` and `cs` fields, and showcases the use of a `local`
+variable with `'static` lifetime.
+Such variables can be delegated from the `init` task to other tasks of the RTIC application.
-The `device` field is only available when the `peripherals` argument is set to `true` (which is the default). In the rare case you want to implement an ultra-slim application you can explicitly set `peripherals` to `false`.
+The `device` field is available when the `peripherals` argument is set to the default value `true`.
+In the rare case you want to implement an ultra-slim application you can explicitly set `peripherals` to `false`.
``` rust
{{#include ../../../../examples/init.rs}}
@@ -16,13 +24,13 @@ The `device` field is only available when the `peripherals` argument is set to `
Running the example will print `init` to the console and then exit the QEMU process.
-``` console
+``` console
$ cargo run --target thumbv7m-none-eabi --example init
{{#include ../../../../ci/expected/init.run}}
```
> **NOTE**: You can choose target device by passing a target
-> triple to cargo (e.g `cargo run --example init --target thumbv7m-none-eabi`) or
+> triple to cargo (e.g. `cargo run --example init --target thumbv7m-none-eabi`) or
> configure a default target in `.cargo/config.toml`.
>
-> For running the examples, we use a Cortex M3 emulated in QEMU so the target is `thumbv7m-none-eabi`.
+> For running the examples, we use a Cortex M3 emulated in QEMU, so the target is `thumbv7m-none-eabi`.
diff --git a/book/en/src/by-example/app_priorities.md b/book/en/src/by-example/app_priorities.md
index 934359d5..1a92ec84 100644
--- a/book/en/src/by-example/app_priorities.md
+++ b/book/en/src/by-example/app_priorities.md
@@ -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 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.
+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.
diff --git a/book/en/src/by-example/app_task.md b/book/en/src/by-example/app_task.md
index a5c8b171..97160041 100644
--- a/book/en/src/by-example/app_task.md
+++ b/book/en/src/by-example/app_task.md
@@ -1,7 +1,18 @@
# Defining tasks with `#[task]`
-Tasks, defined with `#[task]`, are the main mechanism of getting work done in RTIC. Every task can be spawned, now or later, be sent messages (message passing) and be given priorities for preemptive multitasking.
+Tasks, defined with `#[task]`, are the main mechanism of getting work done in RTIC.
-There are two kinds of tasks, software tasks and hardware tasks, and the difference is that hardware tasks are bound to a specific interrupt vector in the MCU while software tasks are not. This means that if a hardware task is bound to the UART's RX interrupt the task will run every time a character is received.
+Tasks can
+
+* Be spawned (now or in the future)
+* Receive messages (message passing)
+* Prioritized allowing preemptive multitasking
+* Optionally bind to a hardware interrupt
+
+RTIC makes a distinction between “software tasks” and “hardware tasks”.
+Hardware tasks are tasks that are bound to a specific interrupt vector in the MCU while software tasks are not.
+
+This means that if a hardware task is bound to an UART RX interrupt the task will run every
+time this interrupt triggers, usually when a character is received.
In the coming pages we will explore both tasks and the different options available.
diff --git a/book/en/src/by-example/hardware_tasks.md b/book/en/src/by-example/hardware_tasks.md
index d5968761..30b88d0d 100644
--- a/book/en/src/by-example/hardware_tasks.md
+++ b/book/en/src/by-example/hardware_tasks.md
@@ -1,17 +1,21 @@
# Hardware tasks
-At its core RTIC is based on using the interrupt controller in the hardware to do scheduling and
-run tasks, as all tasks in the framework are run as interrupt handlers (except `#[init]` and
-`#[idle]`). This also means that you can directly bind tasks to interrupt handlers.
+At its core RTIC is using the hardware interrupt controller ([ARM NVIC on cortex-m][NVIC])
+to perform scheduling and executing tasks, and all tasks except `#[init]` and `#[idle]`
+run as interrupt handlers.
+This also means that you can manually bind tasks to interrupt handlers.
-To declare interrupt handlers the `#[task]` attribute takes a `binds = InterruptName` argument whose
-value is the name of the interrupt to which the handler will be bound to; the
-function used with this attribute becomes the interrupt handler. Within the
-framework these type of tasks are referred to as *hardware* tasks, because they
-start executing in reaction to a hardware event.
+To bind an interrupt use the `#[task]` attribute argument `binds = InterruptName`.
+This task becomes the interrupt handler for this hardware interrupt vector.
-Providing an interrupt name that does not exist will cause a compile error to help with accidental
-errors.
+All tasks bound to an explicit interrupt are *hardware tasks* since they
+start execution in reaction to a hardware event.
+
+Specifying a non-existing interrupt name will cause a compilation error. The interrupt names
+are commonly defined by [PAC or HAL][pacorhal] crates.
+
+[pacorhal]: https://docs.rust-embedded.org/book/start/registers.html
+[NVIC]: https://developer.arm.com/documentation/100166/0001/Nested-Vectored-Interrupt-Controller/NVIC-functional-description/NVIC-interrupts
The example below demonstrates the use of the `#[task]` attribute to declare an
interrupt handler.
@@ -24,4 +28,3 @@ interrupt handler.
$ cargo run --target thumbv7m-none-eabi --example hardware
{{#include ../../../../ci/expected/hardware.run}}
```
-
diff --git a/book/en/src/by-example/message_passing.md b/book/en/src/by-example/message_passing.md
index b80ae03c..0dc8f858 100644
--- a/book/en/src/by-example/message_passing.md
+++ b/book/en/src/by-example/message_passing.md
@@ -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}}
diff --git a/book/en/src/by-example/monotonic.md b/book/en/src/by-example/monotonic.md
index c2a5d86c..0c8e15ae 100644
--- a/book/en/src/by-example/monotonic.md
+++ b/book/en/src/by-example/monotonic.md
@@ -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 fine grained 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:
diff --git a/book/en/src/by-example/resources.md b/book/en/src/by-example/resources.md
index 71092b2f..9f2c6c57 100644
--- a/book/en/src/by-example/resources.md
+++ b/book/en/src/by-example/resources.md
@@ -1,22 +1,22 @@
# Resource usage
-The RTIC framework manages shared and task local resources which allows data to be persistently
-stored and safely accessed without the use of unsafe code.
+The RTIC framework manages shared and task local resources allowing persistent data
+storage and safe accesses without the use of `unsafe` code.
RTIC resources are visible only to functions declared within the `#[app]` module and the framework
gives the user complete control (on a per-task basis) over resource accessibility.
-System wide resources are declared as **two** `struct`'s within the `#[app]` module annotated with
-the attribute `#[local]` and `#[shared]` respectively. Each field in these structures corresponds
-to a different resource (identified by field name). The difference between these two sets of
-resources will be covered below.
+Declaration of system-wide resources are by annotating **two** `struct`s within the `#[app]` module
+with the attribute `#[local]` and `#[shared]`.
+Each field in these structures corresponds to a different resource (identified by field name).
+The difference between these two sets of resources will be covered below.
Each task must declare the resources it intends to access in its corresponding metadata attribute
-using the `local` and `shared` arguments. Each argument takes a list of resource identifiers. The
-listed resources are made available to the context under the `local` and `shared` fields of the
+using the `local` and `shared` arguments. Each argument takes a list of resource identifiers.
+The listed resources are made available to the context under the `local` and `shared` fields of the
`Context` structure.
-The `init` task returns the initial values for the system wide (`#[shared]` and `#[local]`)
+The `init` task returns the initial values for the system-wide (`#[shared]` and `#[local]`)
resources, and the set of initialized timers used by the application. The monotonic timers will be
further discussed in [Monotonic & `spawn_{at/after}`](./monotonic.md).
@@ -27,6 +27,9 @@ access the resource and does so without locks or critical sections. This allows
commonly drivers or large objects, to be initialized in `#[init]` and then be passed to a specific
task.
+Thus, a task `#[local]` resource can only be accessed by one singular task.
+Attempting to assign the same `#[local]` resource to more than one task is a compile-time error.
+
The example application shown below contains two tasks where each task has access to its own
`#[local]` resource, plus that the `idle` task has its own `#[local]` as well.
@@ -39,15 +42,12 @@ $ cargo run --target thumbv7m-none-eabi --example locals
{{#include ../../../../ci/expected/locals.run}}
```
-A `#[local]` resource cannot be accessed from outside the task it was associated to in a `#[task]` attribute.
-Assigning the same `#[local]` resource to more than one task is a compile-time error.
-
### Task local initialized resources
A special use-case of local resources are the ones specified directly in the resource claim,
`#[task(local = [my_var: TYPE = INITIAL_VALUE, ...])]`, this allows for creating locals which do no need to be
initialized in `#[init]`.
-Moreover local resources in `#[init]` and `#[idle]` have `'static` lifetimes, this is safe since both are not re-entrant.
+Moreover, local resources in `#[init]` and `#[idle]` have `'static` lifetimes, this is safe since both are not re-entrant.
In the example below the different uses and lifetimes are shown:
@@ -96,7 +96,7 @@ $ cargo run --target thumbv7m-none-eabi --example lock
## Multi-lock
As an extension to `lock`, and to reduce rightward drift, locks can be taken as tuples. The
-following examples shows this in use:
+following examples show this in use:
``` rust
{{#include ../../../../examples/multilock.rs}}
@@ -109,12 +109,12 @@ $ cargo run --target thumbv7m-none-eabi --example multilock
## Only shared (`&-`) access
-By default the framework assumes that all tasks require exclusive access (`&mut-`) to resources but
-it is possible to specify that a task only requires shared access (`&-`) to a resource using the
+By default, the framework assumes that all tasks require exclusive access (`&mut-`) to resources,
+but it is possible to specify that a task only requires shared access (`&-`) to a resource using the
`&resource_name` syntax in the `shared` list.
The advantage of specifying shared access (`&-`) to a resource is that no locks are required to
-access the resource even if the resource is contended by several tasks running at different
+access the resource even if the resource is contended by more than one task running at different
priorities. The downside is that the task only gets a shared reference (`&-`) to the resource,
limiting the operations it can perform on it, but where a shared reference is enough this approach
reduces the number of required locks. In addition to simple immutable data, this shared access can
@@ -142,8 +142,11 @@ $ cargo run --target thumbv7m-none-eabi --example only-shared-access
A critical section is *not* required to access a `#[shared]` resource that's only accessed by tasks
running at the *same* priority. In this case, you can opt out of the `lock` API by adding the
`#[lock_free]` field-level attribute to the resource declaration (see example below). Note that
-this is merely a convenience: if you do use the `lock` API, at runtime the framework will
-**not** produce a critical section. Also worth noting: using `#[lock_free]` on resources shared by
+this is merely a convenience to reduce needless resource locking code, because even if the
+`lock` API is used, at runtime the framework will **not** produce a critical section due to how
+the underlying resource-ceiling preemption works.
+
+Also worth noting: using `#[lock_free]` on resources shared by
tasks running at different priorities will result in a *compile-time* error -- not using the `lock`
API would be a data race in that case.
diff --git a/book/en/src/by-example/software_tasks.md b/book/en/src/by-example/software_tasks.md
index f78efea9..370792f8 100644
--- a/book/en/src/by-example/software_tasks.md
+++ b/book/en/src/by-example/software_tasks.md
@@ -1,21 +1,31 @@
# Software tasks & spawn
-Software tasks, as hardware tasks, are run as interrupt handlers where all software tasks at the
-same priority shares a "free" interrupt handler to run from, called a dispatcher. These free
-interrupts are interrupt vectors not used by hardware tasks.
-
-To declare tasks in the framework the `#[task]` attribute is used on a function.
-By default these tasks are referred to as software tasks as they do not have a direct coupling to
-an interrupt handler. Software tasks can be spawned (started) using the `task_name::spawn()` static
-method which will directly run the task given that there are no higher priority tasks running.
-
-To indicate to the framework which interrupts are free for use to dispatch software tasks with the
-`#[app]` attribute has a `dispatchers = [FreeInterrupt1, FreeInterrupt2, ...]` argument. You need
-to provide as many dispatchers as there are priority levels used by software tasks, as an
-dispatcher is assigned per interrupt level. The framework will also give a compile error if there
-are not enough dispatchers provided.
-
-This is exemplified in the following:
+Software tasks are tasks which are not directly assigned to a specific interrupt vector.
+
+They run as interrupt handlers where all software tasks at the
+same priority level shares a "free" interrupt handler acting as a dispatcher.
+Thus, what differentiates software and hardware tasks are the dispatcher versus
+bound interrupt vector.
+
+These free interrupts used as dispatchers are interrupt vectors not used by hardware tasks.
+
+The `#[task]` attribute used on a function declare it as a software tasks.
+The static method `task_name::spawn()` spawn (start) a software task and
+given that there are no higher priority tasks running the task will start executing directly.
+
+A list of “free” and usable interrupts allows the framework to dispatch software tasks.
+This list of dispatchers, `dispatchers = [FreeInterrupt1, FreeInterrupt2, ...]` is an
+argument to the `#[app]` attribute.
+
+Each interrupt vector acting as dispatcher gets assigned to one priority level meaning that
+the list of dispatchers need to cover all priority levels used by software tasks.
+
+Example: The `dispatchers =` argument needs to have at least 3 entries for an application using
+three different priorities for software tasks.
+
+The framework will give a compilation error if there are not enough dispatchers provided.
+
+See the following example:
``` rust
{{#include ../../../../examples/spawn.rs}}
diff --git a/book/en/src/by-example/starting_a_project.md b/book/en/src/by-example/starting_a_project.md
index b50ac4a9..c916479a 100644
--- a/book/en/src/by-example/starting_a_project.md
+++ b/book/en/src/by-example/starting_a_project.md
@@ -1,14 +1,16 @@
# Starting a new project
-When starting an RTIC project from scratch it is recommended to follow RTIC's [`defmt-app-template`].
+A recommendation when starting a RTIC project from scratch is to follow RTIC's [`defmt-app-template`].
[`defmt-app-template`]: https://github.com/rtic-rs/defmt-app-template
This will give you an RTIC application with support for RTT logging with [`defmt`] and stack overflow
-protection using [`flip-link`]. There are also an multitude of examples available provided by the community:
+protection using [`flip-link`]. There are also a multitude of examples available provided by the community:
+- [`rtic-examples`] - Multiple projects
- [https://github.com/kalkyl/f411-rtic](https://github.com/kalkyl/f411-rtic)
- ... More to come
[`defmt`]: https://github.com/knurling-rs/defmt/
[`flip-link`]: https://github.com/knurling-rs/flip-link/
+[`rtic-examples`]: https://github.com/rtic-rs/rtic-examples
diff --git a/book/en/src/by-example/tips_destructureing.md b/book/en/src/by-example/tips_destructureing.md
index 7b864c46..4637b483 100644
--- a/book/en/src/by-example/tips_destructureing.md
+++ b/book/en/src/by-example/tips_destructureing.md
@@ -1,7 +1,8 @@
# Resource de-structure-ing
-When having a task taking multiple resources it can help in readability to split
-up the resource struct. Here are two examples on how this can be done:
+Destructuring task resources might help readability if a task takes multiple
+resources.
+Here are two examples on how to split up the resource struct:
``` rust
{{#include ../../../../examples/destructure.rs}}
diff --git a/book/en/src/by-example/tips_from_ram.md b/book/en/src/by-example/tips_from_ram.md
index 6aef2f70..ecb5dde1 100644
--- a/book/en/src/by-example/tips_from_ram.md
+++ b/book/en/src/by-example/tips_from_ram.md
@@ -6,7 +6,7 @@ RTIC v0.4.0 was to allow inter-operation with other attributes. For example, the
improve performance in some cases.
> **IMPORTANT**: In general, the `link_section`, `export_name` and `no_mangle`
-> attributes are very powerful but also easy to misuse. Incorrectly using any of
+> attributes are powerful but also easy to misuse. Incorrectly using any of
> these attributes can cause undefined behavior; you should always prefer to use
> safe, higher level attributes around them like `cortex-m-rt`'s `interrupt` and
> `exception` attributes.
@@ -42,4 +42,3 @@ $ cargo nm --example ramfunc --release | grep ' foo::'
$ cargo nm --example ramfunc --release | grep ' bar::'
{{#include ../../../../ci/expected/ramfunc.grep.bar}}
```
-
diff --git a/book/en/src/by-example/tips_indirection.md b/book/en/src/by-example/tips_indirection.md
index 22c57746..1a330c51 100644
--- a/book/en/src/by-example/tips_indirection.md
+++ b/book/en/src/by-example/tips_indirection.md
@@ -3,7 +3,9 @@
Message passing always involves copying the payload from the sender into a
static variable and then from the static variable into the receiver. Thus
sending a large buffer, like a `[u8; 128]`, as a message involves two expensive
-`memcpy`s. To minimize the message passing overhead one can use indirection:
+`memcpy`s.
+
+Indirection can minimize message passing overhead:
instead of sending the buffer by value, one can send an owning pointer into the
buffer.
@@ -23,4 +25,3 @@ Here's an example where `heapless::Pool` is used to "box" buffers of 128 bytes.
$ cargo run --target thumbv7m-none-eabi --example pool
{{#include ../../../../ci/expected/pool.run}}
```
-
diff --git a/book/en/src/by-example/tips_monotonic_impl.md b/book/en/src/by-example/tips_monotonic_impl.md
index 210a08e6..24df7712 100644
--- a/book/en/src/by-example/tips_monotonic_impl.md
+++ b/book/en/src/by-example/tips_monotonic_impl.md
@@ -1,18 +1,21 @@
# Implementing a `Monotonic` timer for scheduling
-The framework is very flexible in that it can utilize any timer which has compare-match and (optional)
-overflow interrupts for scheduling. The only thing needed to make a timer usable with RTIC is to
-implement the [`rtic_monotonic::Monotonic`] trait.
+The framework is flexible because it can use any timer which has compare-match and optionally
+supporting overflow interrupts for scheduling.
+The single requirement to make a timer usable with RTIC is implementing the
+[`rtic_monotonic::Monotonic`] trait.
-Implementing time that supports a vast range is generally **very** difficult, and in RTIC 0.5 it was a
-common problem how to implement time handling and not get stuck in weird special cases. Moreover
-it was difficult to understand the relation between time and the timers used for scheduling. For
-RTIC 0.6 we have moved to assume the user has a time library, e.g. [`fugit`] or [`embedded_time`],
-as the basis for all time-based operations when implementing `Monotonic`. This is why in RTIC 0.6
-it is almost trivial to implement the `Monotonic` trait and use any timer in a system for scheduling.
+Implementing time counting that supports large time spans is generally **difficult**, in RTIC 0.5
+implementing time handling was a common problem.
+Moreover, the relation between time and timers used for scheduling was difficult to understand.
-The trait documents the requirements for each method, however below you can find a list of
-implementations in the wild that can be used as inspiration:
+For RTIC 0.6 we instead assume the user has a time library, e.g. [`fugit`] or [`embedded_time`],
+as the basis for all time-based operations when implementing `Monotonic`.
+This makes it almost trivial to implement the `Monotonic` trait allowing the use of any timer in
+the system for scheduling.
+
+The trait documents the requirements for each method,
+and for inspiration here is a list of `Monotonic` implementations:
- [`STM32F411 series`], implemented for the 32-bit timers
- [`Nordic nRF52 series`], implemented for the 32-bit timers
@@ -28,4 +31,3 @@ If you know of more implementations feel free to add them to this list.
[`Nordic nRF52 series`]: https://github.com/kalkyl/nrf-play/blob/main/src/bin/mono.rs
[`Systick based`]: https://github.com/rtic-rs/systick-monotonic
[`DWT and Systick based`]: https://github.com/rtic-rs/dwt-systick-monotonic
-
diff --git a/book/en/src/by-example/tips_static_lifetimes.md b/book/en/src/by-example/tips_static_lifetimes.md
index 3ea08166..8d3a832c 100644
--- a/book/en/src/by-example/tips_static_lifetimes.md
+++ b/book/en/src/by-example/tips_static_lifetimes.md
@@ -1,16 +1,16 @@
# 'static super-powers
-As discussed earlier `local` resources are given `'static` lifetime in `#[init]` and `#[idle]`,
-this can be used to allocate an object and then split it up or give the pre-allocated object to a
-task, driver or some other object.
-This is very useful when needing to allocate memory for drivers, such as USB drivers, and using
-data structures that can be split such as [`heapless::spsc::Queue`].
+In `#[init]` and `#[idle]` `local` resources has `'static` lifetime.
-In the following example an [`heapless::spsc::Queue`] is given to two different tasks for lock-free access
-to the shared queue.
+Useful when pre-allocating and/or splitting resources between tasks, drivers
+or some other object.
+This comes in handy when drivers, such as USB drivers, need to allocate memory and
+when using splittable data structures such as [`heapless::spsc::Queue`].
-[`heapless::spsc::Queue`]: https://docs.rs/heapless/0.7.5/heapless/spsc/struct.Queue.html
+In the following example two different tasks share a [`heapless::spsc::Queue`]
+for lock-free access to the shared queue.
+[`heapless::spsc::Queue`]: https://docs.rs/heapless/0.7.5/heapless/spsc/struct.Queue.html
``` rust
{{#include ../../../../examples/static.rs}}
diff --git a/book/en/src/by-example/tips_view_code.md b/book/en/src/by-example/tips_view_code.md
index 8f0d86b5..736b7ac8 100644
--- a/book/en/src/by-example/tips_view_code.md
+++ b/book/en/src/by-example/tips_view_code.md
@@ -7,7 +7,7 @@ options:
You can inspect the file `rtic-expansion.rs` inside the `target` directory. This
file contains the expansion of the `#[rtic::app]` item (not your whole program!)
of the *last built* (via `cargo build` or `cargo check`) RTIC application. The
-expanded code is not pretty printed by default so you'll want to run `rustfmt`
+expanded code is not pretty printed by default, so you'll want to run `rustfmt`
on it before you read it.
``` console
@@ -15,7 +15,7 @@ $ cargo build --example foo
$ rustfmt target/rtic-expansion.rs
-$ tail target/rtic-expansion.rs
+tail target/rtic-expansion.rs
```
``` rust
@@ -43,6 +43,6 @@ crate and print the output to the console.
[`cargo-expand`]: https://crates.io/crates/cargo-expand
``` console
-$ # produces the same output as before
-$ cargo expand --example smallest | tail
+# produces the same output as before
+cargo expand --example smallest | tail
```
diff --git a/book/en/src/migration.md b/book/en/src/migration.md
index 08feb81e..f52b0a51 100644
--- a/book/en/src/migration.md
+++ b/book/en/src/migration.md
@@ -1,4 +1,4 @@
# Migration Guides
-This section describes how to migrate between different version of RTIC.
+This section describes how to migrate between different versions of RTIC.
It also acts as a comparing reference between versions.
diff --git a/book/en/src/migration/migration_v4.md b/book/en/src/migration/migration_v4.md
index ac59d8c9..d1a7ebeb 100644
--- a/book/en/src/migration/migration_v4.md
+++ b/book/en/src/migration/migration_v4.md
@@ -1,19 +1,31 @@
# Migrating from v0.4.x to v0.5.0
-This section covers how to upgrade an application written against RTIC v0.4.x to
+This section covers how to upgrade an application written against RTFM v0.4.x to
the version v0.5.0 of the framework.
+## Project name change RTFM -> RTIC
+
+With release [v0.5.2][rtic0.5.2] the name was change to Real-Time Interrupt-driven Concurrency
+
+All occurrences of `RTFM` needs to change to `RTIC`.
+
+See [migration guide RTFM to RTIC](./migration_rtic.md)
+
+[rtic0.5.2]: https://crates.io/crates/cortex-m-rtic/0.5.2
+
## `Cargo.toml`
-First, the version of the `cortex-m-rtic` dependency needs to be updated to
-`"0.5.0"`. The `timer-queue` feature needs to be removed.
+Change the version of `cortex-m-rtfm` to
+`"0.5.0"`, change `rtfm` to `rtic`.
+Remove the `timer-queue` feature.
``` toml
-[dependencies.cortex-m-rtic]
+[dependencies.cortex-m-rtfm]
# change this
version = "0.4.3"
# into this
+[dependencies.cortex-m-rtic]
version = "0.5.0"
# and remove this Cargo feature
@@ -23,15 +35,15 @@ features = ["timer-queue"]
## `Context` argument
-All functions inside the `#[rtic::app]` item need to take as first argument a
+All functions inside the `#[rtfm::app]` item need to take as first argument a
`Context` structure. This `Context` type will contain the variables that were
magically injected into the scope of the function by version v0.4.x of the
framework: `resources`, `spawn`, `schedule` -- these variables will become
-fields of the `Context` structure. Each function within the `#[rtic::app]` item
+fields of the `Context` structure. Each function within the `#[rtfm::app]` item
gets a different `Context` type.
``` rust
-#[rtic::app(/* .. */)]
+#[rtfm::app(/* .. */)]
const APP: () = {
// change this
#[task(resources = [x], spawn = [a], schedule = [b])]
@@ -75,11 +87,11 @@ const APP: () = {
## Resources
-The syntax used to declare resources has been changed from `static mut`
+The syntax used to declare resources has changed from `static mut`
variables to a `struct Resources`.
``` rust
-#[rtic::app(/* .. */)]
+#[rtfm::app(/* .. */)]
const APP: () = {
// change this
static mut X: u32 = 0;
@@ -101,13 +113,13 @@ const APP: () = {
If your application was accessing the device peripherals in `#[init]` through
the `device` variable then you'll need to add `peripherals = true` to the
-`#[rtic::app]` attribute to continue to access the device peripherals through
+`#[rtfm::app]` attribute to continue to access the device peripherals through
the `device` field of the `init::Context` structure.
Change this:
``` rust
-#[rtic::app(/* .. */)]
+#[rtfm::app(/* .. */)]
const APP: () = {
#[init]
fn init() {
@@ -121,7 +133,7 @@ const APP: () = {
Into this:
``` rust
-#[rtic::app(/* .. */, peripherals = true)]
+#[rtfm::app(/* .. */, peripherals = true)]
// ^^^^^^^^^^^^^^^^^^
const APP: () = {
#[init]
@@ -137,13 +149,14 @@ const APP: () = {
## `#[interrupt]` and `#[exception]`
-The `#[interrupt]` and `#[exception]` attributes have been removed. To declare
-hardware tasks in v0.5.x use the `#[task]` attribute with the `binds` argument.
+Remove the attributes `#[interrupt]` and `#[exception]`.
+To declare hardware tasks in v0.5.x use the `#[task]`
+attribute with the `binds` argument instead.
Change this:
``` rust
-#[rtic::app(/* .. */)]
+#[rtfm::app(/* .. */)]
const APP: () = {
// hardware tasks
#[exception]
@@ -163,7 +176,7 @@ const APP: () = {
Into this:
``` rust
-#[rtic::app(/* .. */)]
+#[rtfm::app(/* .. */)]
const APP: () = {
#[task(binds = SVCall)]
// ^^^^^^^^^^^^^^
@@ -183,25 +196,26 @@ const APP: () = {
## `schedule`
-The `schedule` API no longer requires the `timer-queue` cargo feature, which has
-been removed. To use the `schedule` API one must
-first define the monotonic timer the runtime will use using the `monotonic`
-argument of the `#[rtic::app]` attribute. To continue using the cycle counter
-(CYCCNT) as the monotonic timer, and match the behavior of version v0.4.x, add
-the `monotonic = rtic::cyccnt::CYCCNT` argument to the `#[rtic::app]` attribute.
+The `schedule` API no longer requires the `timer-queue` cargo feature.
+To use the `schedule` API one must first define the monotonic timer the
+runtime will use using the `monotonic` argument of the `#[rtfm::app]` attribute.
+To continue using the cycle counter (CYCCNT) as the monotonic timer,
+and match the behavior of version v0.4.x, add the `monotonic = rtfm::cyccnt::CYCCNT`
+argument to the `#[rtfm::app]` attribute.
-Also, the `Duration` and `Instant` types and the `U32Ext` trait have been moved
-into the `rtic::cyccnt` module. This module is only available on ARMv7-M+
-devices. The removal of the `timer-queue` also brings back the `DWT` peripheral
-inside the core peripherals struct, this will need to be enabled by the application
-inside `init`.
+Also, the `Duration` and `Instant` types and the `U32Ext` trait moved
+into the `rtfm::cyccnt` module.
+This module is only available on ARMv7-M+ devices.
+The removal of the `timer-queue` also brings back the `DWT` peripheral
+inside the core peripherals struct, if `DWT` is required,
+ensure it is enabled by the application inside `init`.
Change this:
``` rust
-use rtic::{Duration, Instant, U32Ext};
+use rtfm::{Duration, Instant, U32Ext};
-#[rtic::app(/* .. */)]
+#[rtfm::app(/* .. */)]
const APP: () = {
#[task(schedule = [b])]
fn a() {
@@ -213,10 +227,10 @@ const APP: () = {
Into this:
``` rust
-use rtic::cyccnt::{Duration, Instant, U32Ext};
+use rtfm::cyccnt::{Duration, Instant, U32Ext};
// ^^^^^^^^
-#[rtic::app(/* .. */, monotonic = rtic::cyccnt::CYCCNT)]
+#[rtfm::app(/* .. */, monotonic = rtfm::cyccnt::CYCCNT)]
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const APP: () = {
#[init]
diff --git a/book/en/src/migration/migration_v5.md b/book/en/src/migration/migration_v5.md
index 24353d2a..5c0dad19 100644
--- a/book/en/src/migration/migration_v5.md
+++ b/book/en/src/migration/migration_v5.md
@@ -71,7 +71,7 @@ mod app {
}
```
-## Move Dispatchers from `extern "C"` to app arguments.
+## Move Dispatchers from `extern "C"` to app arguments
Change
@@ -171,7 +171,10 @@ fn b(_: b::Context) {}
## Symmetric locks
-Now RTIC utilizes symmetric locks, this means that the `lock` method need to be used for all `shared` resource access. In old code one could do the following as the high priority task has exclusive access to the resource:
+Now RTIC utilizes symmetric locks, this means that the `lock` method need
+to be used for all `shared` resource access.
+In old code one could do the following as the high priority
+task has exclusive access to the resource:
``` rust
#[task(priority = 2, resources = [r])]
@@ -354,6 +357,7 @@ Note that the attributes `spawn` and `schedule` are no longer needed.
### Extern tasks
-Both software and hardware tasks can now be defined external to the `mod app`. Previously this was possible only by implementing a trampoline calling out the task implementation.
+Both software and hardware tasks can now be defined external to the `mod app`.
+Previously this was possible only by implementing a trampoline calling out the task implementation.
See examples `examples/extern_binds.rs` and `examples/extern_spawn.rs`.
diff --git a/book/en/src/preface.md b/book/en/src/preface.md
index e81542c9..d9dbc04b 100644
--- a/book/en/src/preface.md
+++ b/book/en/src/preface.md
@@ -8,7 +8,7 @@
# Preface
This book contains user level documentation for the Real-Time Interrupt-driven Concurrency
-(RTIC) framework. The API reference can be found [here](../../api/).
+(RTIC) framework. The API reference is available [here](../../api/).
Formerly known as Real-Time For the Masses.