aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--book/en/src/by-example/tasks.md6
-rw-r--r--book/en/src/by-example/timer-queue.md4
-rw-r--r--book/en/src/by-example/tips.md23
-rw-r--r--book/en/src/by-example/types-send-sync.md27
-rw-r--r--book/en/src/migration/migration_v5.md122
5 files changed, 108 insertions, 74 deletions
diff --git a/book/en/src/by-example/tasks.md b/book/en/src/by-example/tasks.md
index ba164048..8558a542 100644
--- a/book/en/src/by-example/tasks.md
+++ b/book/en/src/by-example/tasks.md
@@ -6,15 +6,13 @@ 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 an `extern` block when using software tasks; some of these free
+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. To be able to spawn a software task from a context
-the name of the task must appear in the `spawn` argument of the context
-attribute (`init`, `idle`, `task`, etc.).
+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.
diff --git a/book/en/src/by-example/timer-queue.md b/book/en/src/by-example/timer-queue.md
index 482aebc1..29641750 100644
--- a/book/en/src/by-example/timer-queue.md
+++ b/book/en/src/by-example/timer-queue.md
@@ -29,9 +29,7 @@ on the built-in CYCle CouNTer (CYCCNT). Note that this is a 32-bit timer clocked
at the frequency of the CPU and as such it is not suitable for tracking time
spans in the order of seconds.
-To be able to schedule a software task from a context the name of the task must
-first appear in the `schedule` argument of the context attribute. When
-scheduling a task the (user-defined) `Instant` at which the task should be
+When scheduling a task the (user-defined) `Instant` at which the task should be
executed must be passed as the first argument of the `schedule` invocation.
Additionally, the chosen `monotonic` timer must be configured and initialized
diff --git a/book/en/src/by-example/tips.md b/book/en/src/by-example/tips.md
index 090b30ad..f537173d 100644
--- a/book/en/src/by-example/tips.md
+++ b/book/en/src/by-example/tips.md
@@ -2,15 +2,8 @@
## Generics
-Resources may appear in contexts as resource proxies or as unique references
-(`&mut-`) depending on the priority of the task. Because the same resource may
-appear as *different* types in different contexts one cannot refactor a common
-operation that uses resources into a plain function; however, such refactor is
-possible using *generics*.
-
-All resource proxies implement the `rtic::Mutex` trait. On the other hand,
-unique references (`&mut-`) do *not* implement this trait (due to limitations in
-the trait system) but one can wrap these references in the [`rtic::Exclusive`]
+All resource proxies implement the `rtic::Mutex` trait.
+If a resource does not implement this, one can wrap it in the [`rtic::Exclusive`]
newtype which does implement the `Mutex` trait. With the help of this newtype
one can write a generic function that operates on generic resources and call it
from different tasks to perform some operation on the same set of resources.
@@ -27,15 +20,13 @@ $ cargo run --example generics
{{#include ../../../../ci/expected/generics.run}}
```
-Using generics also lets you change the static priorities of tasks during
-development without having to rewrite a bunch code every time.
-
## Conditional compilation
You can use conditional compilation (`#[cfg]`) on resources (the fields of
-`struct Resources`) and tasks (the `fn` items). The effect of using `#[cfg]`
-attributes is that the resource / task will *not* be available through the
-corresponding `Context` `struct` if the condition doesn't hold.
+`#[resources] struct Resources`) and tasks (the `fn` items).
+The effect of using `#[cfg]` attributes is that the resource / task
+will *not* be available through the corresponding `Context` `struct`
+if the condition doesn't hold.
The example below logs a message whenever the `foo` task is spawned, but only if
the program has been compiled using the `dev` profile.
@@ -132,7 +123,7 @@ 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`
-over it before you read it.
+on it before you read it.
``` console
$ cargo build --example foo
diff --git a/book/en/src/by-example/types-send-sync.md b/book/en/src/by-example/types-send-sync.md
index 9cdb8894..a45f179e 100644
--- a/book/en/src/by-example/types-send-sync.md
+++ b/book/en/src/by-example/types-send-sync.md
@@ -27,31 +27,8 @@ resources.
[`Send`]: https://doc.rust-lang.org/core/marker/trait.Send.html
The `app` attribute will enforce that `Send` is implemented where required so
-you don't need to worry much about it. It's more important to know where you do
-*not* need the `Send` trait: on types that are transferred between tasks that
-run at the *same* priority. This occurs in two places: in message passing and in
-shared resources.
-
-The example below shows where a type that doesn't implement `Send` can be used.
-
-``` rust
-{{#include ../../../../examples/not-send.rs}}
-```
-
-It's important to note that late initialization of resources is effectively a
-send operation where the initial value is sent from the background context,
-which has the lowest priority of `0`, to a task, which will run at a priority
-greater than or equal to `1`. Thus all late resources need to implement the
-`Send` trait, except for those exclusively accessed by `idle`, which runs at a
-priority of `0`.
-
-Sharing a resource with `init` can be used to implement late initialization, see
-example below. For that reason, resources shared with `init` must also implement
-the `Send` trait.
-
-``` rust
-{{#include ../../../../examples/shared-with-init.rs}}
-```
+you don't need to worry much about it. Currently all types that are passed need
+to be `Send` in RTIC, however this restriction might be relaxed in the future.
## `Sync`
diff --git a/book/en/src/migration/migration_v5.md b/book/en/src/migration/migration_v5.md
index 44af15e2..8edefd2d 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