diff options
| author | datdenkikniet <jcdra1@gmail.com> | 2023-04-23 13:22:35 +0200 |
|---|---|---|
| committer | datdenkikniet <jcdra1@gmail.com> | 2023-05-11 19:20:58 +0200 |
| commit | e51146a98cc7c83ea574d13b4b5d8e7ceeeb004b (patch) | |
| tree | 2c177aa08778c51167835278d4d3e0c777d03019 /book/en/src/by-example/tips | |
| parent | cb0ceea472f33ed7a8b17fe7e0b98f24927d9185 (diff) | |
Move tips into their own subdir
Diffstat (limited to 'book/en/src/by-example/tips')
| -rw-r--r-- | book/en/src/by-example/tips/destructureing.md | 15 | ||||
| -rw-r--r-- | book/en/src/by-example/tips/from_ram.md | 45 | ||||
| -rw-r--r-- | book/en/src/by-example/tips/index.md | 3 | ||||
| -rw-r--r-- | book/en/src/by-example/tips/indirection.md | 26 | ||||
| -rw-r--r-- | book/en/src/by-example/tips/monotonic_impl.md | 25 | ||||
| -rw-r--r-- | book/en/src/by-example/tips/static_lifetimes.md | 23 | ||||
| -rw-r--r-- | book/en/src/by-example/tips/view_code.md | 47 |
7 files changed, 184 insertions, 0 deletions
diff --git a/book/en/src/by-example/tips/destructureing.md b/book/en/src/by-example/tips/destructureing.md new file mode 100644 index 0000000..6e1d796 --- /dev/null +++ b/book/en/src/by-example/tips/destructureing.md @@ -0,0 +1,15 @@ +# Resource de-structure-ing + +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 ../../../../../rtic/examples/destructure.rs}} +``` + +``` console +$ cargo run --target thumbv7m-none-eabi --example destructure +``` +``` console +{{#include ../../../../../rtic/ci/expected/destructure.run}} +``` diff --git a/book/en/src/by-example/tips/from_ram.md b/book/en/src/by-example/tips/from_ram.md new file mode 100644 index 0000000..7306e12 --- /dev/null +++ b/book/en/src/by-example/tips/from_ram.md @@ -0,0 +1,45 @@ +# Running tasks from RAM + +The main goal of moving the specification of RTIC applications to attributes in RTIC v0.4.0 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 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 +{{#include ../../../../../rtic/examples/ramfunc.rs}} +``` + +Running this program produces the expected output. + +``` console +$ cargo run --target thumbv7m-none-eabi --example ramfunc +``` + +``` console +{{#include ../../../../../rtic/ci/expected/ramfunc.run}} +``` + +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::' +``` + +``` console +{{#include ../../../../../rtic/ci/expected/ramfunc.run.grep.foo}} +``` + +``` console +$ cargo nm --example ramfunc --target thumbv7m-none-eabi --release | grep '*bar::' +``` + +``` console +{{#include ../../../../../rtic/ci/expected/ramfunc.run.grep.bar}} +``` diff --git a/book/en/src/by-example/tips/index.md b/book/en/src/by-example/tips/index.md new file mode 100644 index 0000000..18d5991 --- /dev/null +++ b/book/en/src/by-example/tips/index.md @@ -0,0 +1,3 @@ +# Tips & tricks + +In this section we will explore common tips & tricks related to using RTIC. diff --git a/book/en/src/by-example/tips/indirection.md b/book/en/src/by-example/tips/indirection.md new file mode 100644 index 0000000..eef0d8e --- /dev/null +++ b/book/en/src/by-example/tips/indirection.md @@ -0,0 +1,26 @@ +# Using indirection for faster message passing + +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. + +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 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 +{{#include ../../../../../rtic/examples/pool.rs}} +``` + +``` console +$ cargo run --target thumbv7m-none-eabi --example pool +``` + +``` console +{{#include ../../../../../rtic/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 new file mode 100644 index 0000000..9f88c19 --- /dev/null +++ b/book/en/src/by-example/tips/monotonic_impl.md @@ -0,0 +1,25 @@ +# Implementing a `Monotonic` timer for scheduling + +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-time::Monotonic` trait. + +For RTIC 1.0 and 2.0 we instead assume the user has a time library, e.g. [`fugit`], as the basis for all time-based operations when implementing `Monotonic`. 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. There are reference implementations available in [`rtic-monotonics`] that can be used for inspriation. + +- [`Systick based`], runs at a fixed interrupt (tick) rate - with some overhead but simple and provides support for large time spans +- [`RP2040 Timer`], a "proper" implementation with support for waiting for long periods without interrupts. Clearly demonstrates how to use the `TimerQueue` to handle scheduling. +- [`nRF52 timers`] implements monotonic & Timer Queue for the RTC and normal timers in nRF52's + +## Contributing + +Contributing new implementations of `Monotonic` can be done in multiple ways: +* Implement the trait behind a feature flag in [`rtic-monotonics`], and create a PR for them to be included in the main RTIC repository. This way, the implementations of are in-tree, and RTIC can guarantee their correctness, and can update them in the case of a new release. +* Implement the changes in an external repository. + +[`rtic-monotonics`]: https://github.com/rtic-rs/rtic/tree/master/rtic-monotonics/ +[`rtic_time::Monotonic`]: https://docs.rs/rtic_time/ +[`fugit`]: https://docs.rs/fugit/ +[`Systick based`]: https://github.com/rtic-monotonics +[`rtic-monotonics`]: https://github.com/rtic-rs/rtic/blob/master/rtic-monotonics +[`RP2040 Timer`]: https://github.com/rtic-rs/rtic/blob/master/rtic-monotonics/src/rp2040.rs +[`nRF52 timers`]: https://github.com/rtic-rs/rtic/blob/master/rtic-monotonics/src/nrf.rs
\ No newline at end of file diff --git a/book/en/src/by-example/tips/static_lifetimes.md b/book/en/src/by-example/tips/static_lifetimes.md new file mode 100644 index 0000000..b1fd606 --- /dev/null +++ b/book/en/src/by-example/tips/static_lifetimes.md @@ -0,0 +1,23 @@ +# 'static super-powers + +In `#[init]` and `#[idle]` `local` resources have `'static` lifetime. + +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`]. + +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 ../../../../../rtic/examples/static.rs}} +``` + +Running this program produces the expected output. + +``` console +$ cargo run --target thumbv7m-none-eabi --example static +``` + +``` console +{{#include ../../../../../rtic/ci/expected/static.run}} +``` diff --git a/book/en/src/by-example/tips/view_code.md b/book/en/src/by-example/tips/view_code.md new file mode 100644 index 0000000..b4a9066 --- /dev/null +++ b/book/en/src/by-example/tips/view_code.md @@ -0,0 +1,47 @@ +# Inspecting generated code + +`#[rtic::app]` is a procedural macro that produces support code. If for some reason you need to inspect the code generated by this macro you have two 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` on it before you read it. + +``` console +$ cargo build --example smallest --target thumbv7m-none-eabi +``` + +``` console +$ rustfmt target/rtic-expansion.rs +``` + +``` console +$ tail target/rtic-expansion.rs +``` + +``` rust +#[doc = r" Implementation details"] +mod app { + #[doc = r" Always include the device crate which contains the vector table"] + use lm3s6965 as _; + #[no_mangle] + unsafe extern "C" fn main() -> ! { + rtic::export::interrupt::disable(); + let mut core: rtic::export::Peripherals = core::mem::transmute(()); + core.SCB.scr.modify(|r| r | 1 << 1); + rtic::export::interrupt::enable(); + loop { + rtic::export::wfi() + } + } +} +``` + +Or, you can use the [`cargo-expand`] sub-command. This sub-command will expand *all* the macros, including the `#[rtic::app]` attribute, and modules in your crate and print the output to the console. + +[`cargo-expand`]: https://crates.io/crates/cargo-expand + +``` console +# produces the same output as before +``` + +``` console +cargo expand --example smallest | tail +``` |
