aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--book/en/src/by-example/app_init.md17
-rw-r--r--book/en/src/by-example/app_priorities.md7
-rw-r--r--book/en/src/by-example/app_task.md15
-rw-r--r--book/en/src/by-example/hardware_tasks.md20
-rw-r--r--book/en/src/by-example/monotonic.md6
-rw-r--r--book/en/src/by-example/resources.md20
-rw-r--r--book/en/src/by-example/software_tasks.md34
-rw-r--r--book/en/src/by-example/starting_a_project.md2
-rw-r--r--book/en/src/by-example/tips_indirection.md6
-rw-r--r--book/en/src/by-example/tips_monotonic_impl.md2
-rw-r--r--book/en/src/by-example/tips_static_lifetimes.md2
-rw-r--r--book/en/src/migration/migration_v5.md2
13 files changed, 81 insertions, 53 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c43a73d2..9432cab7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
### Fixed
- Attempt to handle docs generation enabling `deny(missing_docs)`
+- Book: Editorial review
- Use native GHA rustup and cargo
- Distinguish between thumbv8m.base and thumbv8m.main for basepri usage.
diff --git a/book/en/src/by-example/app_init.md b/book/en/src/by-example/app_init.md
index 22c4a28a..5bf6200e 100644
--- a/book/en/src/by-example/app_init.md
+++ b/book/en/src/by-example/app_init.md
@@ -1,13 +1,18 @@
# App initialization and the `#[init]` task
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
+signature `fn(init::Context) -> (Shared, Local, init::Monotonics)`, where `Shared` and `Local` are resource
structures defined by the user.
-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`.
+The `init` task executes after system reset, [after an optionally defined `pre-init` code section][pre-init] and an always occurring internal RTIC
+initialization.
+
+[pre-init]: https://docs.rs/cortex-m-rt/latest/cortex_m_rt/attr.pre_init.html
+
+The `init` and optional `pre-init` tasks runs *with interrupts disabled* and have exclusive access to Cortex-M (the
+`bare_metal::CriticalSection` token is available as `cs`).
+
+Device specific peripherals are available through the `core` and `device` fields of `init::Context`.
## Example
@@ -15,7 +20,7 @@ The example below shows the types of the `core`, `device` and `cs` fields, and s
variable with `'static` lifetime.
Such variables can be delegated from the `init` task to other tasks of the RTIC application.
-The `device` field is available when the `peripherals` argument is set to the default value `true`.
+The `device` field is only 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
diff --git a/book/en/src/by-example/app_priorities.md b/book/en/src/by-example/app_priorities.md
index 1a92ec84..8cee7499 100644
--- a/book/en/src/by-example/app_priorities.md
+++ b/book/en/src/by-example/app_priorities.md
@@ -18,8 +18,8 @@ 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
+Spawning a higher priority task A during execution of a lower priority task B suspends
+task B. 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
@@ -53,7 +53,8 @@ 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 compilation error.
-The error is cryptic due to limitations in the language,
+
+The error is cryptic due to limitations in the Rust language
if `priority = 9` for task `uart0_interrupt` in `example/common.rs` this looks like:
```text
diff --git a/book/en/src/by-example/app_task.md b/book/en/src/by-example/app_task.md
index 97160041..d83f1ff1 100644
--- a/book/en/src/by-example/app_task.md
+++ b/book/en/src/by-example/app_task.md
@@ -4,15 +4,18 @@ Tasks, defined with `#[task]`, are the main mechanism of getting work done in RT
Tasks can
-* Be spawned (now or in the future)
-* Receive messages (message passing)
-* Prioritized allowing preemptive multitasking
+* Be spawned (now or in the future, also by themselves)
+* Receive messages (passing messages between tasks)
+* Be 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.
+*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, lets say, a UART RX interrupt, the task will be run every
+time that interrupt triggers, usually when a character is received.
+
+*Software tasks* are explicitly spawned in a task, either immediately or using the Monotonic timer mechanism.
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 7f8d3c6e..2d405d32 100644
--- a/book/en/src/by-example/hardware_tasks.md
+++ b/book/en/src/by-example/hardware_tasks.md
@@ -1,24 +1,26 @@
# Hardware tasks
-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]`
+At its core RTIC is using a hardware interrupt controller ([ARM NVIC on cortex-m][NVIC])
+to schedule and start execution of tasks. All tasks except `pre-init`, `#[init]` and `#[idle]`
run as interrupt handlers.
-This also means that you can manually bind tasks to interrupt handlers.
-To bind an interrupt use the `#[task]` attribute argument `binds = InterruptName`.
-This task becomes the interrupt handler for this hardware interrupt vector.
+Hardware tasks are explicitly bound to interrupt handlers.
-All tasks bound to an explicit interrupt are *hardware tasks* since they
+To bind a task to an interrupt, use the `#[task]` attribute argument `binds = InterruptName`.
+This task then becomes the interrupt handler for this hardware interrupt vector.
+
+All tasks bound to an explicit interrupt are called *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.
-Any available interrupt vector should work, but different hardware might have
-added special properties to select interrupt priority levels, such as the
+Any available interrupt vector should work. Specific devices may bind
+specific interrupt priorities to specific interrupt vectors outside
+user code control. See for example the
[nRF “softdevice”](https://github.com/rtic-rs/cortex-m-rtic/issues/434).
-Beware of re-purposing interrupt vectors used internally by hardware features,
+Beware of using interrupt vectors that are used internally by hardware features;
RTIC is unaware of such hardware specific details.
[pacorhal]: https://docs.rust-embedded.org/book/start/registers.html
diff --git a/book/en/src/by-example/monotonic.md b/book/en/src/by-example/monotonic.md
index 094bd5df..3a23681f 100644
--- a/book/en/src/by-example/monotonic.md
+++ b/book/en/src/by-example/monotonic.md
@@ -1,7 +1,7 @@
# 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 useful. For this use-case the framework provides the static methods
+based on time is essential. The framework provides the static methods
`task::spawn_after(/* duration */)` and `task::spawn_at(/* specific time instant */)`.
`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.
@@ -43,10 +43,14 @@ $ cargo run --target thumbv7m-none-eabi --example schedule
{{#include ../../../../ci/expected/schedule.run}}
```
+A key requirement of a Monotonic is that it must deal gracefully with
+hardware timer overruns.
+
## Canceling or rescheduling a scheduled task
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 6349b520..30089d34 100644
--- a/book/en/src/by-example/resources.md
+++ b/book/en/src/by-example/resources.md
@@ -30,13 +30,13 @@ 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.
-Types of `#[local]` resources must implement [`Send`] trait as they are being sent from `init`
-to target task and thus crossing the thread boundary.
+Types of `#[local]` resources must implement a [`Send`] trait as they are being sent from `init`
+to a target task, crossing a thread boundary.
[`Send`]: https://doc.rust-lang.org/stable/core/marker/trait.Send.html
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.
+`#[local]` resource; the `idle` task has its own `#[local]` as well.
``` rust
{{#include ../../../../examples/locals.rs}}
@@ -49,12 +49,14 @@ $ cargo run --target thumbv7m-none-eabi --example locals
{{#include ../../../../ci/expected/locals.run}}
```
+Local resources in `#[init]` and `#[idle]` have `'static`
+lifetimes. This is safe since both tasks are not re-entrant.
+
### 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
+Local resources can also be specified directly in the resource claim like so:
+`#[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.
Types of `#[task(local = [..])]` resources have to be neither [`Send`] nor [`Sync`] as they
are not crossing any thread boundary.
@@ -92,9 +94,9 @@ preempting the critical section. This synchronization protocol is known as the
[srp]: https://en.wikipedia.org/wiki/Stack_Resource_Policy
In the example below we have three interrupt handlers with priorities ranging from one to three.
-The two handlers with the lower priorities contend for the `shared` resource and need to lock the
-resource for accessing the data. The highest priority handler, which do not access the `shared`
-resource, is free to preempt the critical section created by the lowest priority handler.
+The two handlers with the lower priorities contend for a `shared` resource and need to succeed in locking the
+resource in order to access its data. The highest priority handler, which does not access the `shared`
+resource, is free to preempt a critical section created by the lowest priority handler.
``` rust
{{#include ../../../../examples/lock.rs}}
diff --git a/book/en/src/by-example/software_tasks.md b/book/en/src/by-example/software_tasks.md
index 5c03f914..8ee185bd 100644
--- a/book/en/src/by-example/software_tasks.md
+++ b/book/en/src/by-example/software_tasks.md
@@ -2,29 +2,33 @@
The RTIC concept of a software task shares a lot with that of [hardware tasks](./hardware_tasks.md)
with the core difference that a software task is not explicitly bound to a specific
-interrupt vector, but rather a “dispatcher” interrupt vector running
-at the same priority as the software task.
+interrupt vector, but rather bound to a “dispatcher” interrupt vector running
+at the intended priority of the software task (see below).
-Thus, software tasks are tasks which are not directly assigned to a specific interrupt vector.
+Thus, software tasks are tasks which are not *directly* bound to an interrupt vector.
-The `#[task]` attribute used on a function declare it as a software tasks.
-Observe the absence of a `binds = InterruptName` argument to the attribute.
-The static method `task_name::spawn()` spawns (starts) a software task and
-given that there are no higher priority tasks running the task will start executing directly.
+The `#[task]` attributes used on a function determine if it is
+software tasks, specifically the absence of a `binds = InterruptName`
+argument to the attribute definition.
-All software tasks at the same priority level shares an interrupt handler acting as a dispatcher.
-What differentiates software and hardware tasks are the dispatcher versus bound interrupt vector.
+The static method `task_name::spawn()` spawns (schedules) a software
+task by registering it with a specific dispatcher. If there are no
+higher priority tasks available to the scheduler (which serves a set
+of dispatchers), the task will start executing directly.
-The interrupt vectors used as dispatchers can not be used by hardware tasks.
+All software tasks at the same priority level share an interrupt handler bound to their dispatcher.
+What differentiates software and hardware tasks is the usage of either a dispatcher or a bound interrupt vector.
-A list of “free” (not in use by hardware tasks) and usable interrupts allows the framework
-to dispatch software tasks.
+The interrupt vectors used as dispatchers cannot be used by hardware tasks.
-This list of dispatchers, `dispatchers = [FreeInterrupt1, FreeInterrupt2, ...]` is an
+Availability of a set of “free” (not in use by hardware tasks) and usable interrupt vectors allows the framework
+to dispatch software tasks via dedicated interrupt handlers.
+
+This set 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.
+Each interrupt vector acting as dispatcher gets assigned to a unique priority level meaning that
+the list of dispatchers needs 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.
diff --git a/book/en/src/by-example/starting_a_project.md b/book/en/src/by-example/starting_a_project.md
index ccb0083c..fe7be578 100644
--- a/book/en/src/by-example/starting_a_project.md
+++ b/book/en/src/by-example/starting_a_project.md
@@ -8,7 +8,7 @@ If you are targeting ARMv6-M or ARMv8-M-base architecture, check out the section
[`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 a multitude of examples available provided by the community:
+protection using [`flip-link`]. There is also a multitude of examples provided by the community:
- [`rtic-examples`] - Multiple projects
- [https://github.com/kalkyl/f411-rtic](https://github.com/kalkyl/f411-rtic)
diff --git a/book/en/src/by-example/tips_indirection.md b/book/en/src/by-example/tips_indirection.md
index 1a330c51..567a5e72 100644
--- a/book/en/src/by-example/tips_indirection.md
+++ b/book/en/src/by-example/tips_indirection.md
@@ -9,12 +9,16 @@ Indirection can minimize message passing overhead:
instead of sending the buffer by value, one can send an owning pointer into the
buffer.
-One can use a global allocator to achieve indirection (`alloc::Box`,
+One can use a global memory allocator to achieve indirection (`alloc::Box`,
`alloc::Rc`, etc.), which requires using the nightly channel as of Rust v1.37.0,
or one can use a statically allocated memory pool like [`heapless::Pool`].
[`heapless::Pool`]: https://docs.rs/heapless/0.5.0/heapless/pool/index.html
+As this example of approach goes completely outside of RTIC resource
+model with shared and local the program would rely on the correctness
+of the memory allocator, in this case `heapless::pool`.
+
Here's an example where `heapless::Pool` is used to "box" buffers of 128 bytes.
``` rust
diff --git a/book/en/src/by-example/tips_monotonic_impl.md b/book/en/src/by-example/tips_monotonic_impl.md
index d97b5839..7c3449b2 100644
--- a/book/en/src/by-example/tips_monotonic_impl.md
+++ b/book/en/src/by-example/tips_monotonic_impl.md
@@ -11,7 +11,7 @@ Moreover, the relation between time and timers used for scheduling was difficult
For RTIC 1.0 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 much easier to correctly implement the `Monotonic` trait allowing the use of
+These libraries make it much easier to correctly implement the `Monotonic` trait, allowing the use of
almost any timer in the system for scheduling.
The trait documents the requirements for each method,
diff --git a/book/en/src/by-example/tips_static_lifetimes.md b/book/en/src/by-example/tips_static_lifetimes.md
index 8d3a832c..dadd9c94 100644
--- a/book/en/src/by-example/tips_static_lifetimes.md
+++ b/book/en/src/by-example/tips_static_lifetimes.md
@@ -1,6 +1,6 @@
# 'static super-powers
-In `#[init]` and `#[idle]` `local` resources has `'static` lifetime.
+In `#[init]` and `#[idle]` `local` resources have `'static` lifetime.
Useful when pre-allocating and/or splitting resources between tasks, drivers
or some other object.
diff --git a/book/en/src/migration/migration_v5.md b/book/en/src/migration/migration_v5.md
index 731931f0..5a8fabce 100644
--- a/book/en/src/migration/migration_v5.md
+++ b/book/en/src/migration/migration_v5.md
@@ -368,3 +368,5 @@ 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`.
+
+This enables breaking apps into multiple files.