aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--book/en/book.toml2
-rw-r--r--book/en/src/by-example/app.md17
-rw-r--r--book/en/src/migration/migration_v5.md122
3 files changed, 105 insertions, 36 deletions
diff --git a/book/en/book.toml b/book/en/book.toml
index caa04ba..98c5bf3 100644
--- a/book/en/book.toml
+++ b/book/en/book.toml
@@ -1,5 +1,5 @@
[book]
-authors = ["Jorge Aparicio"]
+authors = ["Jorge Aparicio, Per Lindgren and The Real-Time Interrupt-driven Concurrency developers"]
multilingual = false
src = "src"
title = "Real-Time Interrupt-driven Concurrency"
diff --git a/book/en/src/by-example/app.md b/book/en/src/by-example/app.md
index 2c70af0..6a01193 100644
--- a/book/en/src/by-example/app.md
+++ b/book/en/src/by-example/app.md
@@ -34,14 +34,13 @@ And optionally, device specific peripherals through the `core` and `device` fiel
of `init::Context`.
`static mut` variables declared at the beginning of `init` will be transformed
-into `&'static mut` references that are safe to access.
+into `&'static mut` references that are safe to access. Notice, this feature may be deprecated in next release, see `task_local` resources.
[`rtic::Peripherals`]: ../../api/rtic/struct.Peripherals.html
The example below shows the types of the `core`, `device` and `cs` fields, and
showcases safe access to a `static mut` variable. The `device` field is only
-available when the `peripherals` argument is set to `true` (it defaults to
-`false`).
+available when the `peripherals` argument is set to `true` (default). In the rare case you want to implement an ultra-slim application you can explicitly set `peripherals` to `false`.
``` rust
{{#include ../../../../examples/init.rs}}
@@ -71,12 +70,12 @@ then sends the microcontroller to sleep after running `init`.
[SLEEPONEXIT]: https://developer.arm.com/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit
Like in `init`, `static mut` variables will be transformed into `&'static mut`
-references that are safe to access.
+references that are safe to access. Notice, this feature may be deprecated in the next release, see `task_local` resources.
The example below shows that `idle` runs after `init`.
-**Note:** The `loop {}` in idle cannot be empty as this will crash the microcontroller due to a bug
-in LLVM which miss-optimizes empty loops to a `UDF` instruction in release mode.
+**Note:** The `loop {}` in idle cannot be empty as this will crash the microcontroller due to
+LLVM compiling empty loops to an `UDF` instruction in release mode. To avoid UB, the loop needs to imply a "side-effect" by inserting an assembly instruction (e.g., `WFI`) or a `continue`.
``` rust
{{#include ../../../../examples/idle.rs}}
@@ -146,9 +145,9 @@ $ cargo run --example preempt
```
Note that the task `gpiob` does *not* preempt task `gpioc` because its priority
-is the *same* as `gpioc`'s. However, once `gpioc` terminates the execution of
-task, `gpiob` is prioritized over `gpioa` due to its higher priority. `gpioa`
-is resumed only after `gpiob` terminates.
+is the *same* as `gpioc`'s. However, once `gpioc` returns, the execution of
+task `gpiob` is prioritized over `gpioa` due to its higher priority. `gpioa`
+is resumed only after `gpiob` returns.
One more note about priorities: choosing a priority higher than what the device
supports (that is `1 << NVIC_PRIO_BITS`) will result in a compile error. Due to
diff --git a/book/en/src/migration/migration_v5.md b/book/en/src/migration/migration_v5.md
index 44af15e..8edefd2 100644
--- a/book/en/src/migration/migration_v5.md
+++ b/book/en/src/migration/migration_v5.md
@@ -6,61 +6,62 @@ This section describes how to upgrade from v0.5.x to v0.6.0 of the RTIC framewor
Change the version of `cortex-m-rtic` to `"0.6.0"`.
-## Move Dispatchers from `extern "C"` to app arguments.
+## `mod` instead of `const`
+
+With the support of attributes on modules the `const APP` workaround is not needed.
Change
``` rust
#[rtic::app(/* .. */)]
const APP: () = {
- [code here]
-
- // RTIC requires that unused interrupts are declared in an extern block when
- // using software tasks; these free interrupts will be used to dispatch the
- // software tasks.
- extern "C" {
- fn SSI0();
- fn QEI0();
- }
+ [code here]
};
```
into
``` rust
-#[rtic::app(/* .. */, dispatchers = [SSI0, QEI0])]
+#[rtic::app(/* .. */)]
mod app {
[code here]
}
```
-This works also for ram functions, see examples/ramfunc.rs
-
-## Module instead of Const
+Now that a regular Rust module is used it means it is possible to have custom
+user code within that module.
+Additionally, it means that `use`-statements for resources etc may be required.
-With the support of attributes on modules the `const APP` workaround is not needed.
+## Move Dispatchers from `extern "C"` to app arguments.
Change
``` rust
#[rtic::app(/* .. */)]
const APP: () = {
- [code here]
+ [code here]
+
+ // RTIC requires that unused interrupts are declared in an extern block when
+ // using software tasks; these free interrupts will be used to dispatch the
+ // software tasks.
+ extern "C" {
+ fn SSI0();
+ fn QEI0();
+ }
};
```
into
``` rust
-#[rtic::app(/* .. */)]
+#[rtic::app(/* .. */, dispatchers = [SSI0, QEI0])]
mod app {
[code here]
}
```
-Now that a regular Rust module is used it means it is possible to have custom
-user code within that module.
-Additionally, it means that `use`-statements for resources etc may be required.
+This works also for ram functions, see examples/ramfunc.rs
+
## Init always returns late resources
@@ -75,7 +76,8 @@ mod app {
fn init(_: init::Context) {
rtic::pend(Interrupt::UART0);
}
- [more code]
+
+ // [more code]
}
```
@@ -90,11 +92,12 @@ mod app {
init::LateResources {}
}
- [more code]
+
+ // [more code]
}
```
-## Resources struct - #[resources]
+## Resources struct - `#[resources]`
Previously the RTIC resources had to be in in a struct named exactly "Resources":
@@ -118,19 +121,86 @@ In fact, the name of the struct is now up to the developer:
``` rust
#[resources]
-struct whateveryouwant {
+struct Whateveryouwant {
// Resources defined in here
}
```
would work equally well.
+## Spawn/schedule from anywhere
+
+With the new "spawn/schedule from anywhere", old code such as:
+
+
+
+``` rust
+#[task(spawn = [bar])]
+fn foo(cx: foo::Context) {
+ cx.spawn.bar().unwrap();
+}
+
+#[task(schedule = [bar])]
+fn bar(cx: bar::Context) {
+ cx.schedule.foo(/* ... */).unwrap();
+}
+```
+
+Will now be written as:
+
+``` rust
+#[task]
+fn foo(_c: foo::Context) {
+ bar::spawn().unwrap();
+}
+
+#[task]
+fn bar(_c: bar::Context) {
+ foo::schedule(/* ... */).unwrap();
+}
+```
+
+Note that the attributes `spawn` and `schedule` are no longer needed.
+
+## Symmetric locks
+
+Now RTIC utilizes symmetric locks, this means that the `lock` method need to be used for all 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])]
+fn foo(cx: foo::Context) {
+ cx.resources.r = /* ... */;
+}
+
+#[task(resources = [r])]
+fn bar(cx: bar::Context) {
+ cx.resources.r.lock(|r| r = /* ... */);
+}
+```
+
+And with symmetric locks one needs to use locks in both tasks:
+
+``` rust
+#[task(priority = 2, resources = [r])]
+fn foo(cx: foo::Context) {
+ cx.resources.r.lock(|r| r = /* ... */);
+}
+
+#[task(resources = [r])]
+fn bar(cx: bar::Context) {
+ cx.resources.r.lock(|r| r = /* ... */);
+}
+```
+
+Note that the performance does not change thanks to LLVM's optimizations which optimizes away unnecessary locks.
+
---
## Additions
### 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`.
-See examples `examples/extern_binds.rs` and `examples/extern_spawn.rs`. \ No newline at end of file