mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-29 06:54:33 +01:00
Merge #368
368: Mod over const r=korken89 a=AfoHT Related [RFC](https://github.com/rtic-rs/rfcs/pull/34) Dependent on [rtic-syntax-PR30](https://github.com/rtic-rs/rtic-syntax/pull/30) ~~Currently using my own dev-branch~~ Co-authored-by: Henrik Tjäder <henrik@tjaders.com>
This commit is contained in:
commit
dbf9a7f298
77 changed files with 638 additions and 333 deletions
20
.github/workflows/build.yml
vendored
20
.github/workflows/build.yml
vendored
|
@ -45,7 +45,6 @@ jobs:
|
|||
- x86_64-unknown-linux-gnu
|
||||
toolchain:
|
||||
- stable
|
||||
- 1.36.0
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
@ -79,10 +78,6 @@ jobs:
|
|||
target: ${{ matrix.target }}
|
||||
override: true
|
||||
|
||||
- name: Disable optimisation profiles
|
||||
if: matrix.toolchain == '1.36.0'
|
||||
run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml
|
||||
|
||||
- name: cargo check
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
|
@ -306,7 +301,6 @@ jobs:
|
|||
- x86_64-unknown-linux-gnu
|
||||
toolchain:
|
||||
- stable
|
||||
- 1.36.0
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
@ -340,10 +334,6 @@ jobs:
|
|||
target: ${{ matrix.target }}
|
||||
override: true
|
||||
|
||||
- name: Disable optimisation profiles
|
||||
if: matrix.toolchain == '1.36.0'
|
||||
run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml
|
||||
|
||||
- name: cargo check
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
|
@ -382,13 +372,10 @@ jobs:
|
|||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.36.0
|
||||
toolchain: stable
|
||||
target: thumbv7m-none-eabi
|
||||
override: true
|
||||
|
||||
- name: Disable optimisation profiles
|
||||
run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: false
|
||||
|
@ -426,13 +413,10 @@ jobs:
|
|||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.36.0
|
||||
toolchain: stable
|
||||
target: thumbv6m-none-eabi
|
||||
override: true
|
||||
|
||||
- name: Disable optimisation profiles
|
||||
run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: false
|
||||
|
|
|
@ -9,7 +9,7 @@ is required to follow along.
|
|||
|
||||
[repository]: https://github.com/rtic-rs/cortex-m-rtic
|
||||
|
||||
To run the examples on your laptop / PC you'll need the `qemu-system-arm`
|
||||
To run the examples on your computer you'll need the `qemu-system-arm`
|
||||
program. Check [the embedded Rust book] for instructions on how to set up an
|
||||
embedded development environment that includes QEMU.
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ This is the smallest possible RTIC application:
|
|||
```
|
||||
|
||||
All RTIC applications use the [`app`] attribute (`#[app(..)]`). This attribute
|
||||
must be applied to a `const` item that contains items. The `app` attribute has
|
||||
must be applied to a `mod`-item. The `app` attribute has
|
||||
a mandatory `device` argument that takes a *path* as a value. This path must
|
||||
point to a *peripheral access crate* (PAC) generated using [`svd2rust`]
|
||||
**v0.14.x** or newer. The `app` attribute will expand into a suitable entry
|
||||
|
@ -17,16 +17,9 @@ point so it's not required to use the [`cortex_m_rt::entry`] attribute.
|
|||
[`svd2rust`]: https://crates.io/crates/svd2rust
|
||||
[`cortex_m_rt::entry`]: ../../../api/cortex_m_rt_macros/attr.entry.html
|
||||
|
||||
> **ASIDE**: Some of you may be wondering why we are using a `const` item as a
|
||||
> module and not a proper `mod` item. The reason is that using attributes on
|
||||
> modules requires a feature gate, which requires a nightly toolchain. To make
|
||||
> RTIC work on stable we use the `const` item instead. When more parts of macros
|
||||
> 1.2 are stabilized we'll move from a `const` item to a `mod` item and
|
||||
> eventually to a crate level attribute (`#![app]`).
|
||||
|
||||
## `init`
|
||||
|
||||
Within the pseudo-module the `app` attribute expects to find an initialization
|
||||
Within the `app` module the attribute expects to find an initialization
|
||||
function marked with the `init` attribute. This function must have signature
|
||||
`fn(init::Context) [-> init::LateResources]` (the return type is not always
|
||||
required).
|
||||
|
@ -62,7 +55,7 @@ $ cargo run --example init
|
|||
## `idle`
|
||||
|
||||
A function marked with the `idle` attribute can optionally appear in the
|
||||
pseudo-module. This function is used as the special *idle task* and must have
|
||||
module. This function is used as the special *idle task* and must have
|
||||
signature `fn(idle::Context) - > !`.
|
||||
|
||||
When present, the runtime will execute the `idle` task after `init`. Unlike
|
||||
|
|
|
@ -4,11 +4,13 @@ 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.
|
||||
|
||||
Resources are data visible only to functions declared within the `#[app]`
|
||||
pseudo-module. The framework gives the user complete control over which context
|
||||
module. The framework gives the user complete control over which context
|
||||
can access which resource.
|
||||
|
||||
All resources are declared as a single `struct` within the `#[app]`
|
||||
pseudo-module. Each field in the structure corresponds to a different resource.
|
||||
module. Each field in the structure corresponds to a different resource.
|
||||
The `struct` must be annotated with the following attribute: `#[resources]`.
|
||||
|
||||
Resources can optionally be given an initial value using the `#[init]`
|
||||
attribute. Resources that are not given an initial value are referred to as
|
||||
*late* resources and are covered in more detail in a follow-up section in this
|
||||
|
|
|
@ -95,7 +95,7 @@ following snippet:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init(spawn = [foo, bar])]
|
||||
fn init(cx: init::Context) {
|
||||
cx.spawn.foo().unwrap();
|
||||
|
@ -116,5 +116,5 @@ const APP: () = {
|
|||
fn bar(cx: bar::Context, payload: i32) {
|
||||
// ..
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -143,7 +143,7 @@ $ tail target/rtic-expansion.rs
|
|||
|
||||
``` rust
|
||||
#[doc = r" Implementation details"]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[doc = r" Always include the device crate which contains the vector table"]
|
||||
use lm3s6965 as _;
|
||||
#[no_mangle]
|
||||
|
@ -156,7 +156,7 @@ const APP: () = {
|
|||
rtic::export::wfi()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Or, you can use the [`cargo-expand`] sub-command. This sub-command will expand
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Types, Send and Sync
|
||||
|
||||
Every function within the `APP` pseudo-module has a `Context` structure as its
|
||||
Every function within the `app` module has a `Context` structure as its
|
||||
first parameter. All the fields of these structures have predictable,
|
||||
non-anonymous types so you can write plain functions that take them as arguments.
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ To achieve the fine-grained access control where tasks can only access the
|
|||
static variables (resources) that they have specified in their RTIC attribute
|
||||
the RTIC framework performs a source code level transformation. This
|
||||
transformation consists of placing the resources (static variables) specified by
|
||||
the user *inside* a `const` item and the user code *outside* the `const` item.
|
||||
the user *inside* a module and the user code *outside* the module.
|
||||
This makes it impossible for the user code to refer to these static variables.
|
||||
|
||||
Access to the resources is then given to each task using a `Resources` struct
|
||||
|
@ -29,7 +29,7 @@ happens behind the scenes:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
static mut X: u64: 0;
|
||||
static mut Y: bool: 0;
|
||||
|
||||
|
@ -49,7 +49,7 @@ const APP: () = {
|
|||
}
|
||||
|
||||
// ..
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The framework produces codes like this:
|
||||
|
@ -103,8 +103,8 @@ pub mod bar {
|
|||
}
|
||||
|
||||
/// Implementation details
|
||||
const APP: () = {
|
||||
// everything inside this `const` item is hidden from user code
|
||||
mod app {
|
||||
// everything inside this module is hidden from user code
|
||||
|
||||
static mut X: u64 = 0;
|
||||
static mut Y: bool = 0;
|
||||
|
@ -154,5 +154,5 @@ const APP: () = {
|
|||
// ..
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -28,7 +28,7 @@ An example to illustrate the ceiling analysis:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
struct Resources {
|
||||
// accessed by `foo` (prio = 1) and `bar` (prio = 2)
|
||||
// -> CEILING = 2
|
||||
|
@ -80,5 +80,5 @@ const APP: () = {
|
|||
}
|
||||
|
||||
// ..
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -32,7 +32,7 @@ The example below shows the different types handed out to each task:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mut app {
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
x: u64,
|
||||
|
@ -57,7 +57,7 @@ const APP: () = {
|
|||
}
|
||||
|
||||
// ..
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Now let's see how these types are created by the framework.
|
||||
|
@ -99,7 +99,7 @@ pub mod bar {
|
|||
}
|
||||
}
|
||||
|
||||
const APP: () = {
|
||||
mod app {
|
||||
static mut x: u64 = 0;
|
||||
|
||||
impl rtic::Mutex for resources::x {
|
||||
|
@ -129,7 +129,7 @@ const APP: () = {
|
|||
// ..
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `lock`
|
||||
|
@ -225,7 +225,7 @@ Consider this program:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
x: u64,
|
||||
|
@ -277,7 +277,7 @@ const APP: () = {
|
|||
}
|
||||
|
||||
// ..
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The code generated by the framework looks like this:
|
||||
|
@ -315,7 +315,7 @@ pub mod foo {
|
|||
}
|
||||
}
|
||||
|
||||
const APP: () = {
|
||||
mod app {
|
||||
use cortex_m::register::basepri;
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -368,7 +368,7 @@ const APP: () = {
|
|||
}
|
||||
|
||||
// repeat for resource `y`
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
At the end the compiler will optimize the function `foo` into something like
|
||||
|
@ -430,7 +430,7 @@ handler through preemption. This is best observed in the following example:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
x: u64,
|
||||
|
@ -484,7 +484,7 @@ const APP: () = {
|
|||
// ..
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
IMPORTANT: let's say we *forget* to roll back `BASEPRI` in `UART1` -- this would
|
||||
|
@ -493,7 +493,7 @@ be a bug in the RTIC code generator.
|
|||
``` rust
|
||||
// code generated by RTIC
|
||||
|
||||
const APP: () = {
|
||||
mod app {
|
||||
// ..
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -513,7 +513,7 @@ const APP: () = {
|
|||
// BUG: FORGOT to roll back the BASEPRI to the snapshot value we took before
|
||||
basepri::write(initial);
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The consequence is that `idle` will run at a dynamic priority of `2` and in fact
|
||||
|
|
|
@ -13,7 +13,7 @@ This example gives you an idea of the code that the RTIC framework runs:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(c: init::Context) {
|
||||
// .. user code ..
|
||||
|
@ -28,7 +28,7 @@ const APP: () = {
|
|||
fn foo(c: foo::Context) {
|
||||
// .. user code ..
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The framework generates an entry point that looks like this:
|
||||
|
|
|
@ -10,7 +10,7 @@ initialize late resources.
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
struct Resources {
|
||||
x: Thing,
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ const APP: () = {
|
|||
}
|
||||
|
||||
// ..
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The code generated by the framework looks like this:
|
||||
|
@ -69,7 +69,7 @@ pub mod foo {
|
|||
}
|
||||
|
||||
/// Implementation details
|
||||
const APP: () = {
|
||||
mod app {
|
||||
// uninitialized static
|
||||
static mut x: MaybeUninit<Thing> = MaybeUninit::uninit();
|
||||
|
||||
|
@ -101,7 +101,7 @@ const APP: () = {
|
|||
// ..
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
An important detail here is that `interrupt::enable` behaves like a *compiler
|
||||
|
|
|
@ -12,7 +12,7 @@ are discouraged from directly invoking an interrupt handler.
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(c: init::Context) { .. }
|
||||
|
||||
|
@ -39,7 +39,7 @@ const APP: () = {
|
|||
// in aliasing of the static variable `X`
|
||||
unsafe { UART0() }
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The RTIC framework must generate the interrupt handler code that calls the user
|
||||
|
@ -57,7 +57,7 @@ fn bar(c: bar::Context) {
|
|||
// .. user code ..
|
||||
}
|
||||
|
||||
const APP: () = {
|
||||
mod app {
|
||||
// everything in this block is not visible to user code
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -69,7 +69,7 @@ const APP: () = {
|
|||
unsafe fn USART1() {
|
||||
bar(..);
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## By hardware
|
||||
|
|
|
@ -28,7 +28,7 @@ Consider this example:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
// ..
|
||||
|
||||
#[interrupt(binds = UART0, priority = 2, spawn = [bar, baz])]
|
||||
|
@ -51,7 +51,7 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn UART1();
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The framework produces the following task dispatcher which consists of an
|
||||
|
@ -62,7 +62,7 @@ fn bar(c: bar::Context) {
|
|||
// .. user code ..
|
||||
}
|
||||
|
||||
const APP: () = {
|
||||
mod app {
|
||||
use heapless::spsc::Queue;
|
||||
use cortex_m::register::basepri;
|
||||
|
||||
|
@ -110,7 +110,7 @@ const APP: () = {
|
|||
// BASEPRI invariant
|
||||
basepri::write(snapshot);
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Spawning a task
|
||||
|
@ -144,7 +144,7 @@ mod foo {
|
|||
}
|
||||
}
|
||||
|
||||
const APP: () = {
|
||||
mod app {
|
||||
// ..
|
||||
|
||||
// Priority ceiling for the producer endpoint of the `RQ1`
|
||||
|
@ -194,7 +194,7 @@ const APP: () = {
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Using `bar_FQ` to limit the number of `bar` tasks that can be spawned may seem
|
||||
|
@ -211,7 +211,7 @@ fn baz(c: baz::Context, input: u64) {
|
|||
// .. user code ..
|
||||
}
|
||||
|
||||
const APP: () = {
|
||||
mod app {
|
||||
// ..
|
||||
|
||||
// Now we show the full contents of the `Ready` struct
|
||||
|
@ -263,13 +263,13 @@ const APP: () = {
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
And now let's look at the real implementation of the task dispatcher:
|
||||
|
||||
``` rust
|
||||
const APP: () = {
|
||||
mod app {
|
||||
// ..
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -304,7 +304,7 @@ const APP: () = {
|
|||
// BASEPRI invariant
|
||||
basepri::write(snapshot);
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
`INPUTS` plus `FQ`, the free queue, is effectively a memory pool. However,
|
||||
|
@ -357,7 +357,7 @@ Consider the following example:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[idle(spawn = [foo, bar])]
|
||||
fn idle(c: idle::Context) -> ! {
|
||||
// ..
|
||||
|
@ -382,7 +382,7 @@ const APP: () = {
|
|||
fn quux(c: quux::Context) {
|
||||
// ..
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This is how the ceiling analysis would go:
|
||||
|
|
|
@ -12,7 +12,7 @@ Let's see how this in implemented in code. Consider the following program:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
// ..
|
||||
|
||||
#[task(capacity = 2, schedule = [foo])]
|
||||
|
@ -24,7 +24,7 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn UART0();
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## `schedule`
|
||||
|
@ -46,7 +46,7 @@ mod foo {
|
|||
}
|
||||
}
|
||||
|
||||
const APP: () = {
|
||||
mod app {
|
||||
type Instant = <path::to::user::monotonic::timer as rtic::Monotonic>::Instant;
|
||||
|
||||
// all tasks that can be `schedule`-d
|
||||
|
@ -100,7 +100,7 @@ const APP: () = {
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This looks very similar to the `Spawn` implementation. In fact, the same
|
||||
|
@ -123,7 +123,7 @@ is up.
|
|||
Let's see the associated code.
|
||||
|
||||
``` rust
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[no_mangle]
|
||||
fn SysTick() {
|
||||
const PRIORITY: u8 = 1;
|
||||
|
@ -146,7 +146,7 @@ const APP: () = {
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This looks similar to a task dispatcher except that instead of running the
|
||||
|
@ -197,7 +197,7 @@ able to insert the task in the timer queue; this lets us omit runtime checks.
|
|||
|
||||
## System timer priority
|
||||
|
||||
The priority of the system timer can't set by the user; it is chosen by the
|
||||
The priority of the system timer can't be set by the user; it is chosen by the
|
||||
framework. To ensure that lower priority tasks don't prevent higher priority
|
||||
tasks from running we choose the priority of the system timer to be the maximum
|
||||
of all the `schedule`-able tasks.
|
||||
|
@ -222,7 +222,7 @@ To illustrate, consider the following example:
|
|||
|
||||
``` rust
|
||||
#[rtic::app(device = ..)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[task(priority = 3, spawn = [baz])]
|
||||
fn foo(c: foo::Context) {
|
||||
// ..
|
||||
|
@ -237,7 +237,7 @@ const APP: () = {
|
|||
fn baz(c: baz::Context) {
|
||||
// ..
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The ceiling analysis would go like this:
|
||||
|
@ -246,7 +246,7 @@ The ceiling analysis would go like this:
|
|||
`SysTick` must run at the highest priority between these two, that is `3`.
|
||||
|
||||
- `foo::Spawn` (prio = 3) and `bar::Schedule` (prio = 2) contend over the
|
||||
consumer endpoind of `baz_FQ`; this leads to a priority ceiling of `3`.
|
||||
consumer endpoint of `baz_FQ`; this leads to a priority ceiling of `3`.
|
||||
|
||||
- `bar::Schedule` (prio = 2) has exclusive access over the consumer endpoint of
|
||||
`foo_FQ`; thus the priority ceiling of `foo_FQ` is effectively `2`.
|
||||
|
@ -270,7 +270,7 @@ run; this `Instant` is read in the task dispatcher and passed to the user code
|
|||
as part of the task context.
|
||||
|
||||
``` rust
|
||||
const APP: () = {
|
||||
mod app {
|
||||
// ..
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -303,7 +303,7 @@ const APP: () = {
|
|||
// BASEPRI invariant
|
||||
basepri::write(snapshot);
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Conversely, the `spawn` implementation needs to write a value to the `INSTANTS`
|
||||
|
@ -333,7 +333,7 @@ mod foo {
|
|||
}
|
||||
}
|
||||
|
||||
const APP: () = {
|
||||
mod app {
|
||||
impl<'a> foo::Spawn<'a> {
|
||||
/// Spawns the `baz` task
|
||||
pub fn baz(&self, message: u64) -> Result<(), u64> {
|
||||
|
@ -364,5 +364,5 @@ const APP: () = {
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
|
|
@ -1,14 +1,112 @@
|
|||
# Migrating from v0.4.x to v0.5.0
|
||||
# Migration of RTIC
|
||||
|
||||
## 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`
|
||||
### `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
|
||||
|
@ -22,7 +120,7 @@ features = ["timer-queue"]
|
|||
# ^^^^^^^^^^^^^
|
||||
```
|
||||
|
||||
## `Context` argument
|
||||
### `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
|
||||
|
@ -74,7 +172,7 @@ const APP: () = {
|
|||
};
|
||||
```
|
||||
|
||||
## Resources
|
||||
### Resources
|
||||
|
||||
The syntax used to declare resources has been changed from `static mut`
|
||||
variables to a `struct Resources`.
|
||||
|
@ -98,7 +196,7 @@ const APP: () = {
|
|||
};
|
||||
```
|
||||
|
||||
## Device peripherals
|
||||
### 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
|
||||
|
@ -136,7 +234,7 @@ const APP: () = {
|
|||
};
|
||||
```
|
||||
|
||||
## `#[interrupt]` and `#[exception]`
|
||||
### `#[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.
|
||||
|
@ -182,7 +280,7 @@ const APP: () = {
|
|||
};
|
||||
```
|
||||
|
||||
## `schedule`
|
||||
### `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`
|
||||
|
|
|
@ -13,8 +13,10 @@ There is a translation of this book in [Russian].
|
|||
|
||||
[Russian]: ../ru/index.html
|
||||
|
||||
This is the documentation of v0.5.x of RTIC; for the documentation of version
|
||||
v0.4.x go [here](/0.4).
|
||||
This is the documentation of v0.6.x of RTIC; for the documentation of version
|
||||
|
||||
* v0.5.x go [here](/0.5).
|
||||
* v0.4.x go [here](/0.4).
|
||||
|
||||
{{#include ../../../README.md:7:46}}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use panic_semihosting as _;
|
|||
|
||||
// NOTE: does NOT properly work on QEMU
|
||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init(spawn = [foo])]
|
||||
fn init(cx: init::Context) {
|
||||
// omitted: initialization of `CYCCNT`
|
||||
|
@ -51,4 +51,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use panic_semihosting as _;
|
|||
|
||||
// `examples/interrupt.rs` rewritten to use `binds`
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
@ -45,4 +45,4 @@ const APP: () = {
|
|||
)
|
||||
.unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use lm3s6965::Interrupt;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
@ -44,4 +44,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ use cortex_m_semihosting::hprintln;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[cfg(debug_assertions)] // <- `true` when using the `dev` profile
|
||||
#[init(0)]
|
||||
|
@ -66,4 +67,4 @@ const APP: () = {
|
|||
fn SSI0();
|
||||
fn QEI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ use lm3s6965::Interrupt;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
// Some resources to work with
|
||||
#[init(0)]
|
||||
|
@ -44,4 +45,4 @@ const APP: () = {
|
|||
|
||||
hprintln!("UART0: a = {}, b = {}, c = {}", a, b, c).unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@ use panic_semihosting as _;
|
|||
use rtic::cyccnt::U32Ext;
|
||||
|
||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
|
||||
#[resources]
|
||||
struct Resources {
|
||||
nothing: (),
|
||||
}
|
||||
|
@ -34,4 +36,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ use panic_semihosting as _;
|
|||
use rtic::{Exclusive, Mutex};
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
shared: u32,
|
||||
|
@ -49,7 +50,7 @@ const APP: () = {
|
|||
// second argument has type `Exclusive<u32>`
|
||||
advance(STATE, Exclusive(c.resources.shared));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// the second parameter is generic: it can be any type that implements the `Mutex` trait
|
||||
fn advance(state: &mut u32, mut shared: impl Mutex<T = u32>) {
|
||||
|
|
|
@ -10,7 +10,7 @@ use lm3s6965::Interrupt;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
// Pends the UART0 interrupt but its handler won't run until *after*
|
||||
|
@ -49,4 +49,4 @@ const APP: () = {
|
|||
)
|
||||
.unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
hprintln!("init").unwrap();
|
||||
|
@ -30,4 +30,4 @@ const APP: () = {
|
|||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, peripherals = true)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(cx: init::Context) {
|
||||
static mut X: u32 = 0;
|
||||
|
@ -31,4 +31,4 @@ const APP: () = {
|
|||
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,8 +15,13 @@ use lm3s6965::Interrupt;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
use heapless::{
|
||||
consts::*,
|
||||
spsc::{Consumer, Producer},
|
||||
};
|
||||
// Late resources
|
||||
#[resources]
|
||||
struct Resources {
|
||||
p: Producer<'static, u32, U4>,
|
||||
c: Consumer<'static, u32, U4>,
|
||||
|
@ -49,4 +54,4 @@ const APP: () = {
|
|||
fn uart0(c: uart0::Context) {
|
||||
c.resources.p.enqueue(42).unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ use lm3s6965::Interrupt;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
shared: u32,
|
||||
|
@ -59,4 +60,4 @@ const APP: () = {
|
|||
fn gpioc(_: gpioc::Context) {
|
||||
hprintln!("C").unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init(spawn = [foo])]
|
||||
fn init(c: init::Context) {
|
||||
c.spawn.foo(/* no message */).unwrap();
|
||||
|
@ -49,4 +49,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,7 +16,10 @@ pub struct NotSend {
|
|||
}
|
||||
|
||||
#[app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
use super::NotSend;
|
||||
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[init(None)]
|
||||
shared: Option<NotSend>,
|
||||
|
@ -60,4 +63,4 @@ const APP: () = {
|
|||
fn SSI0();
|
||||
fn QEI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,7 +15,11 @@ pub struct NotSync {
|
|||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
use super::NotSync;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[init(NotSync { _0: PhantomData })]
|
||||
shared: NotSync,
|
||||
|
@ -42,4 +46,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ use lm3s6965::Interrupt;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
key: u32,
|
||||
}
|
||||
|
@ -35,4 +36,4 @@ const APP: () = {
|
|||
fn uart1(cx: uart1::Context) {
|
||||
hprintln!("UART1(key = {:#x})", cx.resources.key).unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ const PERIOD: u32 = 8_000_000;
|
|||
|
||||
// NOTE: does NOT work on QEMU!
|
||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
|
||||
#[init(schedule = [foo])]
|
||||
fn init(cx: init::Context) {
|
||||
// omitted: initialization of `CYCCNT`
|
||||
|
@ -35,4 +36,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@ use cortex_m_semihosting::debug;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn main(_: main::Context) {
|
||||
fn taskmain(_: taskmain::Context) {
|
||||
assert!(cortex_m::Peripherals::take().is_none());
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,7 +18,12 @@ use rtic::app;
|
|||
pool!(P: [u8; 128]);
|
||||
|
||||
#[app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
use crate::Box;
|
||||
|
||||
// Import the memory pool into scope
|
||||
use super::P;
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
static mut MEMORY: [u8; 512] = [0; 512];
|
||||
|
@ -66,4 +71,4 @@ const APP: () = {
|
|||
fn SSI0();
|
||||
fn QEI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use panic_semihosting as _;
|
|||
use rtic::app;
|
||||
|
||||
#[app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
rtic::pend(Interrupt::GPIOA);
|
||||
|
@ -34,4 +34,4 @@ const APP: () = {
|
|||
rtic::pend(Interrupt::GPIOB);
|
||||
hprintln!(" GPIOC - end").unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init(spawn = [bar])]
|
||||
fn init(c: init::Context) {
|
||||
c.spawn.bar().unwrap();
|
||||
|
@ -38,4 +38,4 @@ const APP: () = {
|
|||
#[link_section = ".data.UART1"]
|
||||
fn UART1();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
61
examples/resource-user-struct.rs
Normal file
61
examples/resource-user-struct.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
//! examples/resource.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
// A resource
|
||||
#[init(0)]
|
||||
shared: u32,
|
||||
}
|
||||
|
||||
// Should not collide with the struct above
|
||||
#[allow(dead_code)]
|
||||
struct Resources2 {
|
||||
// A resource
|
||||
shared: u32,
|
||||
}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART1);
|
||||
}
|
||||
|
||||
// `shared` cannot be accessed from this context
|
||||
#[idle]
|
||||
fn idle(_cx: idle::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
|
||||
// error: no `resources` field in `idle::Context`
|
||||
// _cx.resources.shared += 1;
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
// `shared` can be accessed from this context
|
||||
#[task(binds = UART0, resources = [shared])]
|
||||
fn uart0(cx: uart0::Context) {
|
||||
let shared: &mut u32 = cx.resources.shared;
|
||||
*shared += 1;
|
||||
|
||||
hprintln!("UART0: shared = {}", shared).unwrap();
|
||||
}
|
||||
|
||||
// `shared` can be accessed from this context
|
||||
#[task(binds = UART1, resources = [shared])]
|
||||
fn uart1(cx: uart1::Context) {
|
||||
*cx.resources.shared += 1;
|
||||
|
||||
hprintln!("UART1: shared = {}", cx.resources.shared).unwrap();
|
||||
}
|
||||
}
|
|
@ -10,7 +10,8 @@ use lm3s6965::Interrupt;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
// A resource
|
||||
#[init(0)]
|
||||
|
@ -52,4 +53,4 @@ const APP: () = {
|
|||
|
||||
hprintln!("UART1: shared = {}", cx.resources.shared).unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use rtic::cyccnt::{Instant, U32Ext as _};
|
|||
|
||||
// NOTE: does NOT work on QEMU!
|
||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init(schedule = [foo, bar])]
|
||||
fn init(mut cx: init::Context) {
|
||||
// Initialize (enable) the monotonic timer (CYCCNT)
|
||||
|
@ -50,4 +50,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,7 +13,10 @@ use rtic::app;
|
|||
pub struct MustBeSend;
|
||||
|
||||
#[app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
use super::MustBeSend;
|
||||
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[init(None)]
|
||||
shared: Option<MustBeSend>,
|
||||
|
@ -37,4 +40,4 @@ const APP: () = {
|
|||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,4 +7,4 @@ use panic_semihosting as _; // panic handler
|
|||
use rtic::app;
|
||||
|
||||
#[app(device = lm3s6965)]
|
||||
const APP: () = {};
|
||||
mod app {}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
use panic_halt as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(_: init::Context) {}
|
||||
|
||||
|
@ -23,7 +23,7 @@ const APP: () = {
|
|||
fn bar(c: bar::Context) {
|
||||
bar_trampoline(c)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn foo_trampoline(_: foo::Context) {}
|
||||
|
|
|
@ -6,19 +6,17 @@
|
|||
use panic_halt as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
// A resource
|
||||
#[init(0)]
|
||||
shared: u32,
|
||||
|
||||
// A conditionally compiled resource behind feature_x
|
||||
#[cfg(feature = "feature_x")]
|
||||
x: u32,
|
||||
|
||||
dummy: (),
|
||||
dummy: (), // dummy such that we have at least one late resource
|
||||
}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> init::LateResources {
|
||||
init::LateResources {
|
||||
|
@ -35,4 +33,4 @@ const APP: () = {
|
|||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
use panic_halt as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[cfg(never)]
|
||||
#[init(0)]
|
||||
|
@ -52,4 +53,4 @@ const APP: () = {
|
|||
fn SSI0();
|
||||
fn QEI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,14 +7,14 @@ use cortex_m_semihosting::debug;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
rtic::pend(lm3s6965::Interrupt::UART0)
|
||||
}
|
||||
|
||||
#[task(binds = UART0)]
|
||||
fn main(_: main::Context) {
|
||||
fn taskmain(_: taskmain::Context) {
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,15 +7,15 @@ use cortex_m_semihosting::debug;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(_: init::Context) {}
|
||||
|
||||
#[idle]
|
||||
fn main(_: main::Context) -> ! {
|
||||
fn taskmain(_: taskmain::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ use cortex_m_semihosting::debug;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn main(_: main::Context) {
|
||||
fn taskmain(_: taskmain::Context) {
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,7 +12,10 @@ pub struct NotSend {
|
|||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
use super::NotSend;
|
||||
|
||||
#[resources]
|
||||
struct Resources {
|
||||
x: NotSend,
|
||||
#[init(None)]
|
||||
|
@ -35,4 +38,4 @@ const APP: () = {
|
|||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
use panic_halt as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
o1: u32, // init
|
||||
|
@ -86,4 +87,4 @@ const APP: () = {
|
|||
// no `Mutex` proxy when co-owned by cooperative (same priority) tasks
|
||||
let _: &mut u32 = c.resources.s2;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use panic_halt as _;
|
|||
use rtic::cyccnt::{Instant, U32Ext as _};
|
||||
|
||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init(schedule = [foo, bar, baz])]
|
||||
fn init(c: init::Context) {
|
||||
let _: Result<(), ()> = c.schedule.foo(c.start + 10.cycles());
|
||||
|
@ -61,4 +61,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
use panic_halt as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init(spawn = [foo, bar, baz])]
|
||||
fn init(c: init::Context) {
|
||||
let _: Result<(), ()> = c.spawn.foo();
|
||||
|
@ -60,4 +60,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,14 +7,14 @@ use cortex_m_semihosting::debug;
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
#[init(spawn = [main])]
|
||||
mod app {
|
||||
#[init(spawn = [taskmain])]
|
||||
fn init(cx: init::Context) {
|
||||
cx.spawn.main().ok();
|
||||
cx.spawn.taskmain().ok();
|
||||
}
|
||||
|
||||
#[task]
|
||||
fn main(_: main::Context) {
|
||||
fn taskmain(_: taskmain::Context) {
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -24,4 +24,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
|||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init(spawn = [foo])]
|
||||
fn init(c: init::Context) {
|
||||
c.spawn.foo().unwrap();
|
||||
|
@ -52,4 +52,4 @@ const APP: () = {
|
|||
fn SSI0();
|
||||
fn QEI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ use panic_semihosting as _;
|
|||
use rtic::cyccnt;
|
||||
|
||||
#[rtic::app(device = lm3s6965, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[init(0)]
|
||||
shared: u32,
|
||||
|
@ -60,4 +61,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn SSI0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -25,21 +25,36 @@ mod util;
|
|||
|
||||
// TODO document the syntax here or in `rtic-syntax`
|
||||
pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||
let mut const_app = vec![];
|
||||
let mut mod_app = vec![];
|
||||
let mut mod_app_imports = vec![];
|
||||
let mut mains = vec![];
|
||||
let mut root = vec![];
|
||||
let mut user = vec![];
|
||||
let mut imports = vec![];
|
||||
|
||||
// Generate the `main` function
|
||||
let assertion_stmts = assertions::codegen(analysis);
|
||||
|
||||
let pre_init_stmts = pre_init::codegen(&app, analysis, extra);
|
||||
|
||||
let (const_app_init, root_init, user_init, call_init) = init::codegen(app, analysis, extra);
|
||||
let (mod_app_init, root_init, user_init, user_init_imports, call_init) =
|
||||
init::codegen(app, analysis, extra);
|
||||
|
||||
let post_init_stmts = post_init::codegen(&app, analysis);
|
||||
|
||||
let (const_app_idle, root_idle, user_idle, call_idle) = idle::codegen(app, analysis, extra);
|
||||
let (mod_app_idle, root_idle, user_idle, user_idle_imports, call_idle) =
|
||||
idle::codegen(app, analysis, extra);
|
||||
|
||||
if user_init.is_some() {
|
||||
mod_app_imports.push(quote!(
|
||||
use super::init;
|
||||
))
|
||||
}
|
||||
if user_idle.is_some() {
|
||||
mod_app_imports.push(quote!(
|
||||
use super::idle;
|
||||
))
|
||||
}
|
||||
|
||||
user.push(quote!(
|
||||
#user_init
|
||||
|
@ -47,16 +62,21 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
|||
#user_idle
|
||||
));
|
||||
|
||||
imports.push(quote!(
|
||||
#(#user_init_imports)*
|
||||
#(#user_idle_imports)*
|
||||
));
|
||||
|
||||
root.push(quote!(
|
||||
#(#root_init)*
|
||||
|
||||
#(#root_idle)*
|
||||
));
|
||||
|
||||
const_app.push(quote!(
|
||||
#const_app_init
|
||||
mod_app.push(quote!(
|
||||
#mod_app_init
|
||||
|
||||
#const_app_idle
|
||||
#mod_app_idle
|
||||
));
|
||||
|
||||
let main = util::suffixed("main");
|
||||
|
@ -77,22 +97,33 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
|||
}
|
||||
));
|
||||
|
||||
let (const_app_resources, mod_resources) = resources::codegen(app, analysis, extra);
|
||||
let (mod_app_resources, mod_resources, mod_resources_imports) =
|
||||
resources::codegen(app, analysis, extra);
|
||||
|
||||
let (const_app_hardware_tasks, root_hardware_tasks, user_hardware_tasks) =
|
||||
hardware_tasks::codegen(app, analysis, extra);
|
||||
let (
|
||||
mod_app_hardware_tasks,
|
||||
root_hardware_tasks,
|
||||
user_hardware_tasks,
|
||||
user_hardware_tasks_imports,
|
||||
) = hardware_tasks::codegen(app, analysis, extra);
|
||||
|
||||
let (const_app_software_tasks, root_software_tasks, user_software_tasks) =
|
||||
software_tasks::codegen(app, analysis, extra);
|
||||
let (
|
||||
mod_app_software_tasks,
|
||||
root_software_tasks,
|
||||
user_software_tasks,
|
||||
user_software_tasks_imports,
|
||||
) = software_tasks::codegen(app, analysis, extra);
|
||||
|
||||
let const_app_dispatchers = dispatchers::codegen(app, analysis, extra);
|
||||
let mod_app_dispatchers = dispatchers::codegen(app, analysis, extra);
|
||||
|
||||
let const_app_spawn = spawn::codegen(app, analysis, extra);
|
||||
let mod_app_spawn = spawn::codegen(app, analysis, extra);
|
||||
|
||||
let const_app_timer_queue = timer_queue::codegen(app, analysis, extra);
|
||||
let mod_app_timer_queue = timer_queue::codegen(app, analysis, extra);
|
||||
|
||||
let const_app_schedule = schedule::codegen(app, extra);
|
||||
let mod_app_schedule = schedule::codegen(app, extra);
|
||||
|
||||
let user_imports = app.user_imports.clone();
|
||||
let user_code = app.user_code.clone();
|
||||
let name = &app.name;
|
||||
let device = extra.device;
|
||||
quote!(
|
||||
|
@ -111,28 +142,41 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
|||
#(#root_software_tasks)*
|
||||
|
||||
/// Implementation details
|
||||
// The user can't access the items within this `const` item
|
||||
const #name: () = {
|
||||
mod #name {
|
||||
/// Always include the device crate which contains the vector table
|
||||
use #device as _;
|
||||
#(#imports)*
|
||||
#(#user_imports)*
|
||||
|
||||
#(#const_app)*
|
||||
/// User code from within the module
|
||||
#(#user_code)*
|
||||
/// User code end
|
||||
|
||||
#(#const_app_resources)*
|
||||
|
||||
#(#const_app_hardware_tasks)*
|
||||
#(#user_hardware_tasks_imports)*
|
||||
|
||||
#(#const_app_software_tasks)*
|
||||
#(#user_software_tasks_imports)*
|
||||
|
||||
#(#const_app_dispatchers)*
|
||||
#(#mod_resources_imports)*
|
||||
|
||||
#(#const_app_spawn)*
|
||||
/// app module
|
||||
#(#mod_app)*
|
||||
|
||||
#(#const_app_timer_queue)*
|
||||
#(#mod_app_resources)*
|
||||
|
||||
#(#const_app_schedule)*
|
||||
#(#mod_app_hardware_tasks)*
|
||||
|
||||
#(#mod_app_software_tasks)*
|
||||
|
||||
#(#mod_app_dispatchers)*
|
||||
|
||||
#(#mod_app_spawn)*
|
||||
|
||||
#(#mod_app_timer_queue)*
|
||||
|
||||
#(#mod_app_schedule)*
|
||||
|
||||
#(#mains)*
|
||||
};
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use quote::{format_ident, quote};
|
||||
use rtic_syntax::{ast::App, Context};
|
||||
|
||||
use crate::{
|
||||
|
@ -14,7 +14,7 @@ pub fn codegen(
|
|||
analysis: &Analysis,
|
||||
extra: &Extra,
|
||||
) -> (
|
||||
// const_app_hardware_tasks -- interrupt handlers and `${task}Resources` constructors
|
||||
// mod_app_hardware_tasks -- interrupt handlers and `${task}Resources` constructors
|
||||
Vec<TokenStream2>,
|
||||
// root_hardware_tasks -- items that must be placed in the root of the crate:
|
||||
// - `${task}Locals` structs
|
||||
|
@ -23,10 +23,13 @@ pub fn codegen(
|
|||
Vec<TokenStream2>,
|
||||
// user_hardware_tasks -- the `#[task]` functions written by the user
|
||||
Vec<TokenStream2>,
|
||||
// user_hardware_tasks_imports -- the imports for `#[task]` functions written by the user
|
||||
Vec<TokenStream2>,
|
||||
) {
|
||||
let mut const_app = vec![];
|
||||
let mut mod_app = vec![];
|
||||
let mut root = vec![];
|
||||
let mut user_tasks = vec![];
|
||||
let mut hardware_tasks_imports = vec![];
|
||||
|
||||
for (name, task) in &app.hardware_tasks {
|
||||
let (let_instant, instant) = if app.uses_schedule() {
|
||||
|
@ -49,7 +52,7 @@ pub fn codegen(
|
|||
let symbol = task.args.binds.clone();
|
||||
let priority = task.args.priority;
|
||||
|
||||
const_app.push(quote!(
|
||||
mod_app.push(quote!(
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
unsafe fn #symbol() {
|
||||
|
@ -78,9 +81,16 @@ pub fn codegen(
|
|||
analysis,
|
||||
);
|
||||
|
||||
// Add resources to imports
|
||||
let name_res = format_ident!("{}Resources", name);
|
||||
hardware_tasks_imports.push(quote!(
|
||||
#[allow(non_snake_case)]
|
||||
use super::#name_res;
|
||||
));
|
||||
|
||||
root.push(item);
|
||||
|
||||
const_app.push(constructor);
|
||||
mod_app.push(constructor);
|
||||
}
|
||||
|
||||
root.push(module::codegen(
|
||||
|
@ -112,7 +122,13 @@ pub fn codegen(
|
|||
#(#stmts)*
|
||||
}
|
||||
));
|
||||
|
||||
hardware_tasks_imports.push(quote!(
|
||||
#(#attrs)*
|
||||
#[allow(non_snake_case)]
|
||||
use super::#name;
|
||||
));
|
||||
}
|
||||
|
||||
(const_app, root, user_tasks)
|
||||
(mod_app, root, user_tasks, hardware_tasks_imports)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use quote::{format_ident, quote};
|
||||
use rtic_syntax::{ast::App, Context};
|
||||
|
||||
use crate::{
|
||||
|
@ -14,7 +14,7 @@ pub fn codegen(
|
|||
analysis: &Analysis,
|
||||
extra: &Extra,
|
||||
) -> (
|
||||
// const_app_idle -- the `${idle}Resources` constructor
|
||||
// mod_app_idle -- the `${idle}Resources` constructor
|
||||
Option<TokenStream2>,
|
||||
// root_idle -- items that must be placed in the root of the crate:
|
||||
// - the `${idle}Locals` struct
|
||||
|
@ -23,26 +23,37 @@ pub fn codegen(
|
|||
Vec<TokenStream2>,
|
||||
// user_idle
|
||||
Option<TokenStream2>,
|
||||
// user_idle_imports
|
||||
Vec<TokenStream2>,
|
||||
// call_idle
|
||||
TokenStream2,
|
||||
) {
|
||||
if app.idles.len() > 0 {
|
||||
let idle = &app.idles.first().unwrap();
|
||||
let mut needs_lt = false;
|
||||
let mut const_app = None;
|
||||
let mut mod_app = None;
|
||||
let mut root_idle = vec![];
|
||||
let mut locals_pat = None;
|
||||
let mut locals_new = None;
|
||||
|
||||
let mut user_idle_imports = vec![];
|
||||
|
||||
let name = &idle.name;
|
||||
|
||||
if !idle.args.resources.is_empty() {
|
||||
let (item, constructor) =
|
||||
resources_struct::codegen(Context::Idle, 0, &mut needs_lt, app, analysis);
|
||||
|
||||
root_idle.push(item);
|
||||
const_app = Some(constructor);
|
||||
mod_app = Some(constructor);
|
||||
|
||||
let name_resource = format_ident!("{}Resources", name);
|
||||
user_idle_imports.push(quote!(
|
||||
#[allow(non_snake_case)]
|
||||
use super::#name_resource;
|
||||
));
|
||||
}
|
||||
|
||||
let name = &idle.name;
|
||||
if !idle.locals.is_empty() {
|
||||
let (locals, pat) = locals::codegen(Context::Idle, &idle.locals, app);
|
||||
|
||||
|
@ -66,6 +77,11 @@ pub fn codegen(
|
|||
#(#stmts)*
|
||||
}
|
||||
));
|
||||
user_idle_imports.push(quote!(
|
||||
#(#attrs)*
|
||||
#[allow(non_snake_case)]
|
||||
use super::#name;
|
||||
));
|
||||
|
||||
let locals_new = locals_new.iter();
|
||||
let call_idle = quote!(crate::#name(
|
||||
|
@ -73,12 +89,13 @@ pub fn codegen(
|
|||
#name::Context::new(&rtic::export::Priority::new(0))
|
||||
));
|
||||
|
||||
(const_app, root_idle, user_idle, call_idle)
|
||||
(mod_app, root_idle, user_idle, user_idle_imports, call_idle)
|
||||
} else {
|
||||
(
|
||||
None,
|
||||
vec![],
|
||||
None,
|
||||
vec![],
|
||||
quote!(loop {
|
||||
rtic::export::wfi()
|
||||
}),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use quote::{format_ident, quote};
|
||||
use rtic_syntax::{ast::App, Context};
|
||||
|
||||
use crate::{
|
||||
|
@ -14,7 +14,7 @@ pub fn codegen(
|
|||
analysis: &Analysis,
|
||||
extra: &Extra,
|
||||
) -> (
|
||||
// const_app_idle -- the `${init}Resources` constructor
|
||||
// mod_app_idle -- the `${init}Resources` constructor
|
||||
Option<TokenStream2>,
|
||||
// root_init -- items that must be placed in the root of the crate:
|
||||
// - the `${init}Locals` struct
|
||||
|
@ -24,6 +24,8 @@ pub fn codegen(
|
|||
Vec<TokenStream2>,
|
||||
// user_init -- the `#[init]` function written by the user
|
||||
Option<TokenStream2>,
|
||||
// user_init_imports -- the imports for `#[init]` functio written by the user
|
||||
Vec<TokenStream2>,
|
||||
// call_init -- the call to the user `#[init]` if there's one
|
||||
Option<TokenStream2>,
|
||||
) {
|
||||
|
@ -34,6 +36,8 @@ pub fn codegen(
|
|||
|
||||
let mut root_init = vec![];
|
||||
|
||||
let mut user_init_imports = vec![];
|
||||
|
||||
let ret = {
|
||||
let late_fields = analysis
|
||||
.late_resources
|
||||
|
@ -62,6 +66,12 @@ pub fn codegen(
|
|||
}
|
||||
));
|
||||
|
||||
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
|
||||
|
@ -89,14 +99,25 @@ pub fn codegen(
|
|||
#(#stmts)*
|
||||
}
|
||||
));
|
||||
user_init_imports.push(quote!(
|
||||
#(#attrs)*
|
||||
#[allow(non_snake_case)]
|
||||
use super::#name;
|
||||
));
|
||||
|
||||
let mut const_app = None;
|
||||
let mut mod_app = None;
|
||||
if !init.args.resources.is_empty() {
|
||||
let (item, constructor) =
|
||||
resources_struct::codegen(Context::Init, 0, &mut needs_lt, app, analysis);
|
||||
|
||||
root_init.push(item);
|
||||
const_app = Some(constructor);
|
||||
mod_app = Some(constructor);
|
||||
|
||||
let name_late = format_ident!("{}Resources", name);
|
||||
user_init_imports.push(quote!(
|
||||
#[allow(non_snake_case)]
|
||||
use super::#name_late;
|
||||
));
|
||||
}
|
||||
|
||||
let locals_new = locals_new.iter();
|
||||
|
@ -106,8 +127,8 @@ pub fn codegen(
|
|||
|
||||
root_init.push(module::codegen(Context::Init, needs_lt, app, extra));
|
||||
|
||||
(const_app, root_init, user_init, call_init)
|
||||
(mod_app, root_init, user_init, user_init_imports, call_init)
|
||||
} else {
|
||||
(None, vec![], None, None)
|
||||
(None, vec![], None, vec![], None)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,16 @@ pub fn codegen(
|
|||
analysis: &Analysis,
|
||||
extra: &Extra,
|
||||
) -> (
|
||||
// const_app -- the `static [mut]` variables behind the proxies
|
||||
// mod_app -- the `static [mut]` variables behind the proxies
|
||||
Vec<TokenStream2>,
|
||||
// mod_resources -- the `resources` module
|
||||
TokenStream2,
|
||||
// mod_resources_imports -- the `resources` module imports
|
||||
Vec<TokenStream2>,
|
||||
) {
|
||||
let mut const_app = vec![];
|
||||
let mut mod_app = vec![];
|
||||
let mut mod_resources = vec![];
|
||||
let mut mod_resources_imports = vec![];
|
||||
|
||||
for (name, res, expr, _) in app.resources(analysis) {
|
||||
let cfgs = &res.cfgs;
|
||||
|
@ -39,7 +42,7 @@ pub fn codegen(
|
|||
};
|
||||
|
||||
let attrs = &res.attrs;
|
||||
const_app.push(quote!(
|
||||
mod_app.push(quote!(
|
||||
#[allow(non_upper_case_globals)]
|
||||
#(#attrs)*
|
||||
#(#cfgs)*
|
||||
|
@ -82,7 +85,13 @@ pub fn codegen(
|
|||
)
|
||||
};
|
||||
|
||||
const_app.push(util::impl_mutex(
|
||||
mod_resources_imports.push(quote!(
|
||||
#[allow(non_camel_case_types)]
|
||||
#(#cfgs)*
|
||||
use super::resources::#name;
|
||||
));
|
||||
|
||||
mod_app.push(util::impl_mutex(
|
||||
extra,
|
||||
cfgs,
|
||||
true,
|
||||
|
@ -97,6 +106,11 @@ pub fn codegen(
|
|||
let mod_resources = if mod_resources.is_empty() {
|
||||
quote!()
|
||||
} else {
|
||||
// Also import the resource module
|
||||
mod_resources_imports.push(quote!(
|
||||
use super::resources;
|
||||
));
|
||||
|
||||
quote!(mod resources {
|
||||
use rtic::export::Priority;
|
||||
|
||||
|
@ -104,5 +118,5 @@ pub fn codegen(
|
|||
})
|
||||
};
|
||||
|
||||
(const_app, mod_resources)
|
||||
(mod_app, mod_resources, mod_resources_imports)
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ pub fn codegen(
|
|||
let constructor = quote!(
|
||||
impl<#lt> #ident<#lt> {
|
||||
#[inline(always)]
|
||||
unsafe fn new(#arg) -> Self {
|
||||
pub unsafe fn new(#arg) -> Self {
|
||||
#ident {
|
||||
#(#values,)*
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
|
|||
|
||||
methods.push(quote!(
|
||||
#(#cfgs)*
|
||||
fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
|
||||
pub fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
|
||||
#body
|
||||
}
|
||||
));
|
||||
|
@ -49,7 +49,7 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
|
|||
|
||||
items.push(quote!(
|
||||
#(#cfgs)*
|
||||
unsafe fn #schedule(
|
||||
pub unsafe fn #schedule(
|
||||
priority: &rtic::export::Priority,
|
||||
instant: #instant
|
||||
#(,#args)*
|
||||
|
@ -62,7 +62,7 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
|
|||
methods.push(quote!(
|
||||
#(#cfgs)*
|
||||
#[inline(always)]
|
||||
fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
|
||||
pub fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
|
||||
unsafe {
|
||||
#schedule(self.priority(), instant #(,#untupled)*)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use quote::{format_ident, quote};
|
||||
use rtic_syntax::{ast::App, Context};
|
||||
|
||||
use crate::{
|
||||
|
@ -13,7 +13,7 @@ pub fn codegen(
|
|||
analysis: &Analysis,
|
||||
extra: &Extra,
|
||||
) -> (
|
||||
// const_app_software_tasks -- free queues, buffers and `${task}Resources` constructors
|
||||
// mod_app_software_tasks -- free queues, buffers and `${task}Resources` constructors
|
||||
Vec<TokenStream2>,
|
||||
// root_software_tasks -- items that must be placed in the root of the crate:
|
||||
// - `${task}Locals` structs
|
||||
|
@ -22,10 +22,13 @@ pub fn codegen(
|
|||
Vec<TokenStream2>,
|
||||
// user_software_tasks -- the `#[task]` functions written by the user
|
||||
Vec<TokenStream2>,
|
||||
// user_software_tasks_imports -- the imports for `#[task]` functions written by the user
|
||||
Vec<TokenStream2>,
|
||||
) {
|
||||
let mut const_app = vec![];
|
||||
let mut mod_app = vec![];
|
||||
let mut root = vec![];
|
||||
let mut user_tasks = vec![];
|
||||
let mut software_tasks_imports = vec![];
|
||||
|
||||
for (name, task) in &app.software_tasks {
|
||||
let inputs = &task.inputs;
|
||||
|
@ -48,7 +51,7 @@ pub fn codegen(
|
|||
Box::new(|| util::link_section_uninit(true)),
|
||||
)
|
||||
};
|
||||
const_app.push(quote!(
|
||||
mod_app.push(quote!(
|
||||
/// Queue version of a free-list that keeps track of empty slots in
|
||||
/// the following buffers
|
||||
static mut #fq: #fq_ty = #fq_expr;
|
||||
|
@ -56,13 +59,13 @@ pub fn codegen(
|
|||
|
||||
// Generate a resource proxy if needed
|
||||
if let Some(ceiling) = ceiling {
|
||||
const_app.push(quote!(
|
||||
mod_app.push(quote!(
|
||||
struct #fq<'a> {
|
||||
priority: &'a rtic::export::Priority,
|
||||
}
|
||||
));
|
||||
|
||||
const_app.push(util::impl_mutex(
|
||||
mod_app.push(util::impl_mutex(
|
||||
extra,
|
||||
&[],
|
||||
false,
|
||||
|
@ -82,7 +85,7 @@ pub fn codegen(
|
|||
let instants = util::instants_ident(name);
|
||||
|
||||
let uninit = mk_uninit();
|
||||
const_app.push(quote!(
|
||||
mod_app.push(quote!(
|
||||
#uninit
|
||||
/// Buffer that holds the instants associated to the inputs of a task
|
||||
static mut #instants:
|
||||
|
@ -93,7 +96,7 @@ pub fn codegen(
|
|||
|
||||
let uninit = mk_uninit();
|
||||
let inputs = util::inputs_ident(name);
|
||||
const_app.push(quote!(
|
||||
mod_app.push(quote!(
|
||||
#uninit
|
||||
/// Buffer that holds the inputs of a task
|
||||
static mut #inputs: [core::mem::MaybeUninit<#input_ty>; #cap_lit] =
|
||||
|
@ -112,9 +115,16 @@ pub fn codegen(
|
|||
analysis,
|
||||
);
|
||||
|
||||
// Add resources to imports
|
||||
let name_res = format_ident!("{}Resources", name);
|
||||
software_tasks_imports.push(quote!(
|
||||
#[allow(non_snake_case)]
|
||||
use super::#name_res;
|
||||
));
|
||||
|
||||
root.push(item);
|
||||
|
||||
const_app.push(constructor);
|
||||
mod_app.push(constructor);
|
||||
}
|
||||
|
||||
// `${task}Locals`
|
||||
|
@ -135,12 +145,17 @@ pub fn codegen(
|
|||
#(#attrs)*
|
||||
#(#cfgs)*
|
||||
#[allow(non_snake_case)]
|
||||
fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) {
|
||||
pub fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) {
|
||||
use rtic::Mutex as _;
|
||||
|
||||
#(#stmts)*
|
||||
}
|
||||
));
|
||||
software_tasks_imports.push(quote!(
|
||||
#(#cfgs)*
|
||||
#[allow(non_snake_case)]
|
||||
use super::#name;
|
||||
));
|
||||
|
||||
root.push(module::codegen(
|
||||
Context::SoftwareTask(name),
|
||||
|
@ -150,5 +165,5 @@ pub fn codegen(
|
|||
));
|
||||
}
|
||||
|
||||
(const_app, root, user_tasks)
|
||||
(mod_app, root, user_tasks, software_tasks_imports)
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
|||
|
||||
methods.push(quote!(
|
||||
#(#cfgs)*
|
||||
fn #name(&self #(,#args)*) -> Result<(), #ty> {
|
||||
pub fn #name(&self #(,#args)*) -> Result<(), #ty> {
|
||||
#let_instant
|
||||
#body
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
|||
methods.push(quote!(
|
||||
#(#cfgs)*
|
||||
#[inline(always)]
|
||||
fn #name(&self #(,#args)*) -> Result<(), #ty> {
|
||||
pub fn #name(&self #(,#args)*) -> Result<(), #ty> {
|
||||
unsafe {
|
||||
#let_instant
|
||||
#spawn(self.priority() #instant #(,#untupled)*)
|
||||
|
|
|
@ -15,8 +15,7 @@ mod tests;
|
|||
|
||||
/// Attribute used to declare a RTIC application
|
||||
///
|
||||
/// This attribute must be applied to a `const` item of type `()`. The `const` item is effectively
|
||||
/// used as a `mod` item: its value must be a block that contains items commonly found in modules,
|
||||
/// This attribute must be applied to a module block that contains items commonly found in modules,
|
||||
/// like functions and `static` variables.
|
||||
///
|
||||
/// The `app` attribute has one mandatory argument:
|
||||
|
@ -34,9 +33,10 @@ mod tests;
|
|||
/// - `monotonic = <path>`. This is a path to a zero-sized structure (e.g. `struct Foo;`) that
|
||||
/// implements the `Monotonic` trait. This argument must be provided to use the `schedule` API.
|
||||
///
|
||||
/// The items allowed in the block value of the `const` item are specified below:
|
||||
/// The items allowed in the module block are specified below:
|
||||
///
|
||||
/// # 1. `struct Resources`
|
||||
/// # 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
|
||||
|
|
|
@ -8,7 +8,7 @@ fn analyze() {
|
|||
let (app, analysis) = rtic_syntax::parse2(
|
||||
quote!(device = pac),
|
||||
quote!(
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[task(priority = 1)]
|
||||
fn a(_: a::Context) {}
|
||||
|
||||
|
@ -20,7 +20,7 @@ fn analyze() {
|
|||
fn B();
|
||||
fn A();
|
||||
}
|
||||
};
|
||||
}
|
||||
),
|
||||
settings,
|
||||
)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![no_main]
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[task(binds = NonMaskableInt)]
|
||||
fn nmi(_: nmi::Context) {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#![no_main]
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[task(binds = SysTick)]
|
||||
fn sys_tick(_: sys_tick::Context) {}
|
||||
|
||||
#[task(schedule = [foo])]
|
||||
fn foo(_: foo::Context) {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![no_main]
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[task]
|
||||
fn a(_: a::Context) {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#![no_main]
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[task(binds = UART0)]
|
||||
fn a(_: a::Context) {}
|
||||
|
||||
extern "C" {
|
||||
fn UART0();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#![no_main]
|
||||
use panic_halt as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
#[cfg(never)]
|
||||
|
@ -47,4 +48,4 @@ const APP: () = {
|
|||
extern "C" {
|
||||
fn UART1();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,37 +1,41 @@
|
|||
error[E0425]: cannot find value `FOO` in this scope
|
||||
--> $DIR/locals-cfg.rs:10:9
|
||||
--> $DIR/locals-cfg.rs:11:9
|
||||
|
|
||||
10 | FOO;
|
||||
11 | FOO;
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error[E0425]: cannot find value `FOO` in this scope
|
||||
--> $DIR/locals-cfg.rs:18:9
|
||||
--> $DIR/locals-cfg.rs:19:9
|
||||
|
|
||||
18 | FOO;
|
||||
19 | FOO;
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error[E0425]: cannot find value `FOO` in this scope
|
||||
--> $DIR/locals-cfg.rs:28:9
|
||||
--> $DIR/locals-cfg.rs:29:9
|
||||
|
|
||||
28 | FOO;
|
||||
29 | FOO;
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error[E0425]: cannot find value `FOO` in this scope
|
||||
--> $DIR/locals-cfg.rs:36:9
|
||||
--> $DIR/locals-cfg.rs:37:9
|
||||
|
|
||||
36 | FOO;
|
||||
37 | FOO;
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error[E0425]: cannot find value `FOO` in this scope
|
||||
--> $DIR/locals-cfg.rs:44:9
|
||||
--> $DIR/locals-cfg.rs:45:9
|
||||
|
|
||||
44 | FOO;
|
||||
45 | FOO;
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error: duplicate lang item in crate `panic_halt` (which `$CRATE` depends on): `panic_impl`.
|
||||
|
|
||||
= note: the lang item is first defined in crate `std` (which `$CRATE` depends on)
|
||||
= note: first definition in `std` loaded from /usr/share/rust/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-cf0f33af3a901778.rlib
|
||||
= note: second definition in `panic_halt` loaded from $DIR/target/tests/target/x86_64-unknown-linux-gnu/debug/deps/libpanic_halt-ba6f0ab3439cbc7e.rmeta
|
||||
|
||||
error: duplicate lang item in crate `panic_semihosting`: `panic_impl`.
|
||||
|
|
||||
= note: first defined in crate `std`.
|
||||
|
||||
error: duplicate lang item in crate `panic_halt`: `panic_impl`.
|
||||
|
|
||||
= note: first defined in crate `panic_semihosting`.
|
||||
= note: the lang item is first defined in crate `panic_halt` (which `$CRATE` depends on)
|
||||
= note: first definition in `panic_halt` loaded from $DIR/target/tests/target/x86_64-unknown-linux-gnu/debug/deps/libpanic_halt-ba6f0ab3439cbc7e.rmeta
|
||||
= note: second definition in `panic_semihosting` loaded from $DIR/target/tests/target/x86_64-unknown-linux-gnu/debug/deps/libpanic_semihosting-805015f4a2d05965.rmeta
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#![no_main]
|
||||
use panic_halt as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[resources]
|
||||
struct Resources {
|
||||
#[cfg(never)]
|
||||
#[init(0)]
|
||||
|
@ -72,4 +74,4 @@ const APP: () = {
|
|||
c.resources.s2;
|
||||
c.resources.o5;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,119 +1,125 @@
|
|||
error: duplicate lang item in crate `panic_halt` (which `$CRATE` depends on): `panic_impl`.
|
||||
|
|
||||
= note: the lang item is first defined in crate `std` (which `$CRATE` depends on)
|
||||
= note: first definition in `std` loaded from /usr/share/rust/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-cf0f33af3a901778.rlib
|
||||
= note: second definition in `panic_halt` loaded from $DIR/target/tests/target/x86_64-unknown-linux-gnu/debug/deps/libpanic_halt-ba6f0ab3439cbc7e.rmeta
|
||||
|
||||
error[E0609]: no field `o1` on type `initResources<'_>`
|
||||
--> $DIR/resources-cfg.rs:45:21
|
||||
--> $DIR/resources-cfg.rs:47:21
|
||||
|
|
||||
45 | c.resources.o1;
|
||||
47 | c.resources.o1;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `o4` on type `initResources<'_>`
|
||||
--> $DIR/resources-cfg.rs:46:21
|
||||
--> $DIR/resources-cfg.rs:48:21
|
||||
|
|
||||
46 | c.resources.o4;
|
||||
48 | c.resources.o4;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `o5` on type `initResources<'_>`
|
||||
--> $DIR/resources-cfg.rs:47:21
|
||||
--> $DIR/resources-cfg.rs:49:21
|
||||
|
|
||||
47 | c.resources.o5;
|
||||
49 | c.resources.o5;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `o6` on type `initResources<'_>`
|
||||
--> $DIR/resources-cfg.rs:48:21
|
||||
--> $DIR/resources-cfg.rs:50:21
|
||||
|
|
||||
48 | c.resources.o6;
|
||||
50 | c.resources.o6;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `s3` on type `initResources<'_>`
|
||||
--> $DIR/resources-cfg.rs:49:21
|
||||
--> $DIR/resources-cfg.rs:51:21
|
||||
|
|
||||
49 | c.resources.s3;
|
||||
51 | c.resources.s3;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `o2` on type `idleResources<'_>`
|
||||
--> $DIR/resources-cfg.rs:54:21
|
||||
--> $DIR/resources-cfg.rs:56:21
|
||||
|
|
||||
54 | c.resources.o2;
|
||||
56 | c.resources.o2;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `o4` on type `idleResources<'_>`
|
||||
--> $DIR/resources-cfg.rs:55:21
|
||||
--> $DIR/resources-cfg.rs:57:21
|
||||
|
|
||||
55 | c.resources.o4;
|
||||
57 | c.resources.o4;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `s1` on type `idleResources<'_>`
|
||||
--> $DIR/resources-cfg.rs:56:21
|
||||
--> $DIR/resources-cfg.rs:58:21
|
||||
|
|
||||
56 | c.resources.s1;
|
||||
58 | c.resources.s1;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `s3` on type `idleResources<'_>`
|
||||
--> $DIR/resources-cfg.rs:57:21
|
||||
--> $DIR/resources-cfg.rs:59:21
|
||||
|
|
||||
57 | c.resources.s3;
|
||||
59 | c.resources.s3;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `o3` on type `uart0Resources<'_>`
|
||||
--> $DIR/resources-cfg.rs:64:21
|
||||
--> $DIR/resources-cfg.rs:66:21
|
||||
|
|
||||
64 | c.resources.o3;
|
||||
66 | c.resources.o3;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `s1` on type `uart0Resources<'_>`
|
||||
--> $DIR/resources-cfg.rs:65:21
|
||||
--> $DIR/resources-cfg.rs:67:21
|
||||
|
|
||||
65 | c.resources.s1;
|
||||
67 | c.resources.s1;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `s2` on type `uart0Resources<'_>`
|
||||
--> $DIR/resources-cfg.rs:66:21
|
||||
--> $DIR/resources-cfg.rs:68:21
|
||||
|
|
||||
66 | c.resources.s2;
|
||||
68 | c.resources.s2;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `s3` on type `uart0Resources<'_>`
|
||||
--> $DIR/resources-cfg.rs:67:21
|
||||
--> $DIR/resources-cfg.rs:69:21
|
||||
|
|
||||
67 | c.resources.s3;
|
||||
69 | c.resources.s3;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `s2` on type `uart1Resources<'_>`
|
||||
--> $DIR/resources-cfg.rs:72:21
|
||||
--> $DIR/resources-cfg.rs:74:21
|
||||
|
|
||||
72 | c.resources.s2;
|
||||
74 | c.resources.s2;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
||||
error[E0609]: no field `o5` on type `uart1Resources<'_>`
|
||||
--> $DIR/resources-cfg.rs:73:21
|
||||
--> $DIR/resources-cfg.rs:75:21
|
||||
|
|
||||
73 | c.resources.o5;
|
||||
75 | c.resources.o5;
|
||||
| ^^ unknown field
|
||||
|
|
||||
= note: available fields are: `__marker__`
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#![no_main]
|
||||
|
||||
use rtic::app;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
mod app {
|
||||
#[init]
|
||||
fn init(_: init::Context) {}
|
||||
|
||||
|
@ -35,4 +33,4 @@ const APP: () = {
|
|||
// this value is too high!
|
||||
#[task(binds = I2C0, priority = 9)]
|
||||
fn i2c0(_: i2c0::Context) {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
warning: unused import: `rtic::app`
|
||||
--> $DIR/task-priority-too-high.rs:3:5
|
||||
|
|
||||
3 | use rtic::app;
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: #[warn(unused_imports)] on by default
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/task-priority-too-high.rs:5:1
|
||||
--> $DIR/task-priority-too-high.rs:3:1
|
||||
|
|
||||
5 | #[rtic::app(device = lm3s6965)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
|
||||
3 | #[rtic::app(device = lm3s6965)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `8_usize - 9_usize` which would overflow
|
||||
|
|
||||
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
|
Loading…
Reference in a new issue