From 5f7dc0b903a3d26a5bd49864dce42f3d91d3d2a8 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 14 Jul 2021 12:44:25 +0200 Subject: [PATCH 1/2] update the 0.5.x -> 0.6.0 migration guide to use the new resources syntax I also reordered the sections to cover all the resource API first before covering the spawn API I've also added a section about the old `static mut` variable transform --- book/en/src/migration/migration_v5.md | 201 +++++++++++++++++--------- 1 file changed, 136 insertions(+), 65 deletions(-) diff --git a/book/en/src/migration/migration_v5.md b/book/en/src/migration/migration_v5.md index d3f2c9a645..154714e354 100644 --- a/book/en/src/migration/migration_v5.md +++ b/book/en/src/migration/migration_v5.md @@ -102,6 +102,134 @@ mod app { 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 +struct Resources { + // Resources defined in here +} +``` + +With RTIC v0.6.0 the resources structs are annotated similarly like +`#[task]`, `#[init]`, `#[idle]`: with the attributes `#[shared]` and `#[local]` + +``` rust +#[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 v0.6.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 +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 v0.6.0: + +``` rust +#[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 +#[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, 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. + +## 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 +#[init] +fn init(_: init::Context) { + static mut BUFFER: [u8; 1024] = [0; 1024]; + let buffer: &'static mut [u8; 1024] = BUFFER; +} +``` + +v0.6.0 code: + +``` rust +#[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. @@ -125,48 +253,23 @@ to this: ``` rust #[rtic::app(device = lm3s6965)] mod app { + #[shared] + struct MySharedResources {} + + #[local] + struct MyLocalResources {} + #[init] - fn init(_: init::Context) -> (init::LateResources, init::Monotonics) { + fn init(_: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { rtic::pend(Interrupt::UART0); - (init::LateResources {}, init::Monotonics()) + (MySharedResources, MyLocalResources, init::Monotonics {}) } // [more code] } ``` -## Resources struct - `#[resources]` - -Previously the RTIC resources had to be in in a struct named exactly "Resources": - -``` rust -struct Resources { - // Resources defined in here -} -``` - -With RTIC v0.6.0 the resources struct is annotated similarly like -`#[task]`, `#[init]`, `#[idle]`: with an attribute `#[resources]` - -``` rust -#[resources] -struct Resources { - // Resources defined in here -} -``` - -In fact, the name of the struct is now up to the developer: - -``` rust -#[resources] -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: @@ -201,37 +304,6 @@ fn bar(_c: bar::Context) { 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. --- @@ -242,4 +314,3 @@ Note that the performance does not change thanks to LLVM's optimizations which o 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`. - From 18880406cb425bcd030f0b0aa9e67e8ac05bd852 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 21 Jul 2021 10:14:00 +0200 Subject: [PATCH 2/2] use tuple struct syntax for Monotonics everywhere --- book/en/src/migration/migration_v5.md | 4 ++-- examples/smallest.rs | 2 +- examples/spawn.rs | 2 +- examples/spawn2.rs | 2 +- macros/src/tests/single.rs | 2 +- ui/exception-invalid.rs | 2 +- ui/extern-interrupt-not-enough.rs | 2 +- ui/extern-interrupt-used.rs | 2 +- ui/task-priority-too-high.rs | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/book/en/src/migration/migration_v5.md b/book/en/src/migration/migration_v5.md index 154714e354..210063bf5e 100644 --- a/book/en/src/migration/migration_v5.md +++ b/book/en/src/migration/migration_v5.md @@ -226,7 +226,7 @@ v0.6.0 code: fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { let buffer: &'static mut [u8; 1024] = cx.local.buffer; - (Shared {}, Local {}, init::Monotonics {}) + (Shared {}, Local {}, init::Monotonics()) } ``` @@ -263,7 +263,7 @@ mod app { fn init(_: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) { rtic::pend(Interrupt::UART0); - (MySharedResources, MyLocalResources, init::Monotonics {}) + (MySharedResources, MyLocalResources, init::Monotonics()) } // [more code] diff --git a/examples/smallest.rs b/examples/smallest.rs index 6afcfbd4d0..31750e257a 100644 --- a/examples/smallest.rs +++ b/examples/smallest.rs @@ -16,6 +16,6 @@ mod app { #[init] fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { - (Shared {}, Local {}, init::Monotonics {}) + (Shared {}, Local {}, init::Monotonics()) } } diff --git a/examples/spawn.rs b/examples/spawn.rs index bcb4fb235f..435cdf5697 100644 --- a/examples/spawn.rs +++ b/examples/spawn.rs @@ -21,7 +21,7 @@ mod app { fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { foo::spawn(1, 2).unwrap(); - (Shared {}, Local {}, init::Monotonics {}) + (Shared {}, Local {}, init::Monotonics()) } #[task()] diff --git a/examples/spawn2.rs b/examples/spawn2.rs index ff9516a6af..ed285b70cf 100644 --- a/examples/spawn2.rs +++ b/examples/spawn2.rs @@ -21,7 +21,7 @@ mod app { fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { foo::spawn(1, 2).unwrap(); - (Shared {}, Local {}, init::Monotonics {}) + (Shared {}, Local {}, init::Monotonics()) } #[task] diff --git a/macros/src/tests/single.rs b/macros/src/tests/single.rs index 27118856b7..f20c9ccbb3 100644 --- a/macros/src/tests/single.rs +++ b/macros/src/tests/single.rs @@ -18,7 +18,7 @@ fn analyze() { #[init] fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { - (Shared {}, Local {}, init::Monotonics {}) + (Shared {}, Local {}, init::Monotonics()) } #[task(priority = 1)] diff --git a/ui/exception-invalid.rs b/ui/exception-invalid.rs index d899443b9b..07d3c21f54 100644 --- a/ui/exception-invalid.rs +++ b/ui/exception-invalid.rs @@ -10,7 +10,7 @@ mod app { #[init] fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - (Shared {}, Local {}, init::Monotonics {}) + (Shared {}, Local {}, init::Monotonics()) } #[task(binds = NonMaskableInt)] diff --git a/ui/extern-interrupt-not-enough.rs b/ui/extern-interrupt-not-enough.rs index 6e7863475a..1dbe923c98 100644 --- a/ui/extern-interrupt-not-enough.rs +++ b/ui/extern-interrupt-not-enough.rs @@ -10,7 +10,7 @@ mod app { #[init] fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - (Shared {}, Local {}, init::Monotonics {}) + (Shared {}, Local {}, init::Monotonics()) } #[task] diff --git a/ui/extern-interrupt-used.rs b/ui/extern-interrupt-used.rs index a22b85f41b..882d5e3ab0 100644 --- a/ui/extern-interrupt-used.rs +++ b/ui/extern-interrupt-used.rs @@ -10,7 +10,7 @@ mod app { #[init] fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - (Shared {}, Local {}, init::Monotonics {}) + (Shared {}, Local {}, init::Monotonics()) } #[task(binds = UART0)] diff --git a/ui/task-priority-too-high.rs b/ui/task-priority-too-high.rs index 0d903d3a65..46ab561750 100644 --- a/ui/task-priority-too-high.rs +++ b/ui/task-priority-too-high.rs @@ -10,7 +10,7 @@ mod app { #[init] fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - (Shared {}, Local {}, init::Monotonics {}) + (Shared {}, Local {}, init::Monotonics()) } #[task(binds = GPIOA, priority = 1)]