aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml125
-rw-r--r--README.md26
-rw-r--r--book/en/src/SUMMARY.md6
-rw-r--r--book/en/src/by-example.md8
-rw-r--r--book/en/src/by-example/resources.md6
-rw-r--r--book/en/src/by-example/tips.md1
-rw-r--r--book/en/src/migration.md333
-rw-r--r--book/en/src/migration/migration_rtic.md (renamed from book/en/src/migration_rtic.md)4
-rw-r--r--book/en/src/migration/migration_v4.md233
-rw-r--r--book/en/src/migration/migration_v5.md96
-rw-r--r--examples/baseline.rs4
-rw-r--r--examples/binds.rs4
-rw-r--r--examples/capacity.rs4
-rw-r--r--examples/cfg.rs4
-rw-r--r--examples/destructure.rs4
-rw-r--r--examples/generics.rs4
-rw-r--r--examples/hardware.rs4
-rw-r--r--examples/idle.rs4
-rw-r--r--examples/init.rs4
-rw-r--r--examples/lock.rs4
-rw-r--r--examples/message.rs4
-rw-r--r--examples/not-send.rs4
-rw-r--r--examples/not-sync.rs4
-rw-r--r--examples/periodic.rs4
-rw-r--r--examples/peripherals-taken.rs4
-rw-r--r--examples/pool.rs4
-rw-r--r--examples/preempt.rs4
-rw-r--r--examples/ramfunc.rs4
-rw-r--r--examples/resource-user-struct.rs4
-rw-r--r--examples/resource.rs4
-rw-r--r--examples/schedule.rs4
-rw-r--r--examples/shared-with-init.rs4
-rw-r--r--examples/t-binds.rs4
-rw-r--r--examples/t-cfg.rs4
-rw-r--r--examples/t-htask-main.rs6
-rw-r--r--examples/t-idle-main.rs4
-rw-r--r--examples/t-init-main.rs4
-rw-r--r--examples/t-resource.rs4
-rw-r--r--examples/t-schedule.rs4
-rw-r--r--examples/t-spawn.rs4
-rw-r--r--examples/t-stask-main.rs4
-rw-r--r--examples/task.rs4
-rw-r--r--examples/types.rs4
-rw-r--r--macros/src/codegen/init.rs63
-rw-r--r--macros/src/codegen/module.rs12
-rw-r--r--macros/src/lib.rs3
-rw-r--r--ui/single/locals-cfg.rs4
-rw-r--r--ui/single/locals-cfg.stderr16
-rw-r--r--ui/single/resources-cfg.rs4
-rw-r--r--ui/single/resources-cfg.stderr40
-rw-r--r--ui/single/task-priority-too-high.rs4
51 files changed, 650 insertions, 468 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 56183c3a..8da98678 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -85,7 +85,7 @@ jobs:
command: check
args: --target=${{ matrix.target }}
- # Verify all examples
+ # Verify all examples, checks
checkexamples:
name: checkexamples
runs-on: ubuntu-20.04
@@ -140,6 +140,51 @@ jobs:
command: check
args: --examples --target=${{ matrix.target }} --features __min_r1_43,${{ env.V7 }}
+ # Verify the example output with run-pass tests
+ testexamples:
+ name: testexamples
+ runs-on: ubuntu-20.04
+ strategy:
+ matrix:
+ target:
+ - thumbv7m-none-eabi
+ - thumbv6m-none-eabi
+ toolchain:
+ - stable
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Cache cargo dependencies
+ uses: actions/cache@v2
+ with:
+ path: |
+ - ~/.cargo/bin/
+ - ~/.cargo/registry/index/
+ - ~/.cargo/registry/cache/
+ - ~/.cargo/git/db/
+ key: ${{ runner.OS }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.OS }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ ${{ runner.OS }}-cargo-
+
+ - name: Cache build output dependencies
+ uses: actions/cache@v2
+ with:
+ path: target
+ key: ${{ runner.OS }}-build-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.OS }}-build-${{ hashFiles('**/Cargo.lock') }}
+ ${{ runner.OS }}-build-
+
+ - name: Install Rust ${{ matrix.toolchain }} with target (${{ matrix.target }})
+ uses: actions-rs/toolchain@v1
+ with:
+ toolchain: ${{ matrix.toolchain }}
+ target: ${{ matrix.target }}
+ override: true
+ components: llvm-tools-preview
+
# Use precompiled binutils
- name: cargo install cargo-binutils
uses: actions-rs/install@v0.1
@@ -341,6 +386,56 @@ jobs:
command: check
args: --manifest-path macros/Cargo.toml --target=${{ matrix.target }}
+ # Run the macros test-suite
+ testmacros:
+ name: testmacros
+ runs-on: ubuntu-20.04
+ strategy:
+ matrix:
+ target:
+ - x86_64-unknown-linux-gnu
+ toolchain:
+ - stable
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Cache cargo dependencies
+ uses: actions/cache@v2
+ with:
+ path: |
+ - ~/.cargo/bin/
+ - ~/.cargo/registry/index/
+ - ~/.cargo/registry/cache/
+ - ~/.cargo/git/db/
+ key: ${{ runner.OS }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.OS }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+ ${{ runner.OS }}-cargo-
+
+ - name: Cache build output dependencies
+ uses: actions/cache@v2
+ with:
+ path: target
+ key: ${{ runner.OS }}-build-${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ ${{ runner.OS }}-build-${{ hashFiles('**/Cargo.lock') }}
+ ${{ runner.OS }}-build-
+
+ - name: Install Rust ${{ matrix.toolchain }} with target (${{ matrix.target }})
+ uses: actions-rs/toolchain@v1
+ with:
+ toolchain: ${{ matrix.toolchain }}
+ target: ${{ matrix.target }}
+ override: true
+
+ - name: cargo check
+ uses: actions-rs/cargo@v1
+ with:
+ use-cross: false
+ command: test
+ args: --manifest-path macros/Cargo.toml --target=${{ matrix.target }}
+
# Run test suite for thumbv7m
testv7:
name: testv7
@@ -513,7 +608,7 @@ jobs:
- name: mdBook Action
uses: peaceiris/actions-mdbook@v1.1.11
with:
- mdbook-version: '0.3.1'
+ mdbook-version: 'latest'
- name: Build book in English
run: cd book/en && mdbook build
@@ -541,7 +636,9 @@ jobs:
- style
- check
- checkexamples
+ - testexamples
- checkmacros
+ - testmacros
- testv7
- testv6
- docs
@@ -566,8 +663,7 @@ jobs:
- name: mdBook Action
uses: peaceiris/actions-mdbook@v1.1.11
with:
- mdbook-version: '0.3.1'
- # mdbook-version: 'latest'
+ mdbook-version: 'latest'
- name: Remove cargo-config
run: rm -f .cargo/config
@@ -579,13 +675,16 @@ jobs:
run: |
langs=( en ru )
devver=( dev )
- # Query git for tagged releases, all releases start with "v"
- # followed by MAJOR.MINOR.PATCH, see semver.org
- # Then remove all pre-releases/tags with hyphens (-).
- # The latest release is last, finally trim "v" and PATCH
- stable=$(git tag | grep "^v" | grep -v "-" | tail -n 1 | cut -c2-4)
+ # The latest stable must be the first element in the array
vers=( 0.5.x 0.4.x )
+ # All releases start with "v"
+ # followed by MAJOR.MINOR.PATCH, see semver.org
+ # Retain MAJOR.MINOR as $stable
+ stable=${vers%.*}
+
+ echo "Stable version: $stable"
+
# Create directories
td=$(mktemp -d)
mkdir -p $td/$devver/book/
@@ -630,8 +729,8 @@ jobs:
rm -rf $src
done
- # Create alias for the stable release
- ln -s $stable $td/stable
+ # Copy the stable book to the stable alias
+ cp -r $td/$stable $td/stable
# Forward CNAME file
cp CNAME $td/
@@ -654,7 +753,9 @@ jobs:
- style
- check
- checkexamples
+ - testexamples
- checkmacros
+ - testmacros
- testv7
- testv6
- docs
@@ -670,7 +771,9 @@ jobs:
- style
- check
- checkexamples
+ - testexamples
- checkmacros
+ - testmacros
- testv7
- testv6
- docs
diff --git a/README.md b/README.md
index 45bb9de8..929a813c 100644
--- a/README.md
+++ b/README.md
@@ -4,10 +4,12 @@ A concurrency framework for building real-time systems.
Formerly known as Real-Time For the Masses.
-![crates.io](https://img.shields.io/crates/v/cortex-m-rtic)
-![docs.rs](https://docs.rs/cortex-m-rtic/badge.svg)
-![book](https://img.shields.io/badge/web-rtic.rs-red.svg?style=flat&label=book&colorB=d33847)
-![rustc](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)
+[![crates.io](https://img.shields.io/crates/v/cortex-m-rtic)](https://crates.io/crates/cortex-m-rtic)
+[![docs.rs](https://docs.rs/cortex-m-rtic/badge.svg)](https://docs.rs/cortex-m-rtic)
+[![book](https://img.shields.io/badge/web-rtic.rs-red.svg?style=flat&label=book&colorB=d33847)](https://rtic.rs/)
+[![rustc](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://github.com/rust-lang/rust/releases/tag/1.36.0)
+[![matrix](https://img.shields.io/matrix/rtic:matrix.org)](https://matrix.to/#/#rtic:matrix.org)
+[![Meeting notes](https://hackmd.io/badge.svg)](https://hackmd.io/@xmis9JvZT8Gvo9lOEKyZ4Q/SkBJKsjuH)
## Features
@@ -52,23 +54,29 @@ Formerly known as Real-Time For the Masses.
## [User documentation](https://rtic.rs)
-## [API reference](https://rtic.rs/0.5/api/)
+## [API reference](https://rtic.rs/stable/api/)
## Chat
+
Join us and talk about RTIC in the [Matrix room][matrix-room].
+Weekly meeting notes can be found over at [HackMD][hackmd]
+
[matrix-room]: https://matrix.to/#/#rtic:matrix.org
+[hackmd]: https://hackmd.io/@xmis9JvZT8Gvo9lOEKyZ4Q/SkBJKsjuH
## Contributing
-New features and big changes should go through the RFC process in the [dedicated RFC repository][rfcs].
+
+New features and big changes should go through the RFC process in the
+[dedicated RFC repository][rfcs].
[rfcs]: https://github.com/rtic-rs/rfcs
## Acknowledgments
-This crate is based on [the Real-Time For the Masses language][rtfm-lang] created by the Embedded
-Systems group at [LuleƄ University of Technology][ltu], led by [Prof. Per
-Lindgren][per].
+This crate is based on [the Real-Time For the Masses language][rtfm-lang]
+created by the Embedded Systems group at [LuleƄ University of Technology][ltu],
+led by [Prof. Per Lindgren][per].
[rtfm-lang]: http://www.rtfm-lang.org/
[ltu]: https://www.ltu.se/?l=en
diff --git a/book/en/src/SUMMARY.md b/book/en/src/SUMMARY.md
index a573cbb5..e1a4a330 100644
--- a/book/en/src/SUMMARY.md
+++ b/book/en/src/SUMMARY.md
@@ -10,8 +10,10 @@
- [Types, Send and Sync](./by-example/types-send-sync.md)
- [Starting a new project](./by-example/new.md)
- [Tips & tricks](./by-example/tips.md)
-- [Migrating from v0.4.x to v0.5.0](./migration.md)
-- [Migrating from RTFM to RTIC](./migration_rtic.md)
+- [Migration Guides](./migration.md)
+ - [v0.5.x to v0.6.x](./migration/migration_v5.md)
+ - [v0.4.x to v0.5.x](./migration/migration_v4.md)
+ - [RTFM to RTIC](./migration/migration_rtic.md)
- [Under the hood](./internals.md)
- [Interrupt configuration](./internals/interrupt-configuration.md)
- [Non-reentrancy](./internals/non-reentrancy.md)
diff --git a/book/en/src/by-example.md b/book/en/src/by-example.md
index 38985da1..e4441fd9 100644
--- a/book/en/src/by-example.md
+++ b/book/en/src/by-example.md
@@ -14,3 +14,11 @@ program. Check [the embedded Rust book] for instructions on how to set up an
embedded development environment that includes QEMU.
[the embedded Rust book]: https://rust-embedded.github.io/book/intro/install.html
+
+## Real World Examples
+
+The following are examples of RTFM being used in real world projects.
+
+### RTFM V0.4.2
+
+- [etrombly/sandbox](https://github.com/etrombly/sandbox/tree/41d423bcdd0d8e42fd46b79771400a8ca349af55). A hardware zen garden that draws patterns in sand. Patterns are sent over serial using G-code.
diff --git a/book/en/src/by-example/resources.md b/book/en/src/by-example/resources.md
index d082dfc1..9d90fbe3 100644
--- a/book/en/src/by-example/resources.md
+++ b/book/en/src/by-example/resources.md
@@ -1,4 +1,4 @@
-## Resources
+# Resources
The framework provides an abstraction to share data between any of the contexts
we saw in the previous section (task handlers, `init` and `idle`): resources.
@@ -116,7 +116,9 @@ are required to access the resource even if the resource is contended by several
tasks running at different priorities. The downside is that the task only gets a
shared reference (`&-`) to the resource, limiting the operations it can perform
on it, but where a shared reference is enough this approach reduces the number
-of required locks.
+of required locks. In addition to simple immutable data, this shared access can
+be useful where the resource type safely implements interior mutability, with
+appropriate locking or atomic operations of its own.
Note that in this release of RTIC it is not possible to request both exclusive
access (`&mut-`) and shared access (`&-`) to the *same* resource from different
diff --git a/book/en/src/by-example/tips.md b/book/en/src/by-example/tips.md
index d8264c90..090b30ad 100644
--- a/book/en/src/by-example/tips.md
+++ b/book/en/src/by-example/tips.md
@@ -116,6 +116,7 @@ Here's an example where `heapless::Pool` is used to "box" buffers of 128 bytes.
``` rust
{{#include ../../../../examples/pool.rs}}
```
+
``` console
$ cargo run --example pool
{{#include ../../../../ci/expected/pool.run}}
diff --git a/book/en/src/migration.md b/book/en/src/migration.md
index 7be30943..08feb81e 100644
--- a/book/en/src/migration.md
+++ b/book/en/src/migration.md
@@ -1,331 +1,4 @@
-# Migration of RTIC
+# Migration Guides
-## Migrating from v0.5.x to v0.6.0
-
-This section describes how to upgrade from v0.5.x to v0.6.0 of the RTIC framework.
-
-### `Cargo.toml` - version bump
-
-Change the version of `cortex-m-rtic` to `"0.6.0"`.
-
-### Module 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]
-};
-```
-
-into
-
-``` rust
-#[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 etc may be required.
-
-### Init always returns late resources
-
-In order to make the API more symmetric the #[init]-task always returns a late resource.
-
-From this:
-
-``` rust
-#[rtic::app(device = lm3s6965)]
-mod app {
- #[init]
- fn init(_: init::Context) {
- rtic::pend(Interrupt::UART0);
- }
- [more code]
-}
-```
-
-to this:
-
-``` rust
-#[rtic::app(device = lm3s6965)]
-mod app {
- #[init]
- fn init(_: init::Context) -> init::LateResources {
- rtic::pend(Interrupt::UART0);
-
- init::LateResources {}
- }
- [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.
-
-## Migrating from v0.4.x to v0.5.0
-
-This section covers how to upgrade an application written against RTIC v0.4.x to
-the version v0.5.0 of the framework.
-
-### `Cargo.toml`
-
-First, the version of the `cortex-m-rtic` dependency needs to be updated to
-`"0.5.0"`. The `timer-queue` feature needs to be removed.
-
-``` toml
-[dependencies.cortex-m-rtic]
-# change this
-version = "0.4.3"
-
-# into this
-version = "0.5.0"
-
-# and remove this Cargo feature
-features = ["timer-queue"]
-# ^^^^^^^^^^^^^
-```
-
-### `Context` argument
-
-All functions inside the `#[rtic::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 `#[rtic::app]` item
-gets a different `Context` type.
-
-``` rust
-#[rtic::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 been changed from `static mut`
-variables to a `struct Resources`.
-
-``` rust
-#[rtic::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
-`#[rtic::app]` attribute to continue to access the device peripherals through
-the `device` field of the `init::Context` structure.
-
-Change this:
-
-``` rust
-#[rtic::app(/* .. */)]
-const APP: () = {
- #[init]
- fn init() {
- device.SOME_PERIPHERAL.write(something);
- }
-
- // ..
-};
-```
-
-Into this:
-
-``` rust
-#[rtic::app(/* .. */, peripherals = true)]
-// ^^^^^^^^^^^^^^^^^^
-const APP: () = {
- #[init]
- fn init(cx: init::Context) {
- // ^^^^^^^^^^^^^^^^^
- cx.device.SOME_PERIPHERAL.write(something);
- // ^^^
- }
-
- // ..
-};
-```
-
-### `#[interrupt]` and `#[exception]`
-
-The `#[interrupt]` and `#[exception]` attributes have been removed. To declare
-hardware tasks in v0.5.x use the `#[task]` attribute with the `binds` argument.
-
-Change this:
-
-``` rust
-#[rtic::app(/* .. */)]
-const APP: () = {
- // hardware tasks
- #[exception]
- fn SVCall() { /* .. */ }
-
- #[interrupt]
- fn UART0() { /* .. */ }
-
- // software task
- #[task]
- fn foo() { /* .. */ }
-
- // ..
-};
-```
-
-Into this:
-
-``` rust
-#[rtic::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 `timer-queue` feature has been removed. To use the `schedule` API one must
-first define the monotonic timer the runtime will use using the `monotonic`
-argument of the `#[rtic::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 = rtic::cyccnt::CYCCNT` argument to the `#[rtic::app]` attribute.
-
-Also, the `Duration` and `Instant` types and the `U32Ext` trait have been moved
-into the `rtic::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, this will need to be enabled by the application
-inside `init`.
-
-Change this:
-
-``` rust
-use rtic::{Duration, Instant, U32Ext};
-
-#[rtic::app(/* .. */)]
-const APP: () = {
- #[task(schedule = [b])]
- fn a() {
- // ..
- }
-};
-```
-
-Into this:
-
-``` rust
-use rtic::cyccnt::{Duration, Instant, U32Ext};
-// ^^^^^^^^
-
-#[rtic::app(/* .. */, monotonic = rtic::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) {
- // ..
- }
-};
-```
+This section describes how to migrate between different version of RTIC.
+It also acts as a comparing reference between versions.
diff --git a/book/en/src/migration_rtic.md b/book/en/src/migration/migration_rtic.md
index 555f1bb7..c027da35 100644
--- a/book/en/src/migration_rtic.md
+++ b/book/en/src/migration/migration_rtic.md
@@ -8,14 +8,11 @@ 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
@@ -51,4 +48,3 @@ const APP: () = {
};
```
-
diff --git a/book/en/src/migration/migration_v4.md b/book/en/src/migration/migration_v4.md
new file mode 100644
index 00000000..ac59d8c9
--- /dev/null
+++ b/book/en/src/migration/migration_v4.md
@@ -0,0 +1,233 @@
+# Migrating from v0.4.x to v0.5.0
+
+This section covers how to upgrade an application written against RTIC v0.4.x to
+the version v0.5.0 of the framework.
+
+## `Cargo.toml`
+
+First, the version of the `cortex-m-rtic` dependency needs to be updated to
+`"0.5.0"`. The `timer-queue` feature needs to be removed.
+
+``` toml
+[dependencies.cortex-m-rtic]
+# change this
+version = "0.4.3"
+
+# into this
+version = "0.5.0"
+
+# and remove this Cargo feature
+features = ["timer-queue"]
+# ^^^^^^^^^^^^^
+```
+
+## `Context` argument
+
+All functions inside the `#[rtic::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 `#[rtic::app]` item
+gets a different `Context` type.
+
+``` rust
+#[rtic::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 been changed from `static mut`
+variables to a `struct Resources`.
+
+``` rust
+#[rtic::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
+`#[rtic::app]` attribute to continue to access the device peripherals through
+the `device` field of the `init::Context` structure.
+
+Change this:
+
+``` rust
+#[rtic::app(/* .. */)]
+const APP: () = {
+ #[init]
+ fn init() {
+ device.SOME_PERIPHERAL.write(something);
+ }
+
+ // ..
+};
+```
+
+Into this:
+
+``` rust
+#[rtic::app(/* .. */, peripherals = true)]
+// ^^^^^^^^^^^^^^^^^^
+const APP: () = {
+ #[init]
+ fn init(cx: init::Context) {
+ // ^^^^^^^^^^^^^^^^^
+ cx.device.SOME_PERIPHERAL.write(something);
+ // ^^^
+ }
+
+ // ..
+};
+```
+
+## `#[interrupt]` and `#[exception]`
+
+The `#[interrupt]` and `#[exception]` attributes have been removed. To declare
+hardware tasks in v0.5.x use the `#[task]` attribute with the `binds` argument.
+
+Change this:
+
+``` rust
+#[rtic::app(/* .. */)]
+const APP: () = {
+ // hardware tasks
+ #[exception]
+ fn SVCall() { /* .. */ }
+
+ #[interrupt]
+ fn UART0() { /* .. */ }
+
+ // software task
+ #[task]
+ fn foo() { /* .. */ }
+
+ // ..
+};
+```
+
+Into this:
+
+``` rust
+#[rtic::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, which has
+been removed. To use the `schedule` API one must
+first define the monotonic timer the runtime will use using the `monotonic`
+argument of the `#[rtic::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 = rtic::cyccnt::CYCCNT` argument to the `#[rtic::app]` attribute.
+
+Also, the `Duration` and `Instant` types and the `U32Ext` trait have been moved
+into the `rtic::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, this will need to be enabled by the application
+inside `init`.
+
+Change this:
+
+``` rust
+use rtic::{Duration, Instant, U32Ext};
+
+#[rtic::app(/* .. */)]
+const APP: () = {
+ #[task(schedule = [b])]
+ fn a() {
+ // ..
+ }
+};
+```
+
+Into this:
+
+``` rust
+use rtic::cyccnt::{Duration, Instant, U32Ext};
+// ^^^^^^^^
+
+#[rtic::app(/* .. */, monotonic = rtic::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/src/migration/migration_v5.md b/book/en/src/migration/migration_v5.md
new file mode 100644
index 00000000..1d83444e
--- /dev/null
+++ b/book/en/src/migration/migration_v5.md
@@ -0,0 +1,96 @@
+# Migrating from v0.5.x to v0.6.0
+
+This section describes how to upgrade from v0.5.x to v0.6.0 of the RTIC framework.
+
+## `Cargo.toml` - version bump
+
+Change the version of `cortex-m-rtic` to `"0.6.0"`.
+
+## Module 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]
+};
+```
+
+into
+
+``` rust
+#[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 etc may be required.
+
+## Init always returns late resources
+
+In order to make the API more symmetric the #[init]-task always returns a late resource.
+
+From this:
+
+``` rust
+#[rtic::app(device = lm3s6965)]
+mod app {
+ #[init]
+ fn init(_: init::Context) {
+ rtic::pend(Interrupt::UART0);
+ }
+ [more code]
+}
+```
+
+to this:
+
+``` rust
+#[rtic::app(device = lm3s6965)]
+mod app {
+ #[init]
+ fn init(_: init::Context) -> init::LateResources {
+ rtic::pend(Interrupt::UART0);
+
+ init::LateResources {}
+ }
+ [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.
diff --git a/examples/baseline.rs b/examples/baseline.rs
index e517bf08..3ab40dbb 100644
--- a/examples/baseline.rs
+++ b/examples/baseline.rs
@@ -13,13 +13,15 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
mod app {
#[init(spawn = [foo])]
- fn init(cx: init::Context) {
+ fn init(cx: init::Context) -> init::LateResources {
// omitted: initialization of `CYCCNT`
hprintln!("init(baseline = {:?})", cx.start).unwrap();
// `foo` inherits the baseline of `init`: `Instant(0)`
cx.spawn.foo().unwrap();
+
+ init::LateResources {}
}
#[task(schedule = [foo])]
diff --git a/examples/binds.rs b/examples/binds.rs
index 9c73433b..42010ae2 100644
--- a/examples/binds.rs
+++ b/examples/binds.rs
@@ -13,10 +13,12 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::UART0);
hprintln!("init").unwrap();
+
+ init::LateResources {}
}
#[idle]
diff --git a/examples/capacity.rs b/examples/capacity.rs
index 7ccb086a..ba8b15b0 100644
--- a/examples/capacity.rs
+++ b/examples/capacity.rs
@@ -12,8 +12,10 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::UART0);
+
+ init::LateResources {}
}
#[task(binds = UART0, spawn = [foo, bar])]
diff --git a/examples/cfg.rs b/examples/cfg.rs
index f4848302..d49f54c7 100644
--- a/examples/cfg.rs
+++ b/examples/cfg.rs
@@ -20,9 +20,11 @@ mod app {
}
#[init(spawn = [foo])]
- fn init(cx: init::Context) {
+ fn init(cx: init::Context) -> init::LateResources {
cx.spawn.foo().unwrap();
cx.spawn.foo().unwrap();
+
+ init::LateResources {}
}
#[idle]
diff --git a/examples/destructure.rs b/examples/destructure.rs
index 45d73195..e7c53237 100644
--- a/examples/destructure.rs
+++ b/examples/destructure.rs
@@ -23,9 +23,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
+
+ init::LateResources {}
}
// Direct destructure
diff --git a/examples/generics.rs b/examples/generics.rs
index c65e6518..3107dd11 100644
--- a/examples/generics.rs
+++ b/examples/generics.rs
@@ -19,9 +19,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
+
+ init::LateResources {}
}
#[task(binds = UART0, resources = [shared])]
diff --git a/examples/hardware.rs b/examples/hardware.rs
index 831b029c..f6a2d375 100644
--- a/examples/hardware.rs
+++ b/examples/hardware.rs
@@ -12,12 +12,14 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
// Pends the UART0 interrupt but its handler won't run until *after*
// `init` returns because interrupts are disabled
rtic::pend(Interrupt::UART0); // equivalent to NVIC::pend
hprintln!("init").unwrap();
+
+ init::LateResources {}
}
#[idle]
diff --git a/examples/idle.rs b/examples/idle.rs
index 0db05459..58c3c87d 100644
--- a/examples/idle.rs
+++ b/examples/idle.rs
@@ -11,8 +11,10 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
hprintln!("init").unwrap();
+
+ init::LateResources {}
}
#[idle]
diff --git a/examples/init.rs b/examples/init.rs
index ea543338..6ac284a1 100644
--- a/examples/init.rs
+++ b/examples/init.rs
@@ -11,7 +11,7 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965, peripherals = true)]
mod app {
#[init]
- fn init(cx: init::Context) {
+ fn init(cx: init::Context) -> init::LateResources {
static mut X: u32 = 0;
// Cortex-M peripherals
@@ -30,5 +30,7 @@ mod app {
hprintln!("init").unwrap();
debug::exit(debug::EXIT_SUCCESS);
+
+ init::LateResources {}
}
}
diff --git a/examples/lock.rs b/examples/lock.rs
index 6ce61dc6..669b1aed 100644
--- a/examples/lock.rs
+++ b/examples/lock.rs
@@ -18,8 +18,10 @@ mod app {
}
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::GPIOA);
+
+ init::LateResources {}
}
// when omitted priority is assumed to be `1`
diff --git a/examples/message.rs b/examples/message.rs
index 3f14a5a4..f9736728 100644
--- a/examples/message.rs
+++ b/examples/message.rs
@@ -11,8 +11,10 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init(spawn = [foo])]
- fn init(c: init::Context) {
+ fn init(c: init::Context) -> init::LateResources {
c.spawn.foo(/* no message */).unwrap();
+
+ init::LateResources {}
}
#[task(spawn = [bar])]
diff --git a/examples/not-send.rs b/examples/not-send.rs
index 45f7e4e7..18071fc5 100644
--- a/examples/not-send.rs
+++ b/examples/not-send.rs
@@ -26,9 +26,11 @@ mod app {
}
#[init(spawn = [baz, quux])]
- fn init(c: init::Context) {
+ fn init(c: init::Context) -> init::LateResources {
c.spawn.baz().unwrap();
c.spawn.quux().unwrap();
+
+ init::LateResources {}
}
#[task(spawn = [bar])]
diff --git a/examples/not-sync.rs b/examples/not-sync.rs
index 75816424..75412e63 100644
--- a/examples/not-sync.rs
+++ b/examples/not-sync.rs
@@ -26,8 +26,10 @@ mod app {
}
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
debug::exit(debug::EXIT_SUCCESS);
+
+ init::LateResources {}
}
#[task(resources = [&shared])]
diff --git a/examples/periodic.rs b/examples/periodic.rs
index 2d4c73b5..d3aedd32 100644
--- a/examples/periodic.rs
+++ b/examples/periodic.rs
@@ -16,10 +16,12 @@ const PERIOD: u32 = 8_000_000;
mod app {
#[init(schedule = [foo])]
- fn init(cx: init::Context) {
+ fn init(cx: init::Context) -> init::LateResources {
// omitted: initialization of `CYCCNT`
cx.schedule.foo(cx.start + PERIOD.cycles()).unwrap();
+
+ init::LateResources {}
}
#[task(schedule = [foo])]
diff --git a/examples/peripherals-taken.rs b/examples/peripherals-taken.rs
index 10bc2603..09f92427 100644
--- a/examples/peripherals-taken.rs
+++ b/examples/peripherals-taken.rs
@@ -9,8 +9,10 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn taskmain(_: taskmain::Context) {
+ fn init(_: init::Context) -> init::LateResources {
assert!(cortex_m::Peripherals::take().is_none());
debug::exit(debug::EXIT_SUCCESS);
+
+ init::LateResources {}
}
}
diff --git a/examples/pool.rs b/examples/pool.rs
index 27408d55..cdbabca7 100644
--- a/examples/pool.rs
+++ b/examples/pool.rs
@@ -25,13 +25,15 @@ mod app {
use super::P;
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
static mut MEMORY: [u8; 512] = [0; 512];
// Increase the capacity of the memory pool by ~4
P::grow(MEMORY);
rtic::pend(Interrupt::I2C0);
+
+ init::LateResources {}
}
#[task(binds = I2C0, priority = 2, spawn = [foo, bar])]
diff --git a/examples/preempt.rs b/examples/preempt.rs
index 02193011..f6fc4b05 100644
--- a/examples/preempt.rs
+++ b/examples/preempt.rs
@@ -11,8 +11,10 @@ use rtic::app;
#[app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::GPIOA);
+
+ init::LateResources {}
}
#[task(binds = GPIOA, priority = 1)]
diff --git a/examples/ramfunc.rs b/examples/ramfunc.rs
index 789d7871..5ff167a3 100644
--- a/examples/ramfunc.rs
+++ b/examples/ramfunc.rs
@@ -11,8 +11,10 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init(spawn = [bar])]
- fn init(c: init::Context) {
+ fn init(c: init::Context) -> init::LateResources {
c.spawn.bar().unwrap();
+
+ init::LateResources {}
}
#[inline(never)]
diff --git a/examples/resource-user-struct.rs b/examples/resource-user-struct.rs
index dbda9a3f..a5bd0ddf 100644
--- a/examples/resource-user-struct.rs
+++ b/examples/resource-user-struct.rs
@@ -26,9 +26,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
+
+ init::LateResources {}
}
// `shared` cannot be accessed from this context
diff --git a/examples/resource.rs b/examples/resource.rs
index 4cd0f4ca..273af26a 100644
--- a/examples/resource.rs
+++ b/examples/resource.rs
@@ -19,9 +19,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
+
+ init::LateResources {}
}
// `shared` cannot be accessed from this context
diff --git a/examples/schedule.rs b/examples/schedule.rs
index d5547b67..7e6adc1a 100644
--- a/examples/schedule.rs
+++ b/examples/schedule.rs
@@ -14,7 +14,7 @@ use rtic::cyccnt::{Instant, U32Ext as _};
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
mod app {
#[init(schedule = [foo, bar])]
- fn init(mut cx: init::Context) {
+ fn init(mut cx: init::Context) -> init::LateResources {
// Initialize (enable) the monotonic timer (CYCCNT)
cx.core.DCB.enable_trace();
// required on Cortex-M7 devices that software lock the DWT (e.g. STM32F7)
@@ -32,6 +32,8 @@ mod app {
// Schedule `bar` to run 4e6 cycles in the future
cx.schedule.bar(now + 4_000_000.cycles()).unwrap();
+
+ init::LateResources {}
}
#[task]
diff --git a/examples/shared-with-init.rs b/examples/shared-with-init.rs
index 9f7e26aa..85c72761 100644
--- a/examples/shared-with-init.rs
+++ b/examples/shared-with-init.rs
@@ -23,12 +23,14 @@ mod app {
}
#[init(resources = [shared])]
- fn init(c: init::Context) {
+ fn init(c: init::Context) -> init::LateResources {
// this `message` will be sent to task `UART0`
let message = MustBeSend;
*c.resources.shared = Some(message);
rtic::pend(Interrupt::UART0);
+
+ init::LateResources {}
}
#[task(binds = UART0, resources = [shared])]
diff --git a/examples/t-binds.rs b/examples/t-binds.rs
index 7d7bd7d2..3ca4c66e 100644
--- a/examples/t-binds.rs
+++ b/examples/t-binds.rs
@@ -10,7 +10,9 @@ use panic_halt as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) {}
+ fn init(_: init::Context) -> init::LateResources {
+ init::LateResources {}
+ }
// Cortex-M exception
#[task(binds = SVCall)]
diff --git a/examples/t-cfg.rs b/examples/t-cfg.rs
index 3deb107c..3da20d4e 100644
--- a/examples/t-cfg.rs
+++ b/examples/t-cfg.rs
@@ -15,9 +15,11 @@ mod app {
}
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
#[cfg(never)]
static mut BAR: u32 = 0;
+
+ init::LateResources {}
}
#[idle]
diff --git a/examples/t-htask-main.rs b/examples/t-htask-main.rs
index 998252e1..1e38e317 100644
--- a/examples/t-htask-main.rs
+++ b/examples/t-htask-main.rs
@@ -9,8 +9,10 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) {
- rtic::pend(lm3s6965::Interrupt::UART0)
+ fn init(_: init::Context) -> init::LateResources {
+ rtic::pend(lm3s6965::Interrupt::UART0);
+
+ init::LateResources {}
}
#[task(binds = UART0)]
diff --git a/examples/t-idle-main.rs b/examples/t-idle-main.rs
index 03a52cb2..9078628e 100644
--- a/examples/t-idle-main.rs
+++ b/examples/t-idle-main.rs
@@ -9,7 +9,9 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) {}
+ fn init(_: init::Context) -> init::LateResources {
+ init::LateResources {}
+ }
#[idle]
fn taskmain(_: taskmain::Context) -> ! {
diff --git a/examples/t-init-main.rs b/examples/t-init-main.rs
index d0814877..7c23cc83 100644
--- a/examples/t-init-main.rs
+++ b/examples/t-init-main.rs
@@ -9,7 +9,9 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn taskmain(_: taskmain::Context) {
+ fn init(_: init::Context) -> init::LateResources {
debug::exit(debug::EXIT_SUCCESS);
+
+ init::LateResources {}
}
}
diff --git a/examples/t-resource.rs b/examples/t-resource.rs
index 94b527fa..91950d3e 100644
--- a/examples/t-resource.rs
+++ b/examples/t-resource.rs
@@ -32,7 +32,7 @@ mod app {
}
#[init(resources = [o1, o4, o5, o6, s3])]
- fn init(c: init::Context) {
+ fn init(c: init::Context) -> init::LateResources {
// owned by `init` == `&'static mut`
let _: &'static mut u32 = c.resources.o1;
@@ -43,6 +43,8 @@ mod app {
let _: &mut u32 = c.resources.o4;
let _: &mut u32 = c.resources.o5;
let _: &mut u32 = c.resources.s3;
+
+ init::LateResources {}
}
#[idle(resources = [o2, &o4, s1, &s3])]
diff --git a/examples/t-schedule.rs b/examples/t-schedule.rs
index ef2eb080..d5a6d3ff 100644
--- a/examples/t-schedule.rs
+++ b/examples/t-schedule.rs
@@ -11,10 +11,12 @@ use rtic::cyccnt::{Instant, U32Ext as _};
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
mod app {
#[init(schedule = [foo, bar, baz])]
- fn init(c: init::Context) {
+ fn init(c: init::Context) -> init::LateResources {
let _: Result<(), ()> = c.schedule.foo(c.start + 10.cycles());
let _: Result<(), u32> = c.schedule.bar(c.start + 20.cycles(), 0);
let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 30.cycles(), 0, 1);
+
+ init::LateResources {}
}
#[idle(schedule = [foo, bar, baz])]
diff --git a/examples/t-spawn.rs b/examples/t-spawn.rs
index 72143c5b..efb748bc 100644
--- a/examples/t-spawn.rs
+++ b/examples/t-spawn.rs
@@ -10,10 +10,12 @@ use panic_halt as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init(spawn = [foo, bar, baz])]
- fn init(c: init::Context) {
+ fn init(c: init::Context) -> init::LateResources {
let _: Result<(), ()> = c.spawn.foo();
let _: Result<(), u32> = c.spawn.bar(0);
let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
+
+ init::LateResources {}
}
#[idle(spawn = [foo, bar, baz])]
diff --git a/examples/t-stask-main.rs b/examples/t-stask-main.rs
index 3e650f60..74335c18 100644
--- a/examples/t-stask-main.rs
+++ b/examples/t-stask-main.rs
@@ -9,8 +9,10 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init(spawn = [taskmain])]
- fn init(cx: init::Context) {
+ fn init(cx: init::Context) -> init::LateResources {
cx.spawn.taskmain().ok();
+
+ init::LateResources {}
}
#[task]
diff --git a/examples/task.rs b/examples/task.rs
index f510df74..80a9c431 100644
--- a/examples/task.rs
+++ b/examples/task.rs
@@ -11,8 +11,10 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init(spawn = [foo])]
- fn init(c: init::Context) {
+ fn init(c: init::Context) -> init::LateResources {
c.spawn.foo().unwrap();
+
+ init::LateResources {}
}
#[task(spawn = [bar, baz])]
diff --git a/examples/types.rs b/examples/types.rs
index cd7e8a2f..251d004c 100644
--- a/examples/types.rs
+++ b/examples/types.rs
@@ -18,7 +18,7 @@ mod app {
}
#[init(schedule = [foo], spawn = [foo])]
- fn init(cx: init::Context) {
+ fn init(cx: init::Context) -> init::LateResources {
let _: cyccnt::Instant = cx.start;
let _: rtic::Peripherals = cx.core;
let _: lm3s6965::Peripherals = cx.device;
@@ -26,6 +26,8 @@ mod app {
let _: init::Spawn = cx.spawn;
debug::exit(debug::EXIT_SUCCESS);
+
+ init::LateResources {}
}
#[idle(schedule = [foo], spawn = [foo])]
diff --git a/macros/src/codegen/init.rs b/macros/src/codegen/init.rs
index 5f95f217..465a927d 100644
--- a/macros/src/codegen/init.rs
+++ b/macros/src/codegen/init.rs
@@ -36,47 +36,38 @@ pub fn codegen(
let mut root_init = vec![];
- let mut user_init_imports = vec![];
-
- let ret = {
- let late_fields = analysis
- .late_resources
- .iter()
- .flat_map(|resources| {
- resources.iter().map(|name| {
- let ty = &app.late_resources[name].ty;
- let cfgs = &app.late_resources[name].cfgs;
-
- quote!(
+ let late_fields = analysis
+ .late_resources
+ .iter()
+ .flat_map(|resources| {
+ resources.iter().map(|name| {
+ let ty = &app.late_resources[name].ty;
+ let cfgs = &app.late_resources[name].cfgs;
+
+ quote!(
#(#cfgs)*
pub #name: #ty
- )
- })
+ )
})
- .collect::<Vec<_>>();
+ })
+ .collect::<Vec<_>>();
- if !late_fields.is_empty() {
- let late_resources = util::late_resources_ident(&name);
+ let mut user_init_imports = vec![];
+ let late_resources = util::late_resources_ident(&name);
- root_init.push(quote!(
- /// Resources initialized at runtime
- #[allow(non_snake_case)]
- pub struct #late_resources {
- #(#late_fields),*
- }
- ));
-
- let name_late = format_ident!("{}LateResources", name);
- user_init_imports.push(quote!(
- #[allow(non_snake_case)]
- use super::#name_late;
- ));
-
- Some(quote!(-> #name::LateResources))
- } else {
- None
+ root_init.push(quote!(
+ /// Resources initialized at runtime
+ #[allow(non_snake_case)]
+ pub struct #late_resources {
+ #(#late_fields),*
}
- };
+ ));
+
+ let name_late = format_ident!("{}LateResources", name);
+ user_init_imports.push(quote!(
+ #[allow(non_snake_case)]
+ use super::#name_late;
+ ));
let mut locals_pat = None;
let mut locals_new = None;
@@ -95,7 +86,7 @@ pub fn codegen(
let user_init = Some(quote!(
#(#attrs)*
#[allow(non_snake_case)]
- fn #name(#(#locals_pat,)* #context: #name::Context) #ret {
+ fn #name(#(#locals_pat,)* #context: #name::Context) -> #name::LateResources {
#(#stmts)*
}
));
diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs
index 1fd3cd42..526bf491 100644
--- a/macros/src/codegen/module.rs
+++ b/macros/src/codegen/module.rs
@@ -267,14 +267,12 @@ pub fn codegen(
if let Context::Init = ctxt {
let init = &app.inits.first().unwrap();
- if init.returns_late_resources {
- let late_resources = util::late_resources_ident(&init.name);
+ let late_resources = util::late_resources_ident(&init.name);
- items.push(quote!(
- #[doc(inline)]
- pub use super::#late_resources as LateResources;
- ));
- }
+ items.push(quote!(
+ #[doc(inline)]
+ pub use super::#late_resources as LateResources;
+ ));
}
let doc = match ctxt {
diff --git a/macros/src/lib.rs b/macros/src/lib.rs
index 94e7eec6..e659559e 100644
--- a/macros/src/lib.rs
+++ b/macros/src/lib.rs
@@ -35,8 +35,7 @@ mod tests;
///
/// The items allowed in the module block are specified below:
///
-/// # 1. `#[resources]
-/// struct <resource-name>`
+/// # 1. `#[resources] struct <resource-name>`
///
/// This structure contains the declaration of all the resources used by the application. Each field
/// in this structure corresponds to a different resource. Each resource may optionally be given an
diff --git a/ui/single/locals-cfg.rs b/ui/single/locals-cfg.rs
index e04e5b93..45a7a911 100644
--- a/ui/single/locals-cfg.rs
+++ b/ui/single/locals-cfg.rs
@@ -4,11 +4,13 @@ use panic_halt as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) {
+ fn init(_: init::Context) -> init::LateResources {
#[cfg(never)]
static mut FOO: u32 = 0;
FOO;
+
+ init::LateResources {}
}
#[idle]
diff --git a/ui/single/locals-cfg.stderr b/ui/single/locals-cfg.stderr
index 39d56df2..e58bd935 100644
--- a/ui/single/locals-cfg.stderr
+++ b/ui/single/locals-cfg.stderr
@@ -5,27 +5,27 @@ error[E0425]: cannot find value `FOO` in this scope
| ^^^ not found in this scope
error[E0425]: cannot find value `FOO` in this scope
- --> $DIR/locals-cfg.rs:19:9
+ --> $DIR/locals-cfg.rs:21:9
|
-19 | FOO;
+21 | FOO;
| ^^^ not found in this scope
error[E0425]: cannot find value `FOO` in this scope
- --> $DIR/locals-cfg.rs:29:9
+ --> $DIR/locals-cfg.rs:31:9
|
-29 | FOO;
+31 | FOO;
| ^^^ not found in this scope
error[E0425]: cannot find value `FOO` in this scope
- --> $DIR/locals-cfg.rs:37:9
+ --> $DIR/locals-cfg.rs:39:9
|
-37 | FOO;
+39 | FOO;
| ^^^ not found in this scope
error[E0425]: cannot find value `FOO` in this scope
- --> $DIR/locals-cfg.rs:45:9
+ --> $DIR/locals-cfg.rs:47:9
|
-45 | FOO;
+47 | FOO;
| ^^^ not found in this scope
error: duplicate lang item in crate `panic_halt` (which `$CRATE` depends on): `panic_impl`.
diff --git a/ui/single/resources-cfg.rs b/ui/single/resources-cfg.rs
index f2569e92..2ba65a04 100644
--- a/ui/single/resources-cfg.rs
+++ b/ui/single/resources-cfg.rs
@@ -43,12 +43,14 @@ mod app {
}
#[init(resources = [o1, o4, o5, o6, s3])]
- fn init(c: init::Context) {
+ fn init(c: init::Context) -> init::LateResources {
c.resources.o1;
c.resources.o4;
c.resources.o5;
c.resources.o6;
c.resources.s3;
+
+ init::LateResources {}
}
#[idle(resources = [o2, &o4, s1, &s3])]
diff --git a/ui/single/resources-cfg.stderr b/ui/single/resources-cfg.stderr
index 9c39e567..17f08d81 100644
--- a/ui/single/resources-cfg.stderr
+++ b/ui/single/resources-cfg.stderr
@@ -45,81 +45,81 @@ error[E0609]: no field `s3` on type `initResources<'_>`
= note: available fields are: `__marker__`
error[E0609]: no field `o2` on type `idleResources<'_>`
- --> $DIR/resources-cfg.rs:56:21
+ --> $DIR/resources-cfg.rs:58:21
|
-56 | c.resources.o2;
+58 | c.resources.o2;
| ^^ unknown field
|
= note: available fields are: `__marker__`
error[E0609]: no field `o4` on type `idleResources<'_>`
- --> $DIR/resources-cfg.rs:57:21
+ --> $DIR/resources-cfg.rs:59:21
|
-57 | c.resources.o4;
+59 | c.resources.o4;
| ^^ unknown field
|
= note: available fields are: `__marker__`
error[E0609]: no field `s1` on type `idleResources<'_>`
- --> $DIR/resources-cfg.rs:58:21
+ --> $DIR/resources-cfg.rs:60:21
|
-58 | c.resources.s1;
+60 | c.resources.s1;
| ^^ unknown field
|
= note: available fields are: `__marker__`
error[E0609]: no field `s3` on type `idleResources<'_>`
- --> $DIR/resources-cfg.rs:59:21
+ --> $DIR/resources-cfg.rs:61:21
|
-59 | c.resources.s3;
+61 | c.resources.s3;
| ^^ unknown field
|
= note: available fields are: `__marker__`
error[E0609]: no field `o3` on type `uart0Resources<'_>`
- --> $DIR/resources-cfg.rs:66:21
+ --> $DIR/resources-cfg.rs:68:21
|
-66 | c.resources.o3;
+68 | c.resources.o3;
| ^^ unknown field
|
= note: available fields are: `__marker__`
error[E0609]: no field `s1` on type `uart0Resources<'_>`
- --> $DIR/resources-cfg.rs:67:21
+ --> $DIR/resources-cfg.rs:69:21
|
-67 | c.resources.s1;
+69 | c.resources.s1;
| ^^ unknown field
|
= note: available fields are: `__marker__`
error[E0609]: no field `s2` on type `uart0Resources<'_>`
- --> $DIR/resources-cfg.rs:68:21
+ --> $DIR/resources-cfg.rs:70:21
|
-68 | c.resources.s2;
+70 | c.resources.s2;
| ^^ unknown field
|
= note: available fields are: `__marker__`
error[E0609]: no field `s3` on type `uart0Resources<'_>`
- --> $DIR/resources-cfg.rs:69:21
+ --> $DIR/resources-cfg.rs:71:21
|
-69 | c.resources.s3;
+71 | c.resources.s3;
| ^^ unknown field
|
= note: available fields are: `__marker__`
error[E0609]: no field `s2` on type `uart1Resources<'_>`
- --> $DIR/resources-cfg.rs:74:21
+ --> $DIR/resources-cfg.rs:76:21
|
-74 | c.resources.s2;
+76 | c.resources.s2;
| ^^ unknown field
|
= note: available fields are: `__marker__`
error[E0609]: no field `o5` on type `uart1Resources<'_>`
- --> $DIR/resources-cfg.rs:75:21
+ --> $DIR/resources-cfg.rs:77:21
|
-75 | c.resources.o5;
+77 | c.resources.o5;
| ^^ unknown field
|
= note: available fields are: `__marker__`
diff --git a/ui/single/task-priority-too-high.rs b/ui/single/task-priority-too-high.rs
index fbafa4d2..caa7b8ee 100644
--- a/ui/single/task-priority-too-high.rs
+++ b/ui/single/task-priority-too-high.rs
@@ -3,7 +3,9 @@
#[rtic::app(device = lm3s6965)]
mod app {
#[init]
- fn init(_: init::Context) {}
+ fn init(_: init::Context) -> init::LateResources {
+ init::LateResources {}
+ }
#[task(binds = GPIOA, priority = 1)]
fn gpioa(_: gpioa::Context) {}