2018-11-03 17:02:41 +01:00
|
|
|
# Tips & tricks
|
|
|
|
|
2018-11-04 18:50:42 +01:00
|
|
|
## Generics
|
|
|
|
|
|
|
|
Resources shared between two or more tasks implement the `Mutex` trait in *all*
|
|
|
|
contexts, even on those where a critical section is not required to access the
|
|
|
|
data. This lets you easily write generic code that operates on resources and can
|
|
|
|
be called from different tasks. Here's one such example:
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../examples/generics.rs}}
|
2018-11-04 18:50:42 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
``` console
|
|
|
|
$ cargo run --example generics
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../ci/expected/generics.run}}```
|
2018-11-04 18:50:42 +01:00
|
|
|
|
|
|
|
This also lets you change the static priorities of tasks without having to
|
|
|
|
rewrite code. If you consistently use `lock`s to access the data behind shared
|
|
|
|
resources then your code will continue to compile when you change the priority
|
|
|
|
of tasks.
|
|
|
|
|
2018-12-16 20:56:57 +01:00
|
|
|
## Conditional compilation
|
|
|
|
|
|
|
|
You can use conditional compilation (`#[cfg]`) on resources (`static [mut]`
|
|
|
|
items) and tasks (`fn` items). The effect of using `#[cfg]` attributes is that
|
|
|
|
the resource / task will *not* be injected into the prelude of tasks that use
|
|
|
|
them (see `resources`, `spawn` and `schedule`) 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.
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../examples/cfg.rs}}
|
2018-12-16 20:56:57 +01:00
|
|
|
```
|
|
|
|
|
2018-11-03 17:02:41 +01:00
|
|
|
## Running tasks from RAM
|
|
|
|
|
|
|
|
The main goal of moving the specification of RTFM applications to attributes in
|
|
|
|
RTFM v0.4.x was to allow inter-operation with other attributes. For example, the
|
|
|
|
`link_section` attribute can be applied to tasks to place them in RAM; this can
|
|
|
|
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
|
|
|
|
> 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.
|
|
|
|
>
|
|
|
|
> In the particular case of RAM functions there's no
|
|
|
|
> safe abstraction for it in `cortex-m-rt` v0.6.5 but there's an [RFC] for
|
|
|
|
> adding a `ramfunc` attribute in a future release.
|
|
|
|
|
|
|
|
[RFC]: https://github.com/rust-embedded/cortex-m-rt/pull/100
|
|
|
|
|
|
|
|
The example below shows how to place the higher priority task, `bar`, in RAM.
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../examples/ramfunc.rs}}
|
2018-11-03 17:02:41 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
Running this program produces the expected output.
|
|
|
|
|
|
|
|
``` console
|
|
|
|
$ cargo run --example ramfunc
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../ci/expected/ramfunc.run}}```
|
2018-11-03 17:02:41 +01:00
|
|
|
|
|
|
|
One can look at the output of `cargo-nm` to confirm that `bar` ended in RAM
|
|
|
|
(`0x2000_0000`), whereas `foo` ended in Flash (`0x0000_0000`).
|
|
|
|
|
|
|
|
``` console
|
|
|
|
$ cargo nm --example ramfunc --release | grep ' foo::'
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../ci/expected/ramfunc.grep.foo}}```
|
2018-11-03 17:02:41 +01:00
|
|
|
|
|
|
|
``` console
|
|
|
|
$ cargo nm --example ramfunc --release | grep ' bar::'
|
2019-02-11 21:40:53 +01:00
|
|
|
{{#include ../../../../ci/expected/ramfunc.grep.bar}}```
|