From e3603d1d0531a4593c4c75863fc77162813cf34f Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Fri, 5 May 2023 18:58:06 +0200 Subject: Rename deprecated to archive --- book/en/archive/by_example/monotonic.md | 64 +++++ book/en/archive/migration.md | 4 + book/en/archive/migration/migration_rtic.md | 50 ++++ book/en/archive/migration/migration_v4.md | 247 ++++++++++++++++++ book/en/archive/migration/migration_v5.md | 372 ++++++++++++++++++++++++++++ 5 files changed, 737 insertions(+) create mode 100644 book/en/archive/by_example/monotonic.md create mode 100644 book/en/archive/migration.md create mode 100644 book/en/archive/migration/migration_rtic.md create mode 100644 book/en/archive/migration/migration_v4.md create mode 100644 book/en/archive/migration/migration_v5.md (limited to 'book/en/archive') diff --git a/book/en/archive/by_example/monotonic.md b/book/en/archive/by_example/monotonic.md new file mode 100644 index 0000000..0ed4340 --- /dev/null +++ b/book/en/archive/by_example/monotonic.md @@ -0,0 +1,64 @@ +# 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 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. + +The `#[monotonic]` attribute, applied to a type alias definition, exists to support this. +This type alias must point to a type which implements the [`rtic_monotonic::Monotonic`] trait. +This is generally some timer which handles the timing of the system. +One or more monotonics can coexist in the same system, for example a slow timer that wakes the +system from sleep and another which purpose is for fine grained scheduling while the +system is awake. + +[`rtic_monotonic::Monotonic`]: https://docs.rs/rtic-monotonic + +The attribute has one required parameter and two optional parameters, `binds`, `default` and +`priority` respectively. +The required parameter, `binds = InterruptName`, associates an interrupt vector to the timer's +interrupt, while `default = true` enables a shorthand API when spawning and accessing +time (`monotonics::now()` vs `monotonics::MyMono::now()`), and `priority` sets the priority +of the interrupt vector. + +> The default `priority` is the **maximum priority** of the system. +> If your system has a high priority task with tight scheduling requirements, +> it might be desirable to demote the `monotonic` task to a lower priority +> to reduce scheduling jitter for the high priority task. +> This however might introduce jitter and delays into scheduling via the `monotonic`, +> making it a trade-off. + +The monotonics are initialized in `#[init]` and returned within the `init::Monotonic( ... )` tuple. +This activates the monotonics making it possible to use them. + +See the following example: + +``` rust,noplayground +{{#include ../../../../examples/schedule.rs}} +``` + +``` console +$ 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: + +``` rust,noplayground +{{#include ../../../../examples/cancel-reschedule.rs}} +``` + +``` console +$ cargo run --target thumbv7m-none-eabi --example cancel-reschedule +{{#include ../../../../ci/expected/cancel-reschedule.run}} +``` diff --git a/book/en/archive/migration.md b/book/en/archive/migration.md new file mode 100644 index 0000000..f52b0a5 --- /dev/null +++ b/book/en/archive/migration.md @@ -0,0 +1,4 @@ +# Migration Guides + +This section describes how to migrate between different versions of RTIC. +It also acts as a comparing reference between versions. diff --git a/book/en/archive/migration/migration_rtic.md b/book/en/archive/migration/migration_rtic.md new file mode 100644 index 0000000..e079cbf --- /dev/null +++ b/book/en/archive/migration/migration_rtic.md @@ -0,0 +1,50 @@ +# Migrating from RTFM to RTIC + +This section covers how to upgrade an application written against RTFM v0.5.x to +the same version of RTIC. This applies since the renaming of the framework as per [RFC #33]. + +**Note:** There are no code differences between RTFM v0.5.3 and RTIC v0.5.3, it is purely a name +change. + +[RFC #33]: https://github.com/rtic-rs/rfcs/pull/33 + +## `Cargo.toml` + +First, the `cortex-m-rtfm` dependency needs to be updated to +`cortex-m-rtic`. + +``` toml +[dependencies] +# change this +cortex-m-rtfm = "0.5.3" + +# into this +cortex-m-rtic = "0.5.3" +``` + +## Code changes + +The only code change that needs to be made is that any reference to `rtfm` before now need to point +to `rtic` as follows: + +``` rust,noplayground +// +// Change this +// + +#[rtfm::app(/* .. */, monotonic = rtfm::cyccnt::CYCCNT)] +const APP: () = { + // ... + +}; + +// +// Into this +// + +#[rtic::app(/* .. */, monotonic = rtic::cyccnt::CYCCNT)] +const APP: () = { + // ... + +}; +``` diff --git a/book/en/archive/migration/migration_v4.md b/book/en/archive/migration/migration_v4.md new file mode 100644 index 0000000..f28b6d9 --- /dev/null +++ b/book/en/archive/migration/migration_v4.md @@ -0,0 +1,247 @@ +# Migrating from v0.4.x to v0.5.0 + +This section covers how to upgrade an application written against RTFM v0.4.x to +the version v0.5.0 of the framework. + +## Project name change RTFM -> RTIC + +With release [v0.5.2][rtic0.5.2] the name was change to Real-Time Interrupt-driven Concurrency + +All occurrences of `RTFM` needs to change to `RTIC`. + +See [migration guide RTFM to RTIC](./migration_rtic.md) + +[rtic0.5.2]: https://crates.io/crates/cortex-m-rtic/0.5.2 + +## `Cargo.toml` + +Change the version of `cortex-m-rtfm` to +`"0.5.0"`, change `rtfm` to `rtic`. +Remove the `timer-queue` feature. + +``` toml +[dependencies.cortex-m-rtfm] +# change this +version = "0.4.3" + +# into this +[dependencies.cortex-m-rtic] +version = "0.5.0" + +# and remove this Cargo feature +features = ["timer-queue"] +# ^^^^^^^^^^^^^ +``` + +## `Context` argument + +All functions inside the `#[rtfm::app]` item need to take as first argument a +`Context` structure. This `Context` type will contain the variables that were +magically injected into the scope of the function by version v0.4.x of the +framework: `resources`, `spawn`, `schedule` -- these variables will become +fields of the `Context` structure. Each function within the `#[rtfm::app]` item +gets a different `Context` type. + +``` rust,noplayground +#[rtfm::app(/* .. */)] +const APP: () = { + // change this + #[task(resources = [x], spawn = [a], schedule = [b])] + fn foo() { + resources.x.lock(|x| /* .. */); + spawn.a(message); + schedule.b(baseline); + } + + // into this + #[task(resources = [x], spawn = [a], schedule = [b])] + fn foo(mut cx: foo::Context) { + // ^^^^^^^^^^^^^^^^^^^^ + + cx.resources.x.lock(|x| /* .. */); + // ^^^ + + cx.spawn.a(message); + // ^^^ + + cx.schedule.b(message, baseline); + // ^^^ + } + + // change this + #[init] + fn init() { + // .. + } + + // into this + #[init] + fn init(cx: init::Context) { + // ^^^^^^^^^^^^^^^^^ + // .. + } + + // .. +}; +``` + +## Resources + +The syntax used to declare resources has changed from `static mut` +variables to a `struct Resources`. + +``` rust,noplayground +#[rtfm::app(/* .. */)] +const APP: () = { + // change this + static mut X: u32 = 0; + static mut Y: u32 = (); // late resource + + // into this + struct Resources { + #[init(0)] // <- initial value + X: u32, // NOTE: we suggest changing the naming style to `snake_case` + + Y: u32, // late resource + } + + // .. +}; +``` + +## Device peripherals + +If your application was accessing the device peripherals in `#[init]` through +the `device` variable then you'll need to add `peripherals = true` to the +`#[rtfm::app]` attribute to continue to access the device peripherals through +the `device` field of the `init::Context` structure. + +Change this: + +``` rust,noplayground +#[rtfm::app(/* .. */)] +const APP: () = { + #[init] + fn init() { + device.SOME_PERIPHERAL.write(something); + } + + // .. +}; +``` + +Into this: + +``` rust,noplayground +#[rtfm::app(/* .. */, peripherals = true)] +// ^^^^^^^^^^^^^^^^^^ +const APP: () = { + #[init] + fn init(cx: init::Context) { + // ^^^^^^^^^^^^^^^^^ + cx.device.SOME_PERIPHERAL.write(something); + // ^^^ + } + + // .. +}; +``` + +## `#[interrupt]` and `#[exception]` + +Remove the attributes `#[interrupt]` and `#[exception]`. +To declare hardware tasks in v0.5.x use the `#[task]` +attribute with the `binds` argument instead. + +Change this: + +``` rust,noplayground +#[rtfm::app(/* .. */)] +const APP: () = { + // hardware tasks + #[exception] + fn SVCall() { /* .. */ } + + #[interrupt] + fn UART0() { /* .. */ } + + // software task + #[task] + fn foo() { /* .. */ } + + // .. +}; +``` + +Into this: + +``` rust,noplayground +#[rtfm::app(/* .. */)] +const APP: () = { + #[task(binds = SVCall)] + // ^^^^^^^^^^^^^^ + fn svcall(cx: svcall::Context) { /* .. */ } + // ^^^^^^ we suggest you use a `snake_case` name here + + #[task(binds = UART0)] + // ^^^^^^^^^^^^^ + fn uart0(cx: uart0::Context) { /* .. */ } + + #[task] + fn foo(cx: foo::Context) { /* .. */ } + + // .. +}; +``` + +## `schedule` + +The `schedule` API no longer requires the `timer-queue` cargo feature. +To use the `schedule` API one must first define the monotonic timer the +runtime will use using the `monotonic` argument of the `#[rtfm::app]` attribute. +To continue using the cycle counter (CYCCNT) as the monotonic timer, +and match the behavior of version v0.4.x, add the `monotonic = rtfm::cyccnt::CYCCNT` +argument to the `#[rtfm::app]` attribute. + +Also, the `Duration` and `Instant` types and the `U32Ext` trait moved +into the `rtfm::cyccnt` module. +This module is only available on ARMv7-M+ devices. +The removal of the `timer-queue` also brings back the `DWT` peripheral +inside the core peripherals struct, if `DWT` is required, +ensure it is enabled by the application inside `init`. + +Change this: + +``` rust,noplayground +use rtfm::{Duration, Instant, U32Ext}; + +#[rtfm::app(/* .. */)] +const APP: () = { + #[task(schedule = [b])] + fn a() { + // .. + } +}; +``` + +Into this: + +``` rust,noplayground +use rtfm::cyccnt::{Duration, Instant, U32Ext}; +// ^^^^^^^^ + +#[rtfm::app(/* .. */, monotonic = rtfm::cyccnt::CYCCNT)] +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +const APP: () = { + #[init] + fn init(cx: init::Context) { + cx.core.DWT.enable_cycle_counter(); + // optional, configure the DWT run without a debugger connected + cx.core.DCB.enable_trace(); + } + #[task(schedule = [b])] + fn a(cx: a::Context) { + // .. + } +}; +``` diff --git a/book/en/archive/migration/migration_v5.md b/book/en/archive/migration/migration_v5.md new file mode 100644 index 0000000..1b4fa0d --- /dev/null +++ b/book/en/archive/migration/migration_v5.md @@ -0,0 +1,372 @@ +# Migrating from v0.5.x to v1.0.0 + +This section describes how to upgrade from v0.5.x to v1.0.0 of the RTIC framework. + +## `Cargo.toml` - version bump + +Change the version of `cortex-m-rtic` to `"1.0.0"`. + +## `mod` instead of `const` + +With the support of attributes on modules the `const APP` workaround is not needed. + +Change + +``` rust,noplayground +#[rtic::app(/* .. */)] +const APP: () = { + [code here] +}; +``` + +into + +``` rust,noplayground +#[rtic::app(/* .. */)] +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 used in user +code must be moved inside `mod app`, or be referred to with `super`. For +example, change: + +```rust +use some_crate::some_func; + +#[rtic::app(/* .. */)] +const APP: () = { + fn func() { + some_crate::some_func(); + } +}; +``` + +into + +```rust +#[rtic::app(/* .. */)] +mod app { + use some_crate::some_func; + + fn func() { + some_crate::some_func(); + } +} +``` + +or + +```rust +use some_crate::some_func; + +#[rtic::app(/* .. */)] +mod app { + fn func() { + super::some_crate::some_func(); + } +} +``` + +## Move Dispatchers from `extern "C"` to app arguments + +Change + +``` rust,noplayground +#[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(); + } +}; +``` + +into + +``` rust,noplayground +#[rtic::app(/* .. */, dispatchers = [SSI0, QEI0])] +mod app { + [code here] +} +``` + +This works also for ram functions, see examples/ramfunc.rs + + +## Resources structs - `#[shared]`, `#[local]` + +Previously the RTIC resources had to be in in a struct named exactly "Resources": + +``` rust,noplayground +struct Resources { + // Resources defined in here +} +``` + +With RTIC v1.0.0 the resources structs are annotated similarly like +`#[task]`, `#[init]`, `#[idle]`: with the attributes `#[shared]` and `#[local]` + +``` rust,noplayground +#[shared] +struct MySharedResources { + // Resources shared between tasks are defined here +} + +#[local] +struct MyLocalResources { + // Resources defined here cannot be shared between tasks; each one is local to a single task +} +``` + +These structs can be freely named by the developer. + +## `shared` and `local` arguments in `#[task]`s + +In v1.0.0 resources are split between `shared` resources and `local` resources. +`#[task]`, `#[init]` and `#[idle]` no longer have a `resources` argument; they must now use the `shared` and `local` arguments. + +In v0.5.x: + +``` rust,noplayground +struct Resources { + local_to_b: i64, + shared_by_a_and_b: i64, +} + +#[task(resources = [shared_by_a_and_b])] +fn a(_: a::Context) {} + +#[task(resources = [shared_by_a_and_b, local_to_b])] +fn b(_: b::Context) {} +``` + +In v1.0.0: + +``` rust,noplayground +#[shared] +struct Shared { + shared_by_a_and_b: i64, +} + +#[local] +struct Local { + local_to_b: i64, +} + +#[task(shared = [shared_by_a_and_b])] +fn a(_: a::Context) {} + +#[task(shared = [shared_by_a_and_b], local = [local_to_b])] +fn b(_: b::Context) {} +``` + +## Symmetric locks + +Now RTIC utilizes symmetric locks, this means that the `lock` method need +to be used for all `shared` resource access. +In old code one could do the following as the high priority +task has exclusive access to the resource: + +``` rust,noplayground +#[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,noplayground +#[task(priority = 2, shared = [r])] +fn foo(cx: foo::Context) { + cx.shared.r.lock(|r| r = /* ... */); +} + +#[task(shared = [r])] +fn bar(cx: bar::Context) { + cx.shared.r.lock(|r| r = /* ... */); +} +``` + +Note that the performance does not change thanks to LLVM's optimizations which optimizes away unnecessary locks. + +## Lock-free resource access + +In RTIC 0.5 resources shared by tasks running at the same priority could be accessed *without* the `lock` API. +This is still possible in 1.0: the `#[shared]` resource must be annotated with the field-level `#[lock_free]` attribute. + +v0.5 code: + +``` rust,noplayground +struct Resources { + counter: u64, +} + +#[task(resources = [counter])] +fn a(cx: a::Context) { + *cx.resources.counter += 1; +} + +#[task(resources = [counter])] +fn b(cx: b::Context) { + *cx.resources.counter += 1; +} +``` + +v1.0 code: + +``` rust,noplayground +#[shared] +struct Shared { + #[lock_free] + counter: u64, +} + +#[task(shared = [counter])] +fn a(cx: a::Context) { + *cx.shared.counter += 1; +} + +#[task(shared = [counter])] +fn b(cx: b::Context) { + *cx.shared.counter += 1; +} +``` + +## no `static mut` transform + +`static mut` variables are no longer transformed to safe `&'static mut` references. +Instead of that syntax, use the `local` argument in `#[init]`. + +v0.5.x code: + +``` rust,noplayground +#[init] +fn init(_: init::Context) { + static mut BUFFER: [u8; 1024] = [0; 1024]; + let buffer: &'static mut [u8; 1024] = BUFFER; +} +``` + +v1.0.0 code: + +``` rust,noplayground +#[init(local = [ + buffer: [u8; 1024] = [0; 1024] +// type ^^^^^^^^^^^^ ^^^^^^^^^ initial value +])] +fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + let buffer: &'static mut [u8; 1024] = cx.local.buffer; + + (Shared {}, Local {}, init::Monotonics()) +} +``` + +## Init always returns late resources + +In order to make the API more symmetric the #[init]-task always returns a late resource. + +From this: + +``` rust,noplayground +#[rtic::app(device = lm3s6965)] +const APP: () = { + #[init] + fn init(_: init::Context) { + rtic::pend(Interrupt::UART0); + } + + // [more code] +}; +``` + +to this: + +``` rust,noplayground +#[rtic::app(device = lm3s6965)] +mod app { + #[shared] + struct MySharedResources {} + + #[local] + struct MyLocalResources {} + + #[init] + fn init(_: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { + rtic::pend(Interrupt::UART0); + + (MySharedResources, MyLocalResources, init::Monotonics()) + } + + // [more code] +} +``` + +## Spawn from anywhere + +With the new spawn/spawn_after/spawn_at interface, +old code requiring the context `cx` for spawning such as: + +``` rust,noplayground +#[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,noplayground +#[task] +fn foo(_c: foo::Context) { + bar::spawn().unwrap(); +} + +#[task] +fn bar(_c: bar::Context) { + // Takes a Duration, relative to “now” + let spawn_handle = foo::spawn_after(/* ... */); +} + +#[task] +fn bar(_c: bar::Context) { + // Takes an Instant + let spawn_handle = foo::spawn_at(/* ... */); +} +``` + +Thus the requirement of having access to the context is dropped. + +Note that the attributes `spawn`/`schedule` in the task definition are no longer needed. + +--- + +## 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. + +See examples `examples/extern_binds.rs` and `examples/extern_spawn.rs`. + +This enables breaking apps into multiple files. -- cgit v1.2.3 From 03b16a3a2d83af9b520fa5b5bad3ba76155f594d Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Fri, 5 May 2023 19:20:57 +0200 Subject: Archive app_task.md --- book/en/archive/by_example/app_task.md | 23 +++++++++++++++++++++++ book/en/src/by-example/app_task.md | 23 ----------------------- 2 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 book/en/archive/by_example/app_task.md delete mode 100644 book/en/src/by-example/app_task.md (limited to 'book/en/archive') diff --git a/book/en/archive/by_example/app_task.md b/book/en/archive/by_example/app_task.md new file mode 100644 index 0000000..b2731f6 --- /dev/null +++ b/book/en/archive/by_example/app_task.md @@ -0,0 +1,23 @@ + + +# Defining tasks with `#[task]` + +Tasks, defined with `#[task]`, are the main mechanism of getting work done in RTIC. + +Tasks can + +* 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, 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/app_task.md b/book/en/src/by-example/app_task.md deleted file mode 100644 index b2731f6..0000000 --- a/book/en/src/by-example/app_task.md +++ /dev/null @@ -1,23 +0,0 @@ - - -# Defining tasks with `#[task]` - -Tasks, defined with `#[task]`, are the main mechanism of getting work done in RTIC. - -Tasks can - -* 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, 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. -- cgit v1.2.3 From 4b3bf59215d682e9473ca66545a1f7c2acbccbfe Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 20 May 2023 11:24:03 +0200 Subject: Move some more stuff to the archive, update this link --- book/en/archive/by_example/tips/from_ram.md | 45 +++++++++++++++++++++++++++++ book/en/src/SUMMARY.md | 2 -- book/en/src/by-example/tips/from_ram.md | 45 ----------------------------- book/en/src/by-example/tips/indirection.md | 2 +- 4 files changed, 46 insertions(+), 48 deletions(-) create mode 100644 book/en/archive/by_example/tips/from_ram.md delete mode 100644 book/en/src/by-example/tips/from_ram.md (limited to 'book/en/archive') diff --git a/book/en/archive/by_example/tips/from_ram.md b/book/en/archive/by_example/tips/from_ram.md new file mode 100644 index 0000000..a153139 --- /dev/null +++ b/book/en/archive/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,noplayground +{{#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/SUMMARY.md b/book/en/src/SUMMARY.md index baeb036..e8c8ee6 100644 --- a/book/en/src/SUMMARY.md +++ b/book/en/src/SUMMARY.md @@ -21,8 +21,6 @@ - [Avoid copies when message passing](./by-example/tips/indirection.md) - [`'static` super-powers](./by-example/tips/static_lifetimes.md) - [Inspecting generated code](./by-example/tips/view_code.md) - - - [RTIC vs. the world](./rtic_vs.md) - [Awesome RTIC examples](./awesome_rtic.md) diff --git a/book/en/src/by-example/tips/from_ram.md b/book/en/src/by-example/tips/from_ram.md deleted file mode 100644 index a153139..0000000 --- a/book/en/src/by-example/tips/from_ram.md +++ /dev/null @@ -1,45 +0,0 @@ -# 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,noplayground -{{#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/indirection.md b/book/en/src/by-example/tips/indirection.md index 58b3bde..aa68190 100644 --- a/book/en/src/by-example/tips/indirection.md +++ b/book/en/src/by-example/tips/indirection.md @@ -7,7 +7,7 @@ Indirection can minimize message passing overhead: instead of sending 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 +[`heapless::Pool`]: https://docs.rs/heapless/latest/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`. -- cgit v1.2.3