mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-29 15:04:32 +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
|
- x86_64-unknown-linux-gnu
|
||||||
toolchain:
|
toolchain:
|
||||||
- stable
|
- stable
|
||||||
- 1.36.0
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
@ -79,10 +78,6 @@ jobs:
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Disable optimisation profiles
|
|
||||||
if: matrix.toolchain == '1.36.0'
|
|
||||||
run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml
|
|
||||||
|
|
||||||
- name: cargo check
|
- name: cargo check
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
|
@ -306,7 +301,6 @@ jobs:
|
||||||
- x86_64-unknown-linux-gnu
|
- x86_64-unknown-linux-gnu
|
||||||
toolchain:
|
toolchain:
|
||||||
- stable
|
- stable
|
||||||
- 1.36.0
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
@ -340,10 +334,6 @@ jobs:
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Disable optimisation profiles
|
|
||||||
if: matrix.toolchain == '1.36.0'
|
|
||||||
run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml
|
|
||||||
|
|
||||||
- name: cargo check
|
- name: cargo check
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
|
@ -382,13 +372,10 @@ jobs:
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: 1.36.0
|
toolchain: stable
|
||||||
target: thumbv7m-none-eabi
|
target: thumbv7m-none-eabi
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Disable optimisation profiles
|
|
||||||
run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml
|
|
||||||
|
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
use-cross: false
|
use-cross: false
|
||||||
|
@ -426,13 +413,10 @@ jobs:
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: 1.36.0
|
toolchain: stable
|
||||||
target: thumbv6m-none-eabi
|
target: thumbv6m-none-eabi
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Disable optimisation profiles
|
|
||||||
run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml
|
|
||||||
|
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
use-cross: false
|
use-cross: false
|
||||||
|
|
|
@ -9,7 +9,7 @@ is required to follow along.
|
||||||
|
|
||||||
[repository]: https://github.com/rtic-rs/cortex-m-rtic
|
[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
|
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.
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ This is the smallest possible RTIC application:
|
||||||
```
|
```
|
||||||
|
|
||||||
All RTIC applications use the [`app`] attribute (`#[app(..)]`). This attribute
|
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
|
a mandatory `device` argument that takes a *path* as a value. This path must
|
||||||
point to a *peripheral access crate* (PAC) generated using [`svd2rust`]
|
point to a *peripheral access crate* (PAC) generated using [`svd2rust`]
|
||||||
**v0.14.x** or newer. The `app` attribute will expand into a suitable entry
|
**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
|
[`svd2rust`]: https://crates.io/crates/svd2rust
|
||||||
[`cortex_m_rt::entry`]: ../../../api/cortex_m_rt_macros/attr.entry.html
|
[`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`
|
## `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
|
function marked with the `init` attribute. This function must have signature
|
||||||
`fn(init::Context) [-> init::LateResources]` (the return type is not always
|
`fn(init::Context) [-> init::LateResources]` (the return type is not always
|
||||||
required).
|
required).
|
||||||
|
@ -62,7 +55,7 @@ $ cargo run --example init
|
||||||
## `idle`
|
## `idle`
|
||||||
|
|
||||||
A function marked with the `idle` attribute can optionally appear in the
|
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) - > !`.
|
signature `fn(idle::Context) - > !`.
|
||||||
|
|
||||||
When present, the runtime will execute the `idle` task after `init`. Unlike
|
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.
|
we saw in the previous section (task handlers, `init` and `idle`): resources.
|
||||||
|
|
||||||
Resources are data visible only to functions declared within the `#[app]`
|
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.
|
can access which resource.
|
||||||
|
|
||||||
All resources are declared as a single `struct` within the `#[app]`
|
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]`
|
Resources can optionally be given an initial value using the `#[init]`
|
||||||
attribute. Resources that are not given an initial value are referred to as
|
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
|
*late* resources and are covered in more detail in a follow-up section in this
|
||||||
|
|
|
@ -95,7 +95,7 @@ following snippet:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtic::app(..)]
|
#[rtic::app(..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init(spawn = [foo, bar])]
|
#[init(spawn = [foo, bar])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
cx.spawn.foo().unwrap();
|
cx.spawn.foo().unwrap();
|
||||||
|
@ -116,5 +116,5 @@ const APP: () = {
|
||||||
fn bar(cx: bar::Context, payload: i32) {
|
fn bar(cx: bar::Context, payload: i32) {
|
||||||
// ..
|
// ..
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -143,7 +143,7 @@ $ tail target/rtic-expansion.rs
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[doc = r" Implementation details"]
|
#[doc = r" Implementation details"]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[doc = r" Always include the device crate which contains the vector table"]
|
#[doc = r" Always include the device crate which contains the vector table"]
|
||||||
use lm3s6965 as _;
|
use lm3s6965 as _;
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -156,7 +156,7 @@ const APP: () = {
|
||||||
rtic::export::wfi()
|
rtic::export::wfi()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Or, you can use the [`cargo-expand`] sub-command. This sub-command will expand
|
Or, you can use the [`cargo-expand`] sub-command. This sub-command will expand
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Types, Send and Sync
|
# 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,
|
first parameter. All the fields of these structures have predictable,
|
||||||
non-anonymous types so you can write plain functions that take them as arguments.
|
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
|
static variables (resources) that they have specified in their RTIC attribute
|
||||||
the RTIC framework performs a source code level transformation. This
|
the RTIC framework performs a source code level transformation. This
|
||||||
transformation consists of placing the resources (static variables) specified by
|
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.
|
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
|
Access to the resources is then given to each task using a `Resources` struct
|
||||||
|
@ -29,7 +29,7 @@ happens behind the scenes:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
static mut X: u64: 0;
|
static mut X: u64: 0;
|
||||||
static mut Y: bool: 0;
|
static mut Y: bool: 0;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ..
|
// ..
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The framework produces codes like this:
|
The framework produces codes like this:
|
||||||
|
@ -103,8 +103,8 @@ pub mod bar {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation details
|
/// Implementation details
|
||||||
const APP: () = {
|
mod app {
|
||||||
// everything inside this `const` item is hidden from user code
|
// everything inside this module is hidden from user code
|
||||||
|
|
||||||
static mut X: u64 = 0;
|
static mut X: u64 = 0;
|
||||||
static mut Y: bool = 0;
|
static mut Y: bool = 0;
|
||||||
|
@ -154,5 +154,5 @@ const APP: () = {
|
||||||
// ..
|
// ..
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -28,7 +28,7 @@ An example to illustrate the ceiling analysis:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
// accessed by `foo` (prio = 1) and `bar` (prio = 2)
|
// accessed by `foo` (prio = 1) and `bar` (prio = 2)
|
||||||
// -> CEILING = 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
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mut app {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
x: u64,
|
x: u64,
|
||||||
|
@ -57,7 +57,7 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ..
|
// ..
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now let's see how these types are created by the framework.
|
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;
|
static mut x: u64 = 0;
|
||||||
|
|
||||||
impl rtic::Mutex for resources::x {
|
impl rtic::Mutex for resources::x {
|
||||||
|
@ -129,7 +129,7 @@ const APP: () = {
|
||||||
// ..
|
// ..
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `lock`
|
## `lock`
|
||||||
|
@ -225,7 +225,7 @@ Consider this program:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
x: u64,
|
x: u64,
|
||||||
|
@ -277,7 +277,7 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ..
|
// ..
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The code generated by the framework looks like this:
|
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;
|
use cortex_m::register::basepri;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -368,7 +368,7 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeat for resource `y`
|
// repeat for resource `y`
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
At the end the compiler will optimize the function `foo` into something like
|
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
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
x: u64,
|
x: u64,
|
||||||
|
@ -484,7 +484,7 @@ const APP: () = {
|
||||||
// ..
|
// ..
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
IMPORTANT: let's say we *forget* to roll back `BASEPRI` in `UART1` -- this would
|
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
|
``` rust
|
||||||
// code generated by RTIC
|
// code generated by RTIC
|
||||||
|
|
||||||
const APP: () = {
|
mod app {
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -513,7 +513,7 @@ const APP: () = {
|
||||||
// BUG: FORGOT to roll back the BASEPRI to the snapshot value we took before
|
// BUG: FORGOT to roll back the BASEPRI to the snapshot value we took before
|
||||||
basepri::write(initial);
|
basepri::write(initial);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The consequence is that `idle` will run at a dynamic priority of `2` and in fact
|
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
|
``` rust
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
// .. user code ..
|
// .. user code ..
|
||||||
|
@ -28,7 +28,7 @@ const APP: () = {
|
||||||
fn foo(c: foo::Context) {
|
fn foo(c: foo::Context) {
|
||||||
// .. user code ..
|
// .. user code ..
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The framework generates an entry point that looks like this:
|
The framework generates an entry point that looks like this:
|
||||||
|
|
|
@ -10,7 +10,7 @@ initialize late resources.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
x: Thing,
|
x: Thing,
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ..
|
// ..
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The code generated by the framework looks like this:
|
The code generated by the framework looks like this:
|
||||||
|
@ -69,7 +69,7 @@ pub mod foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation details
|
/// Implementation details
|
||||||
const APP: () = {
|
mod app {
|
||||||
// uninitialized static
|
// uninitialized static
|
||||||
static mut x: MaybeUninit<Thing> = MaybeUninit::uninit();
|
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
|
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
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(c: init::Context) { .. }
|
fn init(c: init::Context) { .. }
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ const APP: () = {
|
||||||
// in aliasing of the static variable `X`
|
// in aliasing of the static variable `X`
|
||||||
unsafe { UART0() }
|
unsafe { UART0() }
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The RTIC framework must generate the interrupt handler code that calls the user
|
The RTIC framework must generate the interrupt handler code that calls the user
|
||||||
|
@ -57,7 +57,7 @@ fn bar(c: bar::Context) {
|
||||||
// .. user code ..
|
// .. user code ..
|
||||||
}
|
}
|
||||||
|
|
||||||
const APP: () = {
|
mod app {
|
||||||
// everything in this block is not visible to user code
|
// everything in this block is not visible to user code
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -69,7 +69,7 @@ const APP: () = {
|
||||||
unsafe fn USART1() {
|
unsafe fn USART1() {
|
||||||
bar(..);
|
bar(..);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## By hardware
|
## By hardware
|
||||||
|
|
|
@ -28,7 +28,7 @@ Consider this example:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
#[interrupt(binds = UART0, priority = 2, spawn = [bar, baz])]
|
#[interrupt(binds = UART0, priority = 2, spawn = [bar, baz])]
|
||||||
|
@ -51,7 +51,7 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn UART1();
|
fn UART1();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The framework produces the following task dispatcher which consists of an
|
The framework produces the following task dispatcher which consists of an
|
||||||
|
@ -62,7 +62,7 @@ fn bar(c: bar::Context) {
|
||||||
// .. user code ..
|
// .. user code ..
|
||||||
}
|
}
|
||||||
|
|
||||||
const APP: () = {
|
mod app {
|
||||||
use heapless::spsc::Queue;
|
use heapless::spsc::Queue;
|
||||||
use cortex_m::register::basepri;
|
use cortex_m::register::basepri;
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ const APP: () = {
|
||||||
// BASEPRI invariant
|
// BASEPRI invariant
|
||||||
basepri::write(snapshot);
|
basepri::write(snapshot);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Spawning a task
|
## Spawning a task
|
||||||
|
@ -144,7 +144,7 @@ mod foo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const APP: () = {
|
mod app {
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
// Priority ceiling for the producer endpoint of the `RQ1`
|
// 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
|
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 ..
|
// .. user code ..
|
||||||
}
|
}
|
||||||
|
|
||||||
const APP: () = {
|
mod app {
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
// Now we show the full contents of the `Ready` struct
|
// 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:
|
And now let's look at the real implementation of the task dispatcher:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
const APP: () = {
|
mod app {
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -304,7 +304,7 @@ const APP: () = {
|
||||||
// BASEPRI invariant
|
// BASEPRI invariant
|
||||||
basepri::write(snapshot);
|
basepri::write(snapshot);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`INPUTS` plus `FQ`, the free queue, is effectively a memory pool. However,
|
`INPUTS` plus `FQ`, the free queue, is effectively a memory pool. However,
|
||||||
|
@ -357,7 +357,7 @@ Consider the following example:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[idle(spawn = [foo, bar])]
|
#[idle(spawn = [foo, bar])]
|
||||||
fn idle(c: idle::Context) -> ! {
|
fn idle(c: idle::Context) -> ! {
|
||||||
// ..
|
// ..
|
||||||
|
@ -382,7 +382,7 @@ const APP: () = {
|
||||||
fn quux(c: quux::Context) {
|
fn quux(c: quux::Context) {
|
||||||
// ..
|
// ..
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This is how the ceiling analysis would go:
|
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
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
#[task(capacity = 2, schedule = [foo])]
|
#[task(capacity = 2, schedule = [foo])]
|
||||||
|
@ -24,7 +24,7 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn UART0();
|
fn UART0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `schedule`
|
## `schedule`
|
||||||
|
@ -46,7 +46,7 @@ mod foo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const APP: () = {
|
mod app {
|
||||||
type Instant = <path::to::user::monotonic::timer as rtic::Monotonic>::Instant;
|
type Instant = <path::to::user::monotonic::timer as rtic::Monotonic>::Instant;
|
||||||
|
|
||||||
// all tasks that can be `schedule`-d
|
// 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
|
This looks very similar to the `Spawn` implementation. In fact, the same
|
||||||
|
@ -123,7 +123,7 @@ is up.
|
||||||
Let's see the associated code.
|
Let's see the associated code.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn SysTick() {
|
fn SysTick() {
|
||||||
const PRIORITY: u8 = 1;
|
const PRIORITY: u8 = 1;
|
||||||
|
@ -146,7 +146,7 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This looks similar to a task dispatcher except that instead of running the
|
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
|
## 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
|
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
|
tasks from running we choose the priority of the system timer to be the maximum
|
||||||
of all the `schedule`-able tasks.
|
of all the `schedule`-able tasks.
|
||||||
|
@ -222,7 +222,7 @@ To illustrate, consider the following example:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtic::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[task(priority = 3, spawn = [baz])]
|
#[task(priority = 3, spawn = [baz])]
|
||||||
fn foo(c: foo::Context) {
|
fn foo(c: foo::Context) {
|
||||||
// ..
|
// ..
|
||||||
|
@ -237,7 +237,7 @@ const APP: () = {
|
||||||
fn baz(c: baz::Context) {
|
fn baz(c: baz::Context) {
|
||||||
// ..
|
// ..
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The ceiling analysis would go like this:
|
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`.
|
`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
|
- `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
|
- `bar::Schedule` (prio = 2) has exclusive access over the consumer endpoint of
|
||||||
`foo_FQ`; thus the priority ceiling of `foo_FQ` is effectively `2`.
|
`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.
|
as part of the task context.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
const APP: () = {
|
mod app {
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -303,7 +303,7 @@ const APP: () = {
|
||||||
// BASEPRI invariant
|
// BASEPRI invariant
|
||||||
basepri::write(snapshot);
|
basepri::write(snapshot);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Conversely, the `spawn` implementation needs to write a value to the `INSTANTS`
|
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> {
|
impl<'a> foo::Spawn<'a> {
|
||||||
/// Spawns the `baz` task
|
/// Spawns the `baz` task
|
||||||
pub fn baz(&self, message: u64) -> Result<(), u64> {
|
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
|
This section covers how to upgrade an application written against RTIC v0.4.x to
|
||||||
the version v0.5.0 of the framework.
|
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
|
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.
|
`"0.5.0"`. The `timer-queue` feature needs to be removed.
|
||||||
|
|
||||||
|
|
||||||
``` toml
|
``` toml
|
||||||
[dependencies.cortex-m-rtic]
|
[dependencies.cortex-m-rtic]
|
||||||
# change this
|
# 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
|
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
|
`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`
|
The syntax used to declare resources has been changed from `static mut`
|
||||||
variables to a `struct Resources`.
|
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
|
If your application was accessing the device peripherals in `#[init]` through
|
||||||
the `device` variable then you'll need to add `peripherals = true` to the
|
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
|
The `#[interrupt]` and `#[exception]` attributes have been removed. To declare
|
||||||
hardware tasks in v0.5.x use the `#[task]` attribute with the `binds` argument.
|
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
|
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`
|
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
|
[Russian]: ../ru/index.html
|
||||||
|
|
||||||
This is the documentation of v0.5.x of RTIC; for the documentation of version
|
This is the documentation of v0.6.x of RTIC; for the documentation of version
|
||||||
v0.4.x go [here](/0.4).
|
|
||||||
|
* v0.5.x go [here](/0.5).
|
||||||
|
* v0.4.x go [here](/0.4).
|
||||||
|
|
||||||
{{#include ../../../README.md:7:46}}
|
{{#include ../../../README.md:7:46}}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use panic_semihosting as _;
|
||||||
|
|
||||||
// NOTE: does NOT properly work on QEMU
|
// NOTE: does NOT properly work on QEMU
|
||||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init(spawn = [foo])]
|
#[init(spawn = [foo])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
// omitted: initialization of `CYCCNT`
|
// omitted: initialization of `CYCCNT`
|
||||||
|
@ -51,4 +51,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use panic_semihosting as _;
|
||||||
|
|
||||||
// `examples/interrupt.rs` rewritten to use `binds`
|
// `examples/interrupt.rs` rewritten to use `binds`
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtic::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
|
@ -45,4 +45,4 @@ const APP: () = {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtic::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
|
@ -44,4 +44,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -11,7 +11,8 @@ use cortex_m_semihosting::hprintln;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[cfg(debug_assertions)] // <- `true` when using the `dev` profile
|
#[cfg(debug_assertions)] // <- `true` when using the `dev` profile
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -66,4 +67,4 @@ const APP: () = {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
fn QEI0();
|
fn QEI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@ use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
// Some resources to work with
|
// Some resources to work with
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -44,4 +45,4 @@ const APP: () = {
|
||||||
|
|
||||||
hprintln!("UART0: a = {}, b = {}, c = {}", a, b, c).unwrap();
|
hprintln!("UART0: a = {}, b = {}, c = {}", a, b, c).unwrap();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -9,7 +9,9 @@ use panic_semihosting as _;
|
||||||
use rtic::cyccnt::U32Ext;
|
use rtic::cyccnt::U32Ext;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
nothing: (),
|
nothing: (),
|
||||||
}
|
}
|
||||||
|
@ -34,4 +36,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -11,7 +11,8 @@ use panic_semihosting as _;
|
||||||
use rtic::{Exclusive, Mutex};
|
use rtic::{Exclusive, Mutex};
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
shared: u32,
|
shared: u32,
|
||||||
|
@ -49,7 +50,7 @@ const APP: () = {
|
||||||
// second argument has type `Exclusive<u32>`
|
// second argument has type `Exclusive<u32>`
|
||||||
advance(STATE, Exclusive(c.resources.shared));
|
advance(STATE, Exclusive(c.resources.shared));
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// the second parameter is generic: it can be any type that implements the `Mutex` trait
|
// 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>) {
|
fn advance(state: &mut u32, mut shared: impl Mutex<T = u32>) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
// Pends the UART0 interrupt but its handler won't run until *after*
|
// Pends the UART0 interrupt but its handler won't run until *after*
|
||||||
|
@ -49,4 +49,4 @@ const APP: () = {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
hprintln!("init").unwrap();
|
hprintln!("init").unwrap();
|
||||||
|
@ -30,4 +30,4 @@ const APP: () = {
|
||||||
cortex_m::asm::nop();
|
cortex_m::asm::nop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965, peripherals = true)]
|
#[rtic::app(device = lm3s6965, peripherals = true)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
static mut X: u32 = 0;
|
static mut X: u32 = 0;
|
||||||
|
@ -31,4 +31,4 @@ const APP: () = {
|
||||||
|
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -15,8 +15,13 @@ use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
use heapless::{
|
||||||
|
consts::*,
|
||||||
|
spsc::{Consumer, Producer},
|
||||||
|
};
|
||||||
// Late resources
|
// Late resources
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
p: Producer<'static, u32, U4>,
|
p: Producer<'static, u32, U4>,
|
||||||
c: Consumer<'static, u32, U4>,
|
c: Consumer<'static, u32, U4>,
|
||||||
|
@ -49,4 +54,4 @@ const APP: () = {
|
||||||
fn uart0(c: uart0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
c.resources.p.enqueue(42).unwrap();
|
c.resources.p.enqueue(42).unwrap();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@ use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
shared: u32,
|
shared: u32,
|
||||||
|
@ -59,4 +60,4 @@ const APP: () = {
|
||||||
fn gpioc(_: gpioc::Context) {
|
fn gpioc(_: gpioc::Context) {
|
||||||
hprintln!("C").unwrap();
|
hprintln!("C").unwrap();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init(spawn = [foo])]
|
#[init(spawn = [foo])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
c.spawn.foo(/* no message */).unwrap();
|
c.spawn.foo(/* no message */).unwrap();
|
||||||
|
@ -49,4 +49,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -16,7 +16,10 @@ pub struct NotSend {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[app(device = lm3s6965)]
|
#[app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
use super::NotSend;
|
||||||
|
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(None)]
|
#[init(None)]
|
||||||
shared: Option<NotSend>,
|
shared: Option<NotSend>,
|
||||||
|
@ -60,4 +63,4 @@ const APP: () = {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
fn QEI0();
|
fn QEI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -15,7 +15,11 @@ pub struct NotSync {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
use super::NotSync;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(NotSync { _0: PhantomData })]
|
#[init(NotSync { _0: PhantomData })]
|
||||||
shared: NotSync,
|
shared: NotSync,
|
||||||
|
@ -42,4 +46,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@ use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
key: u32,
|
key: u32,
|
||||||
}
|
}
|
||||||
|
@ -35,4 +36,4 @@ const APP: () = {
|
||||||
fn uart1(cx: uart1::Context) {
|
fn uart1(cx: uart1::Context) {
|
||||||
hprintln!("UART1(key = {:#x})", cx.resources.key).unwrap();
|
hprintln!("UART1(key = {:#x})", cx.resources.key).unwrap();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ const PERIOD: u32 = 8_000_000;
|
||||||
|
|
||||||
// NOTE: does NOT work on QEMU!
|
// NOTE: does NOT work on QEMU!
|
||||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
|
||||||
#[init(schedule = [foo])]
|
#[init(schedule = [foo])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
// omitted: initialization of `CYCCNT`
|
// omitted: initialization of `CYCCNT`
|
||||||
|
@ -35,4 +36,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -7,10 +7,10 @@ use cortex_m_semihosting::debug;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn main(_: main::Context) {
|
fn taskmain(_: taskmain::Context) {
|
||||||
assert!(cortex_m::Peripherals::take().is_none());
|
assert!(cortex_m::Peripherals::take().is_none());
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -18,7 +18,12 @@ use rtic::app;
|
||||||
pool!(P: [u8; 128]);
|
pool!(P: [u8; 128]);
|
||||||
|
|
||||||
#[app(device = lm3s6965)]
|
#[app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
use crate::Box;
|
||||||
|
|
||||||
|
// Import the memory pool into scope
|
||||||
|
use super::P;
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
static mut MEMORY: [u8; 512] = [0; 512];
|
static mut MEMORY: [u8; 512] = [0; 512];
|
||||||
|
@ -66,4 +71,4 @@ const APP: () = {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
fn QEI0();
|
fn QEI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use panic_semihosting as _;
|
||||||
use rtic::app;
|
use rtic::app;
|
||||||
|
|
||||||
#[app(device = lm3s6965)]
|
#[app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtic::pend(Interrupt::GPIOA);
|
rtic::pend(Interrupt::GPIOA);
|
||||||
|
@ -34,4 +34,4 @@ const APP: () = {
|
||||||
rtic::pend(Interrupt::GPIOB);
|
rtic::pend(Interrupt::GPIOB);
|
||||||
hprintln!(" GPIOC - end").unwrap();
|
hprintln!(" GPIOC - end").unwrap();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init(spawn = [bar])]
|
#[init(spawn = [bar])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
c.spawn.bar().unwrap();
|
c.spawn.bar().unwrap();
|
||||||
|
@ -38,4 +38,4 @@ const APP: () = {
|
||||||
#[link_section = ".data.UART1"]
|
#[link_section = ".data.UART1"]
|
||||||
fn 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 _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
// A resource
|
// A resource
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -52,4 +53,4 @@ const APP: () = {
|
||||||
|
|
||||||
hprintln!("UART1: shared = {}", cx.resources.shared).unwrap();
|
hprintln!("UART1: shared = {}", cx.resources.shared).unwrap();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ use rtic::cyccnt::{Instant, U32Ext as _};
|
||||||
|
|
||||||
// NOTE: does NOT work on QEMU!
|
// NOTE: does NOT work on QEMU!
|
||||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init(schedule = [foo, bar])]
|
#[init(schedule = [foo, bar])]
|
||||||
fn init(mut cx: init::Context) {
|
fn init(mut cx: init::Context) {
|
||||||
// Initialize (enable) the monotonic timer (CYCCNT)
|
// Initialize (enable) the monotonic timer (CYCCNT)
|
||||||
|
@ -50,4 +50,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -13,7 +13,10 @@ use rtic::app;
|
||||||
pub struct MustBeSend;
|
pub struct MustBeSend;
|
||||||
|
|
||||||
#[app(device = lm3s6965)]
|
#[app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
use super::MustBeSend;
|
||||||
|
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(None)]
|
#[init(None)]
|
||||||
shared: Option<MustBeSend>,
|
shared: Option<MustBeSend>,
|
||||||
|
@ -37,4 +40,4 @@ const APP: () = {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -7,4 +7,4 @@ use panic_semihosting as _; // panic handler
|
||||||
use rtic::app;
|
use rtic::app;
|
||||||
|
|
||||||
#[app(device = lm3s6965)]
|
#[app(device = lm3s6965)]
|
||||||
const APP: () = {};
|
mod app {}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {}
|
fn init(_: init::Context) {}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ const APP: () = {
|
||||||
fn bar(c: bar::Context) {
|
fn bar(c: bar::Context) {
|
||||||
bar_trampoline(c)
|
bar_trampoline(c)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn foo_trampoline(_: foo::Context) {}
|
fn foo_trampoline(_: foo::Context) {}
|
||||||
|
|
|
@ -6,19 +6,17 @@
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
// A resource
|
// A resource
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
shared: u32,
|
shared: u32,
|
||||||
|
|
||||||
// A conditionally compiled resource behind feature_x
|
// A conditionally compiled resource behind feature_x
|
||||||
#[cfg(feature = "feature_x")]
|
#[cfg(feature = "feature_x")]
|
||||||
x: u32,
|
x: u32,
|
||||||
|
dummy: (), // dummy such that we have at least one late resource
|
||||||
dummy: (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) -> init::LateResources {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
init::LateResources {
|
init::LateResources {
|
||||||
|
@ -35,4 +33,4 @@ const APP: () = {
|
||||||
cortex_m::asm::nop();
|
cortex_m::asm::nop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[cfg(never)]
|
#[cfg(never)]
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -52,4 +53,4 @@ const APP: () = {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
fn QEI0();
|
fn QEI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -7,14 +7,14 @@ use cortex_m_semihosting::debug;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtic::pend(lm3s6965::Interrupt::UART0)
|
rtic::pend(lm3s6965::Interrupt::UART0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = UART0)]
|
#[task(binds = UART0)]
|
||||||
fn main(_: main::Context) {
|
fn taskmain(_: taskmain::Context) {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -7,15 +7,15 @@ use cortex_m_semihosting::debug;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {}
|
fn init(_: init::Context) {}
|
||||||
|
|
||||||
#[idle]
|
#[idle]
|
||||||
fn main(_: main::Context) -> ! {
|
fn taskmain(_: taskmain::Context) -> ! {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
loop {
|
loop {
|
||||||
cortex_m::asm::nop();
|
cortex_m::asm::nop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ use cortex_m_semihosting::debug;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn main(_: main::Context) {
|
fn taskmain(_: taskmain::Context) {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -12,7 +12,10 @@ pub struct NotSend {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
use super::NotSend;
|
||||||
|
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
x: NotSend,
|
x: NotSend,
|
||||||
#[init(None)]
|
#[init(None)]
|
||||||
|
@ -35,4 +38,4 @@ const APP: () = {
|
||||||
cortex_m::asm::nop();
|
cortex_m::asm::nop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
o1: u32, // init
|
o1: u32, // init
|
||||||
|
@ -86,4 +87,4 @@ const APP: () = {
|
||||||
// no `Mutex` proxy when co-owned by cooperative (same priority) tasks
|
// no `Mutex` proxy when co-owned by cooperative (same priority) tasks
|
||||||
let _: &mut u32 = c.resources.s2;
|
let _: &mut u32 = c.resources.s2;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use panic_halt as _;
|
||||||
use rtic::cyccnt::{Instant, U32Ext as _};
|
use rtic::cyccnt::{Instant, U32Ext as _};
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init(schedule = [foo, bar, baz])]
|
#[init(schedule = [foo, bar, baz])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
let _: Result<(), ()> = c.schedule.foo(c.start + 10.cycles());
|
let _: Result<(), ()> = c.schedule.foo(c.start + 10.cycles());
|
||||||
|
@ -61,4 +61,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init(spawn = [foo, bar, baz])]
|
#[init(spawn = [foo, bar, baz])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
let _: Result<(), ()> = c.spawn.foo();
|
let _: Result<(), ()> = c.spawn.foo();
|
||||||
|
@ -60,4 +60,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -7,14 +7,14 @@ use cortex_m_semihosting::debug;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init(spawn = [main])]
|
#[init(spawn = [taskmain])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
cx.spawn.main().ok();
|
cx.spawn.taskmain().ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task]
|
#[task]
|
||||||
fn main(_: main::Context) {
|
fn taskmain(_: taskmain::Context) {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,4 +24,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init(spawn = [foo])]
|
#[init(spawn = [foo])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
c.spawn.foo().unwrap();
|
c.spawn.foo().unwrap();
|
||||||
|
@ -52,4 +52,4 @@ const APP: () = {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
fn QEI0();
|
fn QEI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@ use panic_semihosting as _;
|
||||||
use rtic::cyccnt;
|
use rtic::cyccnt;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
shared: u32,
|
shared: u32,
|
||||||
|
@ -60,4 +61,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn SSI0();
|
fn SSI0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -25,21 +25,36 @@ mod util;
|
||||||
|
|
||||||
// TODO document the syntax here or in `rtic-syntax`
|
// TODO document the syntax here or in `rtic-syntax`
|
||||||
pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
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 mains = vec![];
|
||||||
let mut root = vec![];
|
let mut root = vec![];
|
||||||
let mut user = vec![];
|
let mut user = vec![];
|
||||||
|
let mut imports = vec![];
|
||||||
|
|
||||||
// Generate the `main` function
|
// Generate the `main` function
|
||||||
let assertion_stmts = assertions::codegen(analysis);
|
let assertion_stmts = assertions::codegen(analysis);
|
||||||
|
|
||||||
let pre_init_stmts = pre_init::codegen(&app, analysis, extra);
|
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 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.push(quote!(
|
||||||
#user_init
|
#user_init
|
||||||
|
@ -47,16 +62,21 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
#user_idle
|
#user_idle
|
||||||
));
|
));
|
||||||
|
|
||||||
|
imports.push(quote!(
|
||||||
|
#(#user_init_imports)*
|
||||||
|
#(#user_idle_imports)*
|
||||||
|
));
|
||||||
|
|
||||||
root.push(quote!(
|
root.push(quote!(
|
||||||
#(#root_init)*
|
#(#root_init)*
|
||||||
|
|
||||||
#(#root_idle)*
|
#(#root_idle)*
|
||||||
));
|
));
|
||||||
|
|
||||||
const_app.push(quote!(
|
mod_app.push(quote!(
|
||||||
#const_app_init
|
#mod_app_init
|
||||||
|
|
||||||
#const_app_idle
|
#mod_app_idle
|
||||||
));
|
));
|
||||||
|
|
||||||
let main = util::suffixed("main");
|
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) =
|
let (
|
||||||
hardware_tasks::codegen(app, analysis, extra);
|
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) =
|
let (
|
||||||
software_tasks::codegen(app, analysis, extra);
|
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 name = &app.name;
|
||||||
let device = extra.device;
|
let device = extra.device;
|
||||||
quote!(
|
quote!(
|
||||||
|
@ -111,28 +142,41 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
#(#root_software_tasks)*
|
#(#root_software_tasks)*
|
||||||
|
|
||||||
/// Implementation details
|
/// Implementation details
|
||||||
// The user can't access the items within this `const` item
|
mod #name {
|
||||||
const #name: () = {
|
|
||||||
/// Always include the device crate which contains the vector table
|
/// Always include the device crate which contains the vector table
|
||||||
use #device as _;
|
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)*
|
#(#mains)*
|
||||||
};
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::{format_ident, quote};
|
||||||
use rtic_syntax::{ast::App, Context};
|
use rtic_syntax::{ast::App, Context};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -14,7 +14,7 @@ pub fn codegen(
|
||||||
analysis: &Analysis,
|
analysis: &Analysis,
|
||||||
extra: &Extra,
|
extra: &Extra,
|
||||||
) -> (
|
) -> (
|
||||||
// const_app_hardware_tasks -- interrupt handlers and `${task}Resources` constructors
|
// mod_app_hardware_tasks -- interrupt handlers and `${task}Resources` constructors
|
||||||
Vec<TokenStream2>,
|
Vec<TokenStream2>,
|
||||||
// root_hardware_tasks -- items that must be placed in the root of the crate:
|
// root_hardware_tasks -- items that must be placed in the root of the crate:
|
||||||
// - `${task}Locals` structs
|
// - `${task}Locals` structs
|
||||||
|
@ -23,10 +23,13 @@ pub fn codegen(
|
||||||
Vec<TokenStream2>,
|
Vec<TokenStream2>,
|
||||||
// user_hardware_tasks -- the `#[task]` functions written by the user
|
// user_hardware_tasks -- the `#[task]` functions written by the user
|
||||||
Vec<TokenStream2>,
|
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 root = vec![];
|
||||||
let mut user_tasks = vec![];
|
let mut user_tasks = vec![];
|
||||||
|
let mut hardware_tasks_imports = vec![];
|
||||||
|
|
||||||
for (name, task) in &app.hardware_tasks {
|
for (name, task) in &app.hardware_tasks {
|
||||||
let (let_instant, instant) = if app.uses_schedule() {
|
let (let_instant, instant) = if app.uses_schedule() {
|
||||||
|
@ -49,7 +52,7 @@ pub fn codegen(
|
||||||
let symbol = task.args.binds.clone();
|
let symbol = task.args.binds.clone();
|
||||||
let priority = task.args.priority;
|
let priority = task.args.priority;
|
||||||
|
|
||||||
const_app.push(quote!(
|
mod_app.push(quote!(
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe fn #symbol() {
|
unsafe fn #symbol() {
|
||||||
|
@ -78,9 +81,16 @@ pub fn codegen(
|
||||||
analysis,
|
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);
|
root.push(item);
|
||||||
|
|
||||||
const_app.push(constructor);
|
mod_app.push(constructor);
|
||||||
}
|
}
|
||||||
|
|
||||||
root.push(module::codegen(
|
root.push(module::codegen(
|
||||||
|
@ -112,7 +122,13 @@ pub fn codegen(
|
||||||
#(#stmts)*
|
#(#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 proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::{format_ident, quote};
|
||||||
use rtic_syntax::{ast::App, Context};
|
use rtic_syntax::{ast::App, Context};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -14,7 +14,7 @@ pub fn codegen(
|
||||||
analysis: &Analysis,
|
analysis: &Analysis,
|
||||||
extra: &Extra,
|
extra: &Extra,
|
||||||
) -> (
|
) -> (
|
||||||
// const_app_idle -- the `${idle}Resources` constructor
|
// mod_app_idle -- the `${idle}Resources` constructor
|
||||||
Option<TokenStream2>,
|
Option<TokenStream2>,
|
||||||
// root_idle -- items that must be placed in the root of the crate:
|
// root_idle -- items that must be placed in the root of the crate:
|
||||||
// - the `${idle}Locals` struct
|
// - the `${idle}Locals` struct
|
||||||
|
@ -23,26 +23,37 @@ pub fn codegen(
|
||||||
Vec<TokenStream2>,
|
Vec<TokenStream2>,
|
||||||
// user_idle
|
// user_idle
|
||||||
Option<TokenStream2>,
|
Option<TokenStream2>,
|
||||||
|
// user_idle_imports
|
||||||
|
Vec<TokenStream2>,
|
||||||
// call_idle
|
// call_idle
|
||||||
TokenStream2,
|
TokenStream2,
|
||||||
) {
|
) {
|
||||||
if app.idles.len() > 0 {
|
if app.idles.len() > 0 {
|
||||||
let idle = &app.idles.first().unwrap();
|
let idle = &app.idles.first().unwrap();
|
||||||
let mut needs_lt = false;
|
let mut needs_lt = false;
|
||||||
let mut const_app = None;
|
let mut mod_app = None;
|
||||||
let mut root_idle = vec![];
|
let mut root_idle = vec![];
|
||||||
let mut locals_pat = None;
|
let mut locals_pat = None;
|
||||||
let mut locals_new = None;
|
let mut locals_new = None;
|
||||||
|
|
||||||
|
let mut user_idle_imports = vec![];
|
||||||
|
|
||||||
|
let name = &idle.name;
|
||||||
|
|
||||||
if !idle.args.resources.is_empty() {
|
if !idle.args.resources.is_empty() {
|
||||||
let (item, constructor) =
|
let (item, constructor) =
|
||||||
resources_struct::codegen(Context::Idle, 0, &mut needs_lt, app, analysis);
|
resources_struct::codegen(Context::Idle, 0, &mut needs_lt, app, analysis);
|
||||||
|
|
||||||
root_idle.push(item);
|
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() {
|
if !idle.locals.is_empty() {
|
||||||
let (locals, pat) = locals::codegen(Context::Idle, &idle.locals, app);
|
let (locals, pat) = locals::codegen(Context::Idle, &idle.locals, app);
|
||||||
|
|
||||||
|
@ -66,6 +77,11 @@ pub fn codegen(
|
||||||
#(#stmts)*
|
#(#stmts)*
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
user_idle_imports.push(quote!(
|
||||||
|
#(#attrs)*
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
use super::#name;
|
||||||
|
));
|
||||||
|
|
||||||
let locals_new = locals_new.iter();
|
let locals_new = locals_new.iter();
|
||||||
let call_idle = quote!(crate::#name(
|
let call_idle = quote!(crate::#name(
|
||||||
|
@ -73,12 +89,13 @@ pub fn codegen(
|
||||||
#name::Context::new(&rtic::export::Priority::new(0))
|
#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 {
|
} else {
|
||||||
(
|
(
|
||||||
None,
|
None,
|
||||||
vec![],
|
vec![],
|
||||||
None,
|
None,
|
||||||
|
vec![],
|
||||||
quote!(loop {
|
quote!(loop {
|
||||||
rtic::export::wfi()
|
rtic::export::wfi()
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::{format_ident, quote};
|
||||||
use rtic_syntax::{ast::App, Context};
|
use rtic_syntax::{ast::App, Context};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -14,7 +14,7 @@ pub fn codegen(
|
||||||
analysis: &Analysis,
|
analysis: &Analysis,
|
||||||
extra: &Extra,
|
extra: &Extra,
|
||||||
) -> (
|
) -> (
|
||||||
// const_app_idle -- the `${init}Resources` constructor
|
// mod_app_idle -- the `${init}Resources` constructor
|
||||||
Option<TokenStream2>,
|
Option<TokenStream2>,
|
||||||
// root_init -- items that must be placed in the root of the crate:
|
// root_init -- items that must be placed in the root of the crate:
|
||||||
// - the `${init}Locals` struct
|
// - the `${init}Locals` struct
|
||||||
|
@ -24,6 +24,8 @@ pub fn codegen(
|
||||||
Vec<TokenStream2>,
|
Vec<TokenStream2>,
|
||||||
// user_init -- the `#[init]` function written by the user
|
// user_init -- the `#[init]` function written by the user
|
||||||
Option<TokenStream2>,
|
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
|
// call_init -- the call to the user `#[init]` if there's one
|
||||||
Option<TokenStream2>,
|
Option<TokenStream2>,
|
||||||
) {
|
) {
|
||||||
|
@ -34,6 +36,8 @@ pub fn codegen(
|
||||||
|
|
||||||
let mut root_init = vec![];
|
let mut root_init = vec![];
|
||||||
|
|
||||||
|
let mut user_init_imports = vec![];
|
||||||
|
|
||||||
let ret = {
|
let ret = {
|
||||||
let late_fields = analysis
|
let late_fields = analysis
|
||||||
.late_resources
|
.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))
|
Some(quote!(-> #name::LateResources))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -89,14 +99,25 @@ pub fn codegen(
|
||||||
#(#stmts)*
|
#(#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() {
|
if !init.args.resources.is_empty() {
|
||||||
let (item, constructor) =
|
let (item, constructor) =
|
||||||
resources_struct::codegen(Context::Init, 0, &mut needs_lt, app, analysis);
|
resources_struct::codegen(Context::Init, 0, &mut needs_lt, app, analysis);
|
||||||
|
|
||||||
root_init.push(item);
|
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();
|
let locals_new = locals_new.iter();
|
||||||
|
@ -106,8 +127,8 @@ pub fn codegen(
|
||||||
|
|
||||||
root_init.push(module::codegen(Context::Init, needs_lt, app, extra));
|
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 {
|
} else {
|
||||||
(None, vec![], None, None)
|
(None, vec![], None, vec![], None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,16 @@ pub fn codegen(
|
||||||
analysis: &Analysis,
|
analysis: &Analysis,
|
||||||
extra: &Extra,
|
extra: &Extra,
|
||||||
) -> (
|
) -> (
|
||||||
// const_app -- the `static [mut]` variables behind the proxies
|
// mod_app -- the `static [mut]` variables behind the proxies
|
||||||
Vec<TokenStream2>,
|
Vec<TokenStream2>,
|
||||||
// mod_resources -- the `resources` module
|
// mod_resources -- the `resources` module
|
||||||
TokenStream2,
|
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 = vec![];
|
||||||
|
let mut mod_resources_imports = vec![];
|
||||||
|
|
||||||
for (name, res, expr, _) in app.resources(analysis) {
|
for (name, res, expr, _) in app.resources(analysis) {
|
||||||
let cfgs = &res.cfgs;
|
let cfgs = &res.cfgs;
|
||||||
|
@ -39,7 +42,7 @@ pub fn codegen(
|
||||||
};
|
};
|
||||||
|
|
||||||
let attrs = &res.attrs;
|
let attrs = &res.attrs;
|
||||||
const_app.push(quote!(
|
mod_app.push(quote!(
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#(#cfgs)*
|
#(#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,
|
extra,
|
||||||
cfgs,
|
cfgs,
|
||||||
true,
|
true,
|
||||||
|
@ -97,6 +106,11 @@ pub fn codegen(
|
||||||
let mod_resources = if mod_resources.is_empty() {
|
let mod_resources = if mod_resources.is_empty() {
|
||||||
quote!()
|
quote!()
|
||||||
} else {
|
} else {
|
||||||
|
// Also import the resource module
|
||||||
|
mod_resources_imports.push(quote!(
|
||||||
|
use super::resources;
|
||||||
|
));
|
||||||
|
|
||||||
quote!(mod resources {
|
quote!(mod resources {
|
||||||
use rtic::export::Priority;
|
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!(
|
let constructor = quote!(
|
||||||
impl<#lt> #ident<#lt> {
|
impl<#lt> #ident<#lt> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
unsafe fn new(#arg) -> Self {
|
pub unsafe fn new(#arg) -> Self {
|
||||||
#ident {
|
#ident {
|
||||||
#(#values,)*
|
#(#values,)*
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
|
||||||
|
|
||||||
methods.push(quote!(
|
methods.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
|
pub fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
|
||||||
#body
|
#body
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
@ -49,7 +49,7 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
|
||||||
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
unsafe fn #schedule(
|
pub unsafe fn #schedule(
|
||||||
priority: &rtic::export::Priority,
|
priority: &rtic::export::Priority,
|
||||||
instant: #instant
|
instant: #instant
|
||||||
#(,#args)*
|
#(,#args)*
|
||||||
|
@ -62,7 +62,7 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
|
||||||
methods.push(quote!(
|
methods.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
|
pub fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
|
||||||
unsafe {
|
unsafe {
|
||||||
#schedule(self.priority(), instant #(,#untupled)*)
|
#schedule(self.priority(), instant #(,#untupled)*)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::{format_ident, quote};
|
||||||
use rtic_syntax::{ast::App, Context};
|
use rtic_syntax::{ast::App, Context};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -13,7 +13,7 @@ pub fn codegen(
|
||||||
analysis: &Analysis,
|
analysis: &Analysis,
|
||||||
extra: &Extra,
|
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>,
|
Vec<TokenStream2>,
|
||||||
// root_software_tasks -- items that must be placed in the root of the crate:
|
// root_software_tasks -- items that must be placed in the root of the crate:
|
||||||
// - `${task}Locals` structs
|
// - `${task}Locals` structs
|
||||||
|
@ -22,10 +22,13 @@ pub fn codegen(
|
||||||
Vec<TokenStream2>,
|
Vec<TokenStream2>,
|
||||||
// user_software_tasks -- the `#[task]` functions written by the user
|
// user_software_tasks -- the `#[task]` functions written by the user
|
||||||
Vec<TokenStream2>,
|
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 root = vec![];
|
||||||
let mut user_tasks = vec![];
|
let mut user_tasks = vec![];
|
||||||
|
let mut software_tasks_imports = vec![];
|
||||||
|
|
||||||
for (name, task) in &app.software_tasks {
|
for (name, task) in &app.software_tasks {
|
||||||
let inputs = &task.inputs;
|
let inputs = &task.inputs;
|
||||||
|
@ -48,7 +51,7 @@ pub fn codegen(
|
||||||
Box::new(|| util::link_section_uninit(true)),
|
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
|
/// Queue version of a free-list that keeps track of empty slots in
|
||||||
/// the following buffers
|
/// the following buffers
|
||||||
static mut #fq: #fq_ty = #fq_expr;
|
static mut #fq: #fq_ty = #fq_expr;
|
||||||
|
@ -56,13 +59,13 @@ pub fn codegen(
|
||||||
|
|
||||||
// Generate a resource proxy if needed
|
// Generate a resource proxy if needed
|
||||||
if let Some(ceiling) = ceiling {
|
if let Some(ceiling) = ceiling {
|
||||||
const_app.push(quote!(
|
mod_app.push(quote!(
|
||||||
struct #fq<'a> {
|
struct #fq<'a> {
|
||||||
priority: &'a rtic::export::Priority,
|
priority: &'a rtic::export::Priority,
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
const_app.push(util::impl_mutex(
|
mod_app.push(util::impl_mutex(
|
||||||
extra,
|
extra,
|
||||||
&[],
|
&[],
|
||||||
false,
|
false,
|
||||||
|
@ -82,7 +85,7 @@ pub fn codegen(
|
||||||
let instants = util::instants_ident(name);
|
let instants = util::instants_ident(name);
|
||||||
|
|
||||||
let uninit = mk_uninit();
|
let uninit = mk_uninit();
|
||||||
const_app.push(quote!(
|
mod_app.push(quote!(
|
||||||
#uninit
|
#uninit
|
||||||
/// Buffer that holds the instants associated to the inputs of a task
|
/// Buffer that holds the instants associated to the inputs of a task
|
||||||
static mut #instants:
|
static mut #instants:
|
||||||
|
@ -93,7 +96,7 @@ pub fn codegen(
|
||||||
|
|
||||||
let uninit = mk_uninit();
|
let uninit = mk_uninit();
|
||||||
let inputs = util::inputs_ident(name);
|
let inputs = util::inputs_ident(name);
|
||||||
const_app.push(quote!(
|
mod_app.push(quote!(
|
||||||
#uninit
|
#uninit
|
||||||
/// Buffer that holds the inputs of a task
|
/// Buffer that holds the inputs of a task
|
||||||
static mut #inputs: [core::mem::MaybeUninit<#input_ty>; #cap_lit] =
|
static mut #inputs: [core::mem::MaybeUninit<#input_ty>; #cap_lit] =
|
||||||
|
@ -112,9 +115,16 @@ pub fn codegen(
|
||||||
analysis,
|
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);
|
root.push(item);
|
||||||
|
|
||||||
const_app.push(constructor);
|
mod_app.push(constructor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// `${task}Locals`
|
// `${task}Locals`
|
||||||
|
@ -135,12 +145,17 @@ pub fn codegen(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#[allow(non_snake_case)]
|
#[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 _;
|
use rtic::Mutex as _;
|
||||||
|
|
||||||
#(#stmts)*
|
#(#stmts)*
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
software_tasks_imports.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
use super::#name;
|
||||||
|
));
|
||||||
|
|
||||||
root.push(module::codegen(
|
root.push(module::codegen(
|
||||||
Context::SoftwareTask(name),
|
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!(
|
methods.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
fn #name(&self #(,#args)*) -> Result<(), #ty> {
|
pub fn #name(&self #(,#args)*) -> Result<(), #ty> {
|
||||||
#let_instant
|
#let_instant
|
||||||
#body
|
#body
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
methods.push(quote!(
|
methods.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn #name(&self #(,#args)*) -> Result<(), #ty> {
|
pub fn #name(&self #(,#args)*) -> Result<(), #ty> {
|
||||||
unsafe {
|
unsafe {
|
||||||
#let_instant
|
#let_instant
|
||||||
#spawn(self.priority() #instant #(,#untupled)*)
|
#spawn(self.priority() #instant #(,#untupled)*)
|
||||||
|
|
|
@ -15,8 +15,7 @@ mod tests;
|
||||||
|
|
||||||
/// Attribute used to declare a RTIC application
|
/// Attribute used to declare a RTIC application
|
||||||
///
|
///
|
||||||
/// This attribute must be applied to a `const` item of type `()`. The `const` item is effectively
|
/// This attribute must be applied to a module block that contains items commonly found in modules,
|
||||||
/// used as a `mod` item: its value must be a block that contains items commonly found in modules,
|
|
||||||
/// like functions and `static` variables.
|
/// like functions and `static` variables.
|
||||||
///
|
///
|
||||||
/// The `app` attribute has one mandatory argument:
|
/// 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
|
/// - `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.
|
/// 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
|
/// 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
|
||||||
|
|
|
@ -8,7 +8,7 @@ fn analyze() {
|
||||||
let (app, analysis) = rtic_syntax::parse2(
|
let (app, analysis) = rtic_syntax::parse2(
|
||||||
quote!(device = pac),
|
quote!(device = pac),
|
||||||
quote!(
|
quote!(
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[task(priority = 1)]
|
#[task(priority = 1)]
|
||||||
fn a(_: a::Context) {}
|
fn a(_: a::Context) {}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ fn analyze() {
|
||||||
fn B();
|
fn B();
|
||||||
fn A();
|
fn A();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
),
|
),
|
||||||
settings,
|
settings,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[task(binds = NonMaskableInt)]
|
#[task(binds = NonMaskableInt)]
|
||||||
fn nmi(_: nmi::Context) {}
|
fn nmi(_: nmi::Context) {}
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[task(binds = SysTick)]
|
#[task(binds = SysTick)]
|
||||||
fn sys_tick(_: sys_tick::Context) {}
|
fn sys_tick(_: sys_tick::Context) {}
|
||||||
|
|
||||||
#[task(schedule = [foo])]
|
#[task(schedule = [foo])]
|
||||||
fn foo(_: foo::Context) {}
|
fn foo(_: foo::Context) {}
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[task]
|
#[task]
|
||||||
fn a(_: a::Context) {}
|
fn a(_: a::Context) {}
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[task(binds = UART0)]
|
#[task(binds = UART0)]
|
||||||
fn a(_: a::Context) {}
|
fn a(_: a::Context) {}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn UART0();
|
fn UART0();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
#[cfg(never)]
|
#[cfg(never)]
|
||||||
|
@ -47,4 +48,4 @@ const APP: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn UART1();
|
fn UART1();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,37 +1,41 @@
|
||||||
error[E0425]: cannot find value `FOO` in this scope
|
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
|
| ^^^ 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:18:9
|
--> $DIR/locals-cfg.rs:19:9
|
||||||
|
|
|
|
||||||
18 | FOO;
|
19 | 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:28:9
|
--> $DIR/locals-cfg.rs:29:9
|
||||||
|
|
|
|
||||||
28 | FOO;
|
29 | 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:36:9
|
--> $DIR/locals-cfg.rs:37:9
|
||||||
|
|
|
|
||||||
36 | FOO;
|
37 | 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:44:9
|
--> $DIR/locals-cfg.rs:45:9
|
||||||
|
|
|
|
||||||
44 | FOO;
|
45 | 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`.
|
||||||
|
|
|
||||||
|
= 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`.
|
error: duplicate lang item in crate `panic_semihosting`: `panic_impl`.
|
||||||
|
|
|
|
||||||
= note: first defined in crate `std`.
|
= 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
|
||||||
error: duplicate lang item in crate `panic_halt`: `panic_impl`.
|
= note: second definition in `panic_semihosting` loaded from $DIR/target/tests/target/x86_64-unknown-linux-gnu/debug/deps/libpanic_semihosting-805015f4a2d05965.rmeta
|
||||||
|
|
|
||||||
= note: first defined in crate `panic_semihosting`.
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
|
#[resources]
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[cfg(never)]
|
#[cfg(never)]
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -72,4 +74,4 @@ const APP: () = {
|
||||||
c.resources.s2;
|
c.resources.s2;
|
||||||
c.resources.o5;
|
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<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `o4` on type `initResources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `o5` on type `initResources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `o6` on type `initResources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `s3` on type `initResources<'_>`
|
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
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= 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:54:21
|
--> $DIR/resources-cfg.rs:56:21
|
||||||
|
|
|
|
||||||
54 | c.resources.o2;
|
56 | 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:55:21
|
--> $DIR/resources-cfg.rs:57:21
|
||||||
|
|
|
|
||||||
55 | c.resources.o4;
|
57 | 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:56:21
|
--> $DIR/resources-cfg.rs:58:21
|
||||||
|
|
|
|
||||||
56 | c.resources.s1;
|
58 | 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:57:21
|
--> $DIR/resources-cfg.rs:59:21
|
||||||
|
|
|
|
||||||
57 | c.resources.s3;
|
59 | 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:64:21
|
--> $DIR/resources-cfg.rs:66:21
|
||||||
|
|
|
|
||||||
64 | c.resources.o3;
|
66 | 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:65:21
|
--> $DIR/resources-cfg.rs:67:21
|
||||||
|
|
|
|
||||||
65 | c.resources.s1;
|
67 | 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:66:21
|
--> $DIR/resources-cfg.rs:68:21
|
||||||
|
|
|
|
||||||
66 | c.resources.s2;
|
68 | 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:67:21
|
--> $DIR/resources-cfg.rs:69:21
|
||||||
|
|
|
|
||||||
67 | c.resources.s3;
|
69 | 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:72:21
|
--> $DIR/resources-cfg.rs:74:21
|
||||||
|
|
|
|
||||||
72 | c.resources.s2;
|
74 | 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:73:21
|
--> $DIR/resources-cfg.rs:75:21
|
||||||
|
|
|
|
||||||
73 | c.resources.o5;
|
75 | c.resources.o5;
|
||||||
| ^^ unknown field
|
| ^^ unknown field
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use rtic::app;
|
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
mod app {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {}
|
fn init(_: init::Context) {}
|
||||||
|
|
||||||
|
@ -35,4 +33,4 @@ const APP: () = {
|
||||||
// this value is too high!
|
// this value is too high!
|
||||||
#[task(binds = I2C0, priority = 9)]
|
#[task(binds = I2C0, priority = 9)]
|
||||||
fn i2c0(_: i2c0::Context) {}
|
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
|
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)]
|
3 | #[rtic::app(device = lm3s6965)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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