mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-27 14:04:56 +01:00
Merge branch 'master' into spawn_experiment
This commit is contained in:
commit
c83b15b643
51 changed files with 649 additions and 467 deletions
125
.github/workflows/build.yml
vendored
125
.github/workflows/build.yml
vendored
|
@ -85,7 +85,7 @@ jobs:
|
||||||
command: check
|
command: check
|
||||||
args: --target=${{ matrix.target }}
|
args: --target=${{ matrix.target }}
|
||||||
|
|
||||||
# Verify all examples
|
# Verify all examples, checks
|
||||||
checkexamples:
|
checkexamples:
|
||||||
name: checkexamples
|
name: checkexamples
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
@ -140,6 +140,51 @@ jobs:
|
||||||
command: check
|
command: check
|
||||||
args: --examples --target=${{ matrix.target }} --features __min_r1_43,${{ env.V7 }}
|
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
|
# Use precompiled binutils
|
||||||
- name: cargo install cargo-binutils
|
- name: cargo install cargo-binutils
|
||||||
uses: actions-rs/install@v0.1
|
uses: actions-rs/install@v0.1
|
||||||
|
@ -341,6 +386,56 @@ jobs:
|
||||||
command: check
|
command: check
|
||||||
args: --manifest-path macros/Cargo.toml --target=${{ matrix.target }}
|
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
|
# Run test suite for thumbv7m
|
||||||
testv7:
|
testv7:
|
||||||
name: testv7
|
name: testv7
|
||||||
|
@ -513,7 +608,7 @@ jobs:
|
||||||
- name: mdBook Action
|
- name: mdBook Action
|
||||||
uses: peaceiris/actions-mdbook@v1.1.11
|
uses: peaceiris/actions-mdbook@v1.1.11
|
||||||
with:
|
with:
|
||||||
mdbook-version: '0.3.1'
|
mdbook-version: 'latest'
|
||||||
|
|
||||||
- name: Build book in English
|
- name: Build book in English
|
||||||
run: cd book/en && mdbook build
|
run: cd book/en && mdbook build
|
||||||
|
@ -541,7 +636,9 @@ jobs:
|
||||||
- style
|
- style
|
||||||
- check
|
- check
|
||||||
- checkexamples
|
- checkexamples
|
||||||
|
- testexamples
|
||||||
- checkmacros
|
- checkmacros
|
||||||
|
- testmacros
|
||||||
- testv7
|
- testv7
|
||||||
- testv6
|
- testv6
|
||||||
- docs
|
- docs
|
||||||
|
@ -566,8 +663,7 @@ jobs:
|
||||||
- name: mdBook Action
|
- name: mdBook Action
|
||||||
uses: peaceiris/actions-mdbook@v1.1.11
|
uses: peaceiris/actions-mdbook@v1.1.11
|
||||||
with:
|
with:
|
||||||
mdbook-version: '0.3.1'
|
mdbook-version: 'latest'
|
||||||
# mdbook-version: 'latest'
|
|
||||||
|
|
||||||
- name: Remove cargo-config
|
- name: Remove cargo-config
|
||||||
run: rm -f .cargo/config
|
run: rm -f .cargo/config
|
||||||
|
@ -579,13 +675,16 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
langs=( en ru )
|
langs=( en ru )
|
||||||
devver=( dev )
|
devver=( dev )
|
||||||
# Query git for tagged releases, all releases start with "v"
|
# The latest stable must be the first element in the array
|
||||||
# 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)
|
|
||||||
vers=( 0.5.x 0.4.x )
|
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
|
# Create directories
|
||||||
td=$(mktemp -d)
|
td=$(mktemp -d)
|
||||||
mkdir -p $td/$devver/book/
|
mkdir -p $td/$devver/book/
|
||||||
|
@ -630,8 +729,8 @@ jobs:
|
||||||
rm -rf $src
|
rm -rf $src
|
||||||
done
|
done
|
||||||
|
|
||||||
# Create alias for the stable release
|
# Copy the stable book to the stable alias
|
||||||
ln -s $stable $td/stable
|
cp -r $td/$stable $td/stable
|
||||||
|
|
||||||
# Forward CNAME file
|
# Forward CNAME file
|
||||||
cp CNAME $td/
|
cp CNAME $td/
|
||||||
|
@ -654,7 +753,9 @@ jobs:
|
||||||
- style
|
- style
|
||||||
- check
|
- check
|
||||||
- checkexamples
|
- checkexamples
|
||||||
|
- testexamples
|
||||||
- checkmacros
|
- checkmacros
|
||||||
|
- testmacros
|
||||||
- testv7
|
- testv7
|
||||||
- testv6
|
- testv6
|
||||||
- docs
|
- docs
|
||||||
|
@ -670,7 +771,9 @@ jobs:
|
||||||
- style
|
- style
|
||||||
- check
|
- check
|
||||||
- checkexamples
|
- checkexamples
|
||||||
|
- testexamples
|
||||||
- checkmacros
|
- checkmacros
|
||||||
|
- testmacros
|
||||||
- testv7
|
- testv7
|
||||||
- testv6
|
- testv6
|
||||||
- docs
|
- docs
|
||||||
|
|
26
README.md
26
README.md
|
@ -4,10 +4,12 @@ A concurrency framework for building real-time systems.
|
||||||
|
|
||||||
Formerly known as Real-Time For the Masses.
|
Formerly known as Real-Time For the Masses.
|
||||||
|
|
||||||
![crates.io](https://img.shields.io/crates/v/cortex-m-rtic)
|
[![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)
|
[![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)
|
[![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)
|
[![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
|
## Features
|
||||||
|
|
||||||
|
@ -52,23 +54,29 @@ Formerly known as Real-Time For the Masses.
|
||||||
|
|
||||||
## [User documentation](https://rtic.rs)
|
## [User documentation](https://rtic.rs)
|
||||||
|
|
||||||
## [API reference](https://rtic.rs/0.5/api/)
|
## [API reference](https://rtic.rs/stable/api/)
|
||||||
|
|
||||||
## Chat
|
## Chat
|
||||||
|
|
||||||
Join us and talk about RTIC in the [Matrix room][matrix-room].
|
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
|
[matrix-room]: https://matrix.to/#/#rtic:matrix.org
|
||||||
|
[hackmd]: https://hackmd.io/@xmis9JvZT8Gvo9lOEKyZ4Q/SkBJKsjuH
|
||||||
|
|
||||||
## Contributing
|
## 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
|
[rfcs]: https://github.com/rtic-rs/rfcs
|
||||||
|
|
||||||
## Acknowledgments
|
## Acknowledgments
|
||||||
|
|
||||||
This crate is based on [the Real-Time For the Masses language][rtfm-lang] created by the Embedded
|
This crate is based on [the Real-Time For the Masses language][rtfm-lang]
|
||||||
Systems group at [Luleå University of Technology][ltu], led by [Prof. Per
|
created by the Embedded Systems group at [Luleå University of Technology][ltu],
|
||||||
Lindgren][per].
|
led by [Prof. Per Lindgren][per].
|
||||||
|
|
||||||
[rtfm-lang]: http://www.rtfm-lang.org/
|
[rtfm-lang]: http://www.rtfm-lang.org/
|
||||||
[ltu]: https://www.ltu.se/?l=en
|
[ltu]: https://www.ltu.se/?l=en
|
||||||
|
|
|
@ -10,8 +10,10 @@
|
||||||
- [Types, Send and Sync](./by-example/types-send-sync.md)
|
- [Types, Send and Sync](./by-example/types-send-sync.md)
|
||||||
- [Starting a new project](./by-example/new.md)
|
- [Starting a new project](./by-example/new.md)
|
||||||
- [Tips & tricks](./by-example/tips.md)
|
- [Tips & tricks](./by-example/tips.md)
|
||||||
- [Migrating from v0.4.x to v0.5.0](./migration.md)
|
- [Migration Guides](./migration.md)
|
||||||
- [Migrating from RTFM to RTIC](./migration_rtic.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)
|
- [Under the hood](./internals.md)
|
||||||
- [Interrupt configuration](./internals/interrupt-configuration.md)
|
- [Interrupt configuration](./internals/interrupt-configuration.md)
|
||||||
- [Non-reentrancy](./internals/non-reentrancy.md)
|
- [Non-reentrancy](./internals/non-reentrancy.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.
|
embedded development environment that includes QEMU.
|
||||||
|
|
||||||
[the embedded Rust book]: https://rust-embedded.github.io/book/intro/install.html
|
[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.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
## Resources
|
# Resources
|
||||||
|
|
||||||
The framework provides an abstraction to share data between any of the contexts
|
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.
|
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
|
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
|
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
|
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
|
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
|
access (`&mut-`) and shared access (`&-`) to the *same* resource from different
|
||||||
|
|
|
@ -116,6 +116,7 @@ Here's an example where `heapless::Pool` is used to "box" buffers of 128 bytes.
|
||||||
``` rust
|
``` rust
|
||||||
{{#include ../../../../examples/pool.rs}}
|
{{#include ../../../../examples/pool.rs}}
|
||||||
```
|
```
|
||||||
|
|
||||||
``` console
|
``` console
|
||||||
$ cargo run --example pool
|
$ cargo run --example pool
|
||||||
{{#include ../../../../ci/expected/pool.run}}
|
{{#include ../../../../ci/expected/pool.run}}
|
||||||
|
|
|
@ -1,331 +1,4 @@
|
||||||
# Migration of RTIC
|
# Migration Guides
|
||||||
|
|
||||||
## Migrating from v0.5.x to v0.6.0
|
This section describes how to migrate between different version of RTIC.
|
||||||
|
It also acts as a comparing reference between versions.
|
||||||
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) {
|
|
||||||
// ..
|
|
||||||
}
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
|
@ -8,14 +8,11 @@ change.
|
||||||
|
|
||||||
[RFC #33]: https://github.com/rtic-rs/rfcs/pull/33
|
[RFC #33]: https://github.com/rtic-rs/rfcs/pull/33
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## `Cargo.toml`
|
## `Cargo.toml`
|
||||||
|
|
||||||
First, the `cortex-m-rtfm` dependency needs to be updated to
|
First, the `cortex-m-rtfm` dependency needs to be updated to
|
||||||
`cortex-m-rtic`.
|
`cortex-m-rtic`.
|
||||||
|
|
||||||
|
|
||||||
``` toml
|
``` toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# change this
|
# change this
|
||||||
|
@ -51,4 +48,3 @@ const APP: () = {
|
||||||
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
233
book/en/src/migration/migration_v4.md
Normal file
233
book/en/src/migration/migration_v4.md
Normal file
|
@ -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) {
|
||||||
|
// ..
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
96
book/en/src/migration/migration_v5.md
Normal file
96
book/en/src/migration/migration_v5.md
Normal file
|
@ -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.
|
|
@ -13,13 +13,15 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init(spawn = [foo])]
|
#[init(spawn = [foo])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) -> init::LateResources {
|
||||||
// omitted: initialization of `CYCCNT`
|
// omitted: initialization of `CYCCNT`
|
||||||
|
|
||||||
hprintln!("init(baseline = {:?})", cx.start).unwrap();
|
hprintln!("init(baseline = {:?})", cx.start).unwrap();
|
||||||
|
|
||||||
// `foo` inherits the baseline of `init`: `Instant(0)`
|
// `foo` inherits the baseline of `init`: `Instant(0)`
|
||||||
cx.spawn.foo().unwrap();
|
cx.spawn.foo().unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(schedule = [foo])]
|
#[task(schedule = [foo])]
|
||||||
|
|
|
@ -13,10 +13,12 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
rtic::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
|
|
||||||
hprintln!("init").unwrap();
|
hprintln!("init").unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle]
|
#[idle]
|
||||||
|
|
|
@ -12,8 +12,10 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
rtic::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = UART0, spawn = [foo, bar])]
|
#[task(binds = UART0, spawn = [foo, bar])]
|
||||||
|
|
|
@ -20,9 +20,11 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init(spawn = [foo])]
|
#[init(spawn = [foo])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) -> init::LateResources {
|
||||||
cx.spawn.foo().unwrap();
|
cx.spawn.foo().unwrap();
|
||||||
cx.spawn.foo().unwrap();
|
cx.spawn.foo().unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle]
|
#[idle]
|
||||||
|
|
|
@ -23,9 +23,11 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
rtic::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
rtic::pend(Interrupt::UART1);
|
rtic::pend(Interrupt::UART1);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direct destructure
|
// Direct destructure
|
||||||
|
|
|
@ -19,9 +19,11 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
rtic::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
rtic::pend(Interrupt::UART1);
|
rtic::pend(Interrupt::UART1);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = UART0, resources = [shared])]
|
#[task(binds = UART0, resources = [shared])]
|
||||||
|
|
|
@ -12,12 +12,14 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
// Pends the UART0 interrupt but its handler won't run until *after*
|
// Pends the UART0 interrupt but its handler won't run until *after*
|
||||||
// `init` returns because interrupts are disabled
|
// `init` returns because interrupts are disabled
|
||||||
rtic::pend(Interrupt::UART0); // equivalent to NVIC::pend
|
rtic::pend(Interrupt::UART0); // equivalent to NVIC::pend
|
||||||
|
|
||||||
hprintln!("init").unwrap();
|
hprintln!("init").unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle]
|
#[idle]
|
||||||
|
|
|
@ -11,8 +11,10 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
hprintln!("init").unwrap();
|
hprintln!("init").unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle]
|
#[idle]
|
||||||
|
|
|
@ -11,7 +11,7 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965, peripherals = true)]
|
#[rtic::app(device = lm3s6965, peripherals = true)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) -> init::LateResources {
|
||||||
static mut X: u32 = 0;
|
static mut X: u32 = 0;
|
||||||
|
|
||||||
// Cortex-M peripherals
|
// Cortex-M peripherals
|
||||||
|
@ -30,5 +30,7 @@ mod app {
|
||||||
hprintln!("init").unwrap();
|
hprintln!("init").unwrap();
|
||||||
|
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,10 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
rtic::pend(Interrupt::GPIOA);
|
rtic::pend(Interrupt::GPIOA);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// when omitted priority is assumed to be `1`
|
// when omitted priority is assumed to be `1`
|
||||||
|
|
|
@ -11,8 +11,10 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init(spawn = [foo])]
|
#[init(spawn = [foo])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) -> init::LateResources {
|
||||||
c.spawn.foo(/* no message */).unwrap();
|
c.spawn.foo(/* no message */).unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(spawn = [bar])]
|
#[task(spawn = [bar])]
|
||||||
|
|
|
@ -26,9 +26,11 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init(spawn = [baz, quux])]
|
#[init(spawn = [baz, quux])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) -> init::LateResources {
|
||||||
c.spawn.baz().unwrap();
|
c.spawn.baz().unwrap();
|
||||||
c.spawn.quux().unwrap();
|
c.spawn.quux().unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(spawn = [bar])]
|
#[task(spawn = [bar])]
|
||||||
|
|
|
@ -26,8 +26,10 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(resources = [&shared])]
|
#[task(resources = [&shared])]
|
||||||
|
|
|
@ -16,10 +16,12 @@ const PERIOD: u32 = 8_000_000;
|
||||||
mod app {
|
mod app {
|
||||||
|
|
||||||
#[init(schedule = [foo])]
|
#[init(schedule = [foo])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) -> init::LateResources {
|
||||||
// omitted: initialization of `CYCCNT`
|
// omitted: initialization of `CYCCNT`
|
||||||
|
|
||||||
cx.schedule.foo(cx.start + PERIOD.cycles()).unwrap();
|
cx.schedule.foo(cx.start + PERIOD.cycles()).unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(schedule = [foo])]
|
#[task(schedule = [foo])]
|
||||||
|
|
|
@ -9,8 +9,10 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn taskmain(_: taskmain::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
assert!(cortex_m::Peripherals::take().is_none());
|
assert!(cortex_m::Peripherals::take().is_none());
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,15 @@ mod app {
|
||||||
use super::P;
|
use super::P;
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
static mut MEMORY: [u8; 512] = [0; 512];
|
static mut MEMORY: [u8; 512] = [0; 512];
|
||||||
|
|
||||||
// Increase the capacity of the memory pool by ~4
|
// Increase the capacity of the memory pool by ~4
|
||||||
P::grow(MEMORY);
|
P::grow(MEMORY);
|
||||||
|
|
||||||
rtic::pend(Interrupt::I2C0);
|
rtic::pend(Interrupt::I2C0);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = I2C0, priority = 2, spawn = [foo, bar])]
|
#[task(binds = I2C0, priority = 2, spawn = [foo, bar])]
|
||||||
|
|
|
@ -11,8 +11,10 @@ use rtic::app;
|
||||||
#[app(device = lm3s6965)]
|
#[app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
rtic::pend(Interrupt::GPIOA);
|
rtic::pend(Interrupt::GPIOA);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = GPIOA, priority = 1)]
|
#[task(binds = GPIOA, priority = 1)]
|
||||||
|
|
|
@ -11,8 +11,10 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init(spawn = [bar])]
|
#[init(spawn = [bar])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) -> init::LateResources {
|
||||||
c.spawn.bar().unwrap();
|
c.spawn.bar().unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
|
|
|
@ -26,9 +26,11 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
rtic::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
rtic::pend(Interrupt::UART1);
|
rtic::pend(Interrupt::UART1);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `shared` cannot be accessed from this context
|
// `shared` cannot be accessed from this context
|
||||||
|
|
|
@ -19,9 +19,11 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
rtic::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
rtic::pend(Interrupt::UART1);
|
rtic::pend(Interrupt::UART1);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `shared` cannot be accessed from this context
|
// `shared` cannot be accessed from this context
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rtic::cyccnt::{Instant, U32Ext as _};
|
||||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init(schedule = [foo, bar])]
|
#[init(schedule = [foo, bar])]
|
||||||
fn init(mut cx: init::Context) {
|
fn init(mut cx: init::Context) -> init::LateResources {
|
||||||
// Initialize (enable) the monotonic timer (CYCCNT)
|
// Initialize (enable) the monotonic timer (CYCCNT)
|
||||||
cx.core.DCB.enable_trace();
|
cx.core.DCB.enable_trace();
|
||||||
// required on Cortex-M7 devices that software lock the DWT (e.g. STM32F7)
|
// 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
|
// Schedule `bar` to run 4e6 cycles in the future
|
||||||
cx.schedule.bar(now + 4_000_000.cycles()).unwrap();
|
cx.schedule.bar(now + 4_000_000.cycles()).unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task]
|
#[task]
|
||||||
|
|
|
@ -23,12 +23,14 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init(resources = [shared])]
|
#[init(resources = [shared])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) -> init::LateResources {
|
||||||
// this `message` will be sent to task `UART0`
|
// this `message` will be sent to task `UART0`
|
||||||
let message = MustBeSend;
|
let message = MustBeSend;
|
||||||
*c.resources.shared = Some(message);
|
*c.resources.shared = Some(message);
|
||||||
|
|
||||||
rtic::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = UART0, resources = [shared])]
|
#[task(binds = UART0, resources = [shared])]
|
||||||
|
|
|
@ -10,7 +10,9 @@ use panic_halt as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {}
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
|
init::LateResources {}
|
||||||
|
}
|
||||||
|
|
||||||
// Cortex-M exception
|
// Cortex-M exception
|
||||||
#[task(binds = SVCall)]
|
#[task(binds = SVCall)]
|
||||||
|
|
|
@ -15,9 +15,11 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
#[cfg(never)]
|
#[cfg(never)]
|
||||||
static mut BAR: u32 = 0;
|
static mut BAR: u32 = 0;
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle]
|
#[idle]
|
||||||
|
|
|
@ -9,8 +9,10 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
rtic::pend(lm3s6965::Interrupt::UART0)
|
rtic::pend(lm3s6965::Interrupt::UART0);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = UART0)]
|
#[task(binds = UART0)]
|
||||||
|
|
|
@ -9,7 +9,9 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {}
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
|
init::LateResources {}
|
||||||
|
}
|
||||||
|
|
||||||
#[idle]
|
#[idle]
|
||||||
fn taskmain(_: taskmain::Context) -> ! {
|
fn taskmain(_: taskmain::Context) -> ! {
|
||||||
|
|
|
@ -9,7 +9,9 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn taskmain(_: taskmain::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init(resources = [o1, o4, o5, o6, s3])]
|
#[init(resources = [o1, o4, o5, o6, s3])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) -> init::LateResources {
|
||||||
// owned by `init` == `&'static mut`
|
// owned by `init` == `&'static mut`
|
||||||
let _: &'static mut u32 = c.resources.o1;
|
let _: &'static mut u32 = c.resources.o1;
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ mod app {
|
||||||
let _: &mut u32 = c.resources.o4;
|
let _: &mut u32 = c.resources.o4;
|
||||||
let _: &mut u32 = c.resources.o5;
|
let _: &mut u32 = c.resources.o5;
|
||||||
let _: &mut u32 = c.resources.s3;
|
let _: &mut u32 = c.resources.s3;
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle(resources = [o2, &o4, s1, &s3])]
|
#[idle(resources = [o2, &o4, s1, &s3])]
|
||||||
|
|
|
@ -11,10 +11,12 @@ use rtic::cyccnt::{Instant, U32Ext as _};
|
||||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init(schedule = [foo, bar, baz])]
|
#[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<(), ()> = c.schedule.foo(c.start + 10.cycles());
|
||||||
let _: Result<(), u32> = c.schedule.bar(c.start + 20.cycles(), 0);
|
let _: Result<(), u32> = c.schedule.bar(c.start + 20.cycles(), 0);
|
||||||
let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 30.cycles(), 0, 1);
|
let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 30.cycles(), 0, 1);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle(schedule = [foo, bar, baz])]
|
#[idle(schedule = [foo, bar, baz])]
|
||||||
|
|
|
@ -10,10 +10,12 @@ use panic_halt as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init(spawn = [foo, bar, baz])]
|
#[init(spawn = [foo, bar, baz])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) -> init::LateResources {
|
||||||
let _: Result<(), ()> = c.spawn.foo();
|
let _: Result<(), ()> = c.spawn.foo();
|
||||||
let _: Result<(), u32> = c.spawn.bar(0);
|
let _: Result<(), u32> = c.spawn.bar(0);
|
||||||
let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
|
let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle(spawn = [foo, bar, baz])]
|
#[idle(spawn = [foo, bar, baz])]
|
||||||
|
|
|
@ -9,8 +9,10 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init(spawn = [taskmain])]
|
#[init(spawn = [taskmain])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) -> init::LateResources {
|
||||||
cx.spawn.taskmain().ok();
|
cx.spawn.taskmain().ok();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task]
|
#[task]
|
||||||
|
|
|
@ -11,8 +11,10 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init(spawn = [foo])]
|
#[init(spawn = [foo])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) -> init::LateResources {
|
||||||
c.spawn.foo().unwrap();
|
c.spawn.foo().unwrap();
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(spawn = [bar, baz])]
|
#[task(spawn = [bar, baz])]
|
||||||
|
|
|
@ -18,7 +18,7 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init(schedule = [foo], spawn = [foo])]
|
#[init(schedule = [foo], spawn = [foo])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) -> init::LateResources {
|
||||||
let _: cyccnt::Instant = cx.start;
|
let _: cyccnt::Instant = cx.start;
|
||||||
let _: rtic::Peripherals = cx.core;
|
let _: rtic::Peripherals = cx.core;
|
||||||
let _: lm3s6965::Peripherals = cx.device;
|
let _: lm3s6965::Peripherals = cx.device;
|
||||||
|
@ -26,6 +26,8 @@ mod app {
|
||||||
let _: init::Spawn = cx.spawn;
|
let _: init::Spawn = cx.spawn;
|
||||||
|
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle(schedule = [foo], spawn = [foo])]
|
#[idle(schedule = [foo], spawn = [foo])]
|
||||||
|
|
|
@ -36,47 +36,38 @@ pub fn codegen(
|
||||||
|
|
||||||
let mut root_init = vec![];
|
let mut root_init = vec![];
|
||||||
|
|
||||||
let mut user_init_imports = vec![];
|
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;
|
||||||
|
|
||||||
let ret = {
|
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)*
|
#(#cfgs)*
|
||||||
pub #name: #ty
|
pub #name: #ty
|
||||||
)
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if !late_fields.is_empty() {
|
let mut user_init_imports = vec![];
|
||||||
let late_resources = util::late_resources_ident(&name);
|
let late_resources = util::late_resources_ident(&name);
|
||||||
|
|
||||||
root_init.push(quote!(
|
root_init.push(quote!(
|
||||||
/// Resources initialized at runtime
|
/// Resources initialized at runtime
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub struct #late_resources {
|
pub struct #late_resources {
|
||||||
#(#late_fields),*
|
#(#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
|
|
||||||
}
|
}
|
||||||
};
|
));
|
||||||
|
|
||||||
|
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_pat = None;
|
||||||
let mut locals_new = None;
|
let mut locals_new = None;
|
||||||
|
@ -95,7 +86,7 @@ pub fn codegen(
|
||||||
let user_init = Some(quote!(
|
let user_init = Some(quote!(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn #name(#(#locals_pat,)* #context: #name::Context) #ret {
|
fn #name(#(#locals_pat,)* #context: #name::Context) -> #name::LateResources {
|
||||||
#(#stmts)*
|
#(#stmts)*
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
|
@ -267,14 +267,12 @@ pub fn codegen(
|
||||||
|
|
||||||
if let Context::Init = ctxt {
|
if let Context::Init = ctxt {
|
||||||
let init = &app.inits.first().unwrap();
|
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!(
|
items.push(quote!(
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use super::#late_resources as LateResources;
|
pub use super::#late_resources as LateResources;
|
||||||
));
|
));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let doc = match ctxt {
|
let doc = match ctxt {
|
||||||
|
|
|
@ -35,8 +35,7 @@ mod tests;
|
||||||
///
|
///
|
||||||
/// The items allowed in the module block are specified below:
|
/// The items allowed in the module block are specified below:
|
||||||
///
|
///
|
||||||
/// # 1. `#[resources]
|
/// # 1. `#[resources] struct <resource-name>`
|
||||||
/// struct <resource-name>`
|
|
||||||
///
|
///
|
||||||
/// This structure contains the declaration of all the resources used by the application. Each field
|
/// 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
|
/// in this structure corresponds to a different resource. Each resource may optionally be given an
|
||||||
|
|
|
@ -4,11 +4,13 @@ use panic_halt as _;
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
#[cfg(never)]
|
#[cfg(never)]
|
||||||
static mut FOO: u32 = 0;
|
static mut FOO: u32 = 0;
|
||||||
|
|
||||||
FOO;
|
FOO;
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle]
|
#[idle]
|
||||||
|
|
|
@ -5,27 +5,27 @@ error[E0425]: cannot find value `FOO` in this scope
|
||||||
| ^^^ not found in this scope
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `FOO` 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
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `FOO` 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
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `FOO` 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
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
error[E0425]: cannot find value `FOO` 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
|
| ^^^ not found in this scope
|
||||||
|
|
||||||
error: duplicate lang item in crate `panic_halt` (which `$CRATE` depends on): `panic_impl`.
|
error: duplicate lang item in crate `panic_halt` (which `$CRATE` depends on): `panic_impl`.
|
||||||
|
|
|
@ -43,12 +43,14 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init(resources = [o1, o4, o5, o6, s3])]
|
#[init(resources = [o1, o4, o5, o6, s3])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) -> init::LateResources {
|
||||||
c.resources.o1;
|
c.resources.o1;
|
||||||
c.resources.o4;
|
c.resources.o4;
|
||||||
c.resources.o5;
|
c.resources.o5;
|
||||||
c.resources.o6;
|
c.resources.o6;
|
||||||
c.resources.s3;
|
c.resources.s3;
|
||||||
|
|
||||||
|
init::LateResources {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle(resources = [o2, &o4, s1, &s3])]
|
#[idle(resources = [o2, &o4, s1, &s3])]
|
||||||
|
|
|
@ -45,81 +45,81 @@ error[E0609]: no field `s3` on type `initResources<'_>`
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `o2` on type `idleResources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `o4` on type `idleResources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `s1` on type `idleResources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `s3` on type `idleResources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `o3` on type `uart0Resources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `s1` on type `uart0Resources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `s2` on type `uart0Resources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `s3` on type `uart0Resources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `s2` on type `uart1Resources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `o5` on type `uart1Resources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
mod app {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {}
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
|
init::LateResources {}
|
||||||
|
}
|
||||||
|
|
||||||
#[task(binds = GPIOA, priority = 1)]
|
#[task(binds = GPIOA, priority = 1)]
|
||||||
fn gpioa(_: gpioa::Context) {}
|
fn gpioa(_: gpioa::Context) {}
|
||||||
|
|
Loading…
Reference in a new issue