mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-20 06:45:36 +01:00
Move deprecated migration guides to deprecated folder
This commit is contained in:
parent
ed465b0c3b
commit
3d97c9e431
11 changed files with 8 additions and 16 deletions
|
|
@ -23,11 +23,12 @@
|
|||
<!-- - [`#[cfg(..)]` support](./by-example/tips.md) -->
|
||||
- [RTIC vs. the world](./rtic_vs.md)
|
||||
- [Awesome RTIC examples](./awesome_rtic.md)
|
||||
<!-- - [Migration Guides](./migration.md)
|
||||
- [v1.0.x to v2.0.0](./migration/migration_v2.md)
|
||||
- [v0.5.x to v1.0.x](./migration/migration_v5.md)
|
||||
- [v0.4.x to v0.5.x](./migration/migration_v4.md)
|
||||
- [RTFM to RTIC](./migration/migration_rtic.md) -->
|
||||
- [Migrating from v1.0.x to v2.0.0](./migration_v1_v2.md)
|
||||
- [Rust Nightly & features](./migration_v1_v2/nightly.md)
|
||||
- [Migrating to `rtic-monotonics`](./migration_v1_v2/monotonics.md)
|
||||
- [Software tasks must now be `async`](./migration_v1_v2/async_tasks.md)
|
||||
- [Using and understanding `rtic-sync`](./migration_v1_v2/rtic-sync.md)
|
||||
- [A code example on migration](./migration_v1_v2/complete_example.md)
|
||||
- [Under the hood](./internals.md)
|
||||
- [Cortex-M architectures](./internals/targets.md)
|
||||
<!--- [Interrupt configuration](./internals/interrupt-configuration.md)-->
|
||||
|
|
@ -44,13 +45,4 @@
|
|||
- [Message passing & `capacity`](./by-example/message_passing.md)
|
||||
- [Task priorities](./by-example/app_priorities.md)
|
||||
- [Monotonic & `spawn_{at/after}`](./by-example/monotonic.md)
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
- [Migrating from v1.0.x to v2.0.0](./migration/migration_v2.md)
|
||||
- [Rust Nightly & features](./migration/migration_v2/nightly.md)
|
||||
- [Migrating to `rtic-monotonics`](./migration/migration_v2/monotonics.md)
|
||||
- [Software tasks must now be `async`](./migration/migration_v2/async_tasks.md)
|
||||
- [Using and understanding `rtic-sync`](./migration/migration_v2/rtic-sync.md)
|
||||
- [A code example on migration](./migration/migration_v2/complete_example.md)
|
||||
-->
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
# Migration Guides
|
||||
|
||||
This section describes how to migrate between different versions of RTIC.
|
||||
It also acts as a comparing reference between versions.
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
# Migrating from RTFM to RTIC
|
||||
|
||||
This section covers how to upgrade an application written against RTFM v0.5.x to
|
||||
the same version of RTIC. This applies since the renaming of the framework as per [RFC #33].
|
||||
|
||||
**Note:** There are no code differences between RTFM v0.5.3 and RTIC v0.5.3, it is purely a name
|
||||
change.
|
||||
|
||||
[RFC #33]: https://github.com/rtic-rs/rfcs/pull/33
|
||||
|
||||
## `Cargo.toml`
|
||||
|
||||
First, the `cortex-m-rtfm` dependency needs to be updated to
|
||||
`cortex-m-rtic`.
|
||||
|
||||
``` toml
|
||||
[dependencies]
|
||||
# change this
|
||||
cortex-m-rtfm = "0.5.3"
|
||||
|
||||
# into this
|
||||
cortex-m-rtic = "0.5.3"
|
||||
```
|
||||
|
||||
## Code changes
|
||||
|
||||
The only code change that needs to be made is that any reference to `rtfm` before now need to point
|
||||
to `rtic` as follows:
|
||||
|
||||
``` rust
|
||||
//
|
||||
// Change this
|
||||
//
|
||||
|
||||
#[rtfm::app(/* .. */, monotonic = rtfm::cyccnt::CYCCNT)]
|
||||
const APP: () = {
|
||||
// ...
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
// Into this
|
||||
//
|
||||
|
||||
#[rtic::app(/* .. */, monotonic = rtic::cyccnt::CYCCNT)]
|
||||
const APP: () = {
|
||||
// ...
|
||||
|
||||
};
|
||||
```
|
||||
|
|
@ -1,247 +0,0 @@
|
|||
# Migrating from v0.4.x to v0.5.0
|
||||
|
||||
This section covers how to upgrade an application written against RTFM v0.4.x to
|
||||
the version v0.5.0 of the framework.
|
||||
|
||||
## Project name change RTFM -> RTIC
|
||||
|
||||
With release [v0.5.2][rtic0.5.2] the name was change to Real-Time Interrupt-driven Concurrency
|
||||
|
||||
All occurrences of `RTFM` needs to change to `RTIC`.
|
||||
|
||||
See [migration guide RTFM to RTIC](./migration_rtic.md)
|
||||
|
||||
[rtic0.5.2]: https://crates.io/crates/cortex-m-rtic/0.5.2
|
||||
|
||||
## `Cargo.toml`
|
||||
|
||||
Change the version of `cortex-m-rtfm` to
|
||||
`"0.5.0"`, change `rtfm` to `rtic`.
|
||||
Remove the `timer-queue` feature.
|
||||
|
||||
``` toml
|
||||
[dependencies.cortex-m-rtfm]
|
||||
# change this
|
||||
version = "0.4.3"
|
||||
|
||||
# into this
|
||||
[dependencies.cortex-m-rtic]
|
||||
version = "0.5.0"
|
||||
|
||||
# and remove this Cargo feature
|
||||
features = ["timer-queue"]
|
||||
# ^^^^^^^^^^^^^
|
||||
```
|
||||
|
||||
## `Context` argument
|
||||
|
||||
All functions inside the `#[rtfm::app]` item need to take as first argument a
|
||||
`Context` structure. This `Context` type will contain the variables that were
|
||||
magically injected into the scope of the function by version v0.4.x of the
|
||||
framework: `resources`, `spawn`, `schedule` -- these variables will become
|
||||
fields of the `Context` structure. Each function within the `#[rtfm::app]` item
|
||||
gets a different `Context` type.
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */)]
|
||||
const APP: () = {
|
||||
// change this
|
||||
#[task(resources = [x], spawn = [a], schedule = [b])]
|
||||
fn foo() {
|
||||
resources.x.lock(|x| /* .. */);
|
||||
spawn.a(message);
|
||||
schedule.b(baseline);
|
||||
}
|
||||
|
||||
// into this
|
||||
#[task(resources = [x], spawn = [a], schedule = [b])]
|
||||
fn foo(mut cx: foo::Context) {
|
||||
// ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
cx.resources.x.lock(|x| /* .. */);
|
||||
// ^^^
|
||||
|
||||
cx.spawn.a(message);
|
||||
// ^^^
|
||||
|
||||
cx.schedule.b(message, baseline);
|
||||
// ^^^
|
||||
}
|
||||
|
||||
// change this
|
||||
#[init]
|
||||
fn init() {
|
||||
// ..
|
||||
}
|
||||
|
||||
// into this
|
||||
#[init]
|
||||
fn init(cx: init::Context) {
|
||||
// ^^^^^^^^^^^^^^^^^
|
||||
// ..
|
||||
}
|
||||
|
||||
// ..
|
||||
};
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
The syntax used to declare resources has changed from `static mut`
|
||||
variables to a `struct Resources`.
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */)]
|
||||
const APP: () = {
|
||||
// change this
|
||||
static mut X: u32 = 0;
|
||||
static mut Y: u32 = (); // late resource
|
||||
|
||||
// into this
|
||||
struct Resources {
|
||||
#[init(0)] // <- initial value
|
||||
X: u32, // NOTE: we suggest changing the naming style to `snake_case`
|
||||
|
||||
Y: u32, // late resource
|
||||
}
|
||||
|
||||
// ..
|
||||
};
|
||||
```
|
||||
|
||||
## Device peripherals
|
||||
|
||||
If your application was accessing the device peripherals in `#[init]` through
|
||||
the `device` variable then you'll need to add `peripherals = true` to the
|
||||
`#[rtfm::app]` attribute to continue to access the device peripherals through
|
||||
the `device` field of the `init::Context` structure.
|
||||
|
||||
Change this:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */)]
|
||||
const APP: () = {
|
||||
#[init]
|
||||
fn init() {
|
||||
device.SOME_PERIPHERAL.write(something);
|
||||
}
|
||||
|
||||
// ..
|
||||
};
|
||||
```
|
||||
|
||||
Into this:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */, peripherals = true)]
|
||||
// ^^^^^^^^^^^^^^^^^^
|
||||
const APP: () = {
|
||||
#[init]
|
||||
fn init(cx: init::Context) {
|
||||
// ^^^^^^^^^^^^^^^^^
|
||||
cx.device.SOME_PERIPHERAL.write(something);
|
||||
// ^^^
|
||||
}
|
||||
|
||||
// ..
|
||||
};
|
||||
```
|
||||
|
||||
## `#[interrupt]` and `#[exception]`
|
||||
|
||||
Remove the attributes `#[interrupt]` and `#[exception]`.
|
||||
To declare hardware tasks in v0.5.x use the `#[task]`
|
||||
attribute with the `binds` argument instead.
|
||||
|
||||
Change this:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */)]
|
||||
const APP: () = {
|
||||
// hardware tasks
|
||||
#[exception]
|
||||
fn SVCall() { /* .. */ }
|
||||
|
||||
#[interrupt]
|
||||
fn UART0() { /* .. */ }
|
||||
|
||||
// software task
|
||||
#[task]
|
||||
fn foo() { /* .. */ }
|
||||
|
||||
// ..
|
||||
};
|
||||
```
|
||||
|
||||
Into this:
|
||||
|
||||
``` rust
|
||||
#[rtfm::app(/* .. */)]
|
||||
const APP: () = {
|
||||
#[task(binds = SVCall)]
|
||||
// ^^^^^^^^^^^^^^
|
||||
fn svcall(cx: svcall::Context) { /* .. */ }
|
||||
// ^^^^^^ we suggest you use a `snake_case` name here
|
||||
|
||||
#[task(binds = UART0)]
|
||||
// ^^^^^^^^^^^^^
|
||||
fn uart0(cx: uart0::Context) { /* .. */ }
|
||||
|
||||
#[task]
|
||||
fn foo(cx: foo::Context) { /* .. */ }
|
||||
|
||||
// ..
|
||||
};
|
||||
```
|
||||
|
||||
## `schedule`
|
||||
|
||||
The `schedule` API no longer requires the `timer-queue` cargo feature.
|
||||
To use the `schedule` API one must first define the monotonic timer the
|
||||
runtime will use using the `monotonic` argument of the `#[rtfm::app]` attribute.
|
||||
To continue using the cycle counter (CYCCNT) as the monotonic timer,
|
||||
and match the behavior of version v0.4.x, add the `monotonic = rtfm::cyccnt::CYCCNT`
|
||||
argument to the `#[rtfm::app]` attribute.
|
||||
|
||||
Also, the `Duration` and `Instant` types and the `U32Ext` trait moved
|
||||
into the `rtfm::cyccnt` module.
|
||||
This module is only available on ARMv7-M+ devices.
|
||||
The removal of the `timer-queue` also brings back the `DWT` peripheral
|
||||
inside the core peripherals struct, if `DWT` is required,
|
||||
ensure it is enabled by the application inside `init`.
|
||||
|
||||
Change this:
|
||||
|
||||
``` rust
|
||||
use rtfm::{Duration, Instant, U32Ext};
|
||||
|
||||
#[rtfm::app(/* .. */)]
|
||||
const APP: () = {
|
||||
#[task(schedule = [b])]
|
||||
fn a() {
|
||||
// ..
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Into this:
|
||||
|
||||
``` rust
|
||||
use rtfm::cyccnt::{Duration, Instant, U32Ext};
|
||||
// ^^^^^^^^
|
||||
|
||||
#[rtfm::app(/* .. */, monotonic = rtfm::cyccnt::CYCCNT)]
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
const APP: () = {
|
||||
#[init]
|
||||
fn init(cx: init::Context) {
|
||||
cx.core.DWT.enable_cycle_counter();
|
||||
// optional, configure the DWT run without a debugger connected
|
||||
cx.core.DCB.enable_trace();
|
||||
}
|
||||
#[task(schedule = [b])]
|
||||
fn a(cx: a::Context) {
|
||||
// ..
|
||||
}
|
||||
};
|
||||
```
|
||||
|
|
@ -1,372 +0,0 @@
|
|||
# Migrating from v0.5.x to v1.0.0
|
||||
|
||||
This section describes how to upgrade from v0.5.x to v1.0.0 of the RTIC framework.
|
||||
|
||||
## `Cargo.toml` - version bump
|
||||
|
||||
Change the version of `cortex-m-rtic` to `"1.0.0"`.
|
||||
|
||||
## `mod` 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 used in user
|
||||
code must be moved inside `mod app`, or be referred to with `super`. For
|
||||
example, change:
|
||||
|
||||
```rust
|
||||
use some_crate::some_func;
|
||||
|
||||
#[rtic::app(/* .. */)]
|
||||
const APP: () = {
|
||||
fn func() {
|
||||
some_crate::some_func();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
into
|
||||
|
||||
```rust
|
||||
#[rtic::app(/* .. */)]
|
||||
mod app {
|
||||
use some_crate::some_func;
|
||||
|
||||
fn func() {
|
||||
some_crate::some_func();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```rust
|
||||
use some_crate::some_func;
|
||||
|
||||
#[rtic::app(/* .. */)]
|
||||
mod app {
|
||||
fn func() {
|
||||
super::some_crate::some_func();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Move Dispatchers from `extern "C"` to app arguments
|
||||
|
||||
Change
|
||||
|
||||
``` rust
|
||||
#[rtic::app(/* .. */)]
|
||||
const APP: () = {
|
||||
[code here]
|
||||
|
||||
// RTIC requires that unused interrupts are declared in an extern block when
|
||||
// using software tasks; these free interrupts will be used to dispatch the
|
||||
// software tasks.
|
||||
extern "C" {
|
||||
fn SSI0();
|
||||
fn QEI0();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
into
|
||||
|
||||
``` rust
|
||||
#[rtic::app(/* .. */, dispatchers = [SSI0, QEI0])]
|
||||
mod app {
|
||||
[code here]
|
||||
}
|
||||
```
|
||||
|
||||
This works also for ram functions, see examples/ramfunc.rs
|
||||
|
||||
|
||||
## Resources structs - `#[shared]`, `#[local]`
|
||||
|
||||
Previously the RTIC resources had to be in in a struct named exactly "Resources":
|
||||
|
||||
``` rust
|
||||
struct Resources {
|
||||
// Resources defined in here
|
||||
}
|
||||
```
|
||||
|
||||
With RTIC v1.0.0 the resources structs are annotated similarly like
|
||||
`#[task]`, `#[init]`, `#[idle]`: with the attributes `#[shared]` and `#[local]`
|
||||
|
||||
``` rust
|
||||
#[shared]
|
||||
struct MySharedResources {
|
||||
// Resources shared between tasks are defined here
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct MyLocalResources {
|
||||
// Resources defined here cannot be shared between tasks; each one is local to a single task
|
||||
}
|
||||
```
|
||||
|
||||
These structs can be freely named by the developer.
|
||||
|
||||
## `shared` and `local` arguments in `#[task]`s
|
||||
|
||||
In v1.0.0 resources are split between `shared` resources and `local` resources.
|
||||
`#[task]`, `#[init]` and `#[idle]` no longer have a `resources` argument; they must now use the `shared` and `local` arguments.
|
||||
|
||||
In v0.5.x:
|
||||
|
||||
``` rust
|
||||
struct Resources {
|
||||
local_to_b: i64,
|
||||
shared_by_a_and_b: i64,
|
||||
}
|
||||
|
||||
#[task(resources = [shared_by_a_and_b])]
|
||||
fn a(_: a::Context) {}
|
||||
|
||||
#[task(resources = [shared_by_a_and_b, local_to_b])]
|
||||
fn b(_: b::Context) {}
|
||||
```
|
||||
|
||||
In v1.0.0:
|
||||
|
||||
``` rust
|
||||
#[shared]
|
||||
struct Shared {
|
||||
shared_by_a_and_b: i64,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
local_to_b: i64,
|
||||
}
|
||||
|
||||
#[task(shared = [shared_by_a_and_b])]
|
||||
fn a(_: a::Context) {}
|
||||
|
||||
#[task(shared = [shared_by_a_and_b], local = [local_to_b])]
|
||||
fn b(_: b::Context) {}
|
||||
```
|
||||
|
||||
## Symmetric locks
|
||||
|
||||
Now RTIC utilizes symmetric locks, this means that the `lock` method need
|
||||
to be used for all `shared` resource access.
|
||||
In old code one could do the following as the high priority
|
||||
task has exclusive access to the resource:
|
||||
|
||||
``` rust
|
||||
#[task(priority = 2, resources = [r])]
|
||||
fn foo(cx: foo::Context) {
|
||||
cx.resources.r = /* ... */;
|
||||
}
|
||||
|
||||
#[task(resources = [r])]
|
||||
fn bar(cx: bar::Context) {
|
||||
cx.resources.r.lock(|r| r = /* ... */);
|
||||
}
|
||||
```
|
||||
|
||||
And with symmetric locks one needs to use locks in both tasks:
|
||||
|
||||
``` rust
|
||||
#[task(priority = 2, shared = [r])]
|
||||
fn foo(cx: foo::Context) {
|
||||
cx.shared.r.lock(|r| r = /* ... */);
|
||||
}
|
||||
|
||||
#[task(shared = [r])]
|
||||
fn bar(cx: bar::Context) {
|
||||
cx.shared.r.lock(|r| r = /* ... */);
|
||||
}
|
||||
```
|
||||
|
||||
Note that the performance does not change thanks to LLVM's optimizations which optimizes away unnecessary locks.
|
||||
|
||||
## Lock-free resource access
|
||||
|
||||
In RTIC 0.5 resources shared by tasks running at the same priority could be accessed *without* the `lock` API.
|
||||
This is still possible in 1.0: the `#[shared]` resource must be annotated with the field-level `#[lock_free]` attribute.
|
||||
|
||||
v0.5 code:
|
||||
|
||||
``` rust
|
||||
struct Resources {
|
||||
counter: u64,
|
||||
}
|
||||
|
||||
#[task(resources = [counter])]
|
||||
fn a(cx: a::Context) {
|
||||
*cx.resources.counter += 1;
|
||||
}
|
||||
|
||||
#[task(resources = [counter])]
|
||||
fn b(cx: b::Context) {
|
||||
*cx.resources.counter += 1;
|
||||
}
|
||||
```
|
||||
|
||||
v1.0 code:
|
||||
|
||||
``` rust
|
||||
#[shared]
|
||||
struct Shared {
|
||||
#[lock_free]
|
||||
counter: u64,
|
||||
}
|
||||
|
||||
#[task(shared = [counter])]
|
||||
fn a(cx: a::Context) {
|
||||
*cx.shared.counter += 1;
|
||||
}
|
||||
|
||||
#[task(shared = [counter])]
|
||||
fn b(cx: b::Context) {
|
||||
*cx.shared.counter += 1;
|
||||
}
|
||||
```
|
||||
|
||||
## no `static mut` transform
|
||||
|
||||
`static mut` variables are no longer transformed to safe `&'static mut` references.
|
||||
Instead of that syntax, use the `local` argument in `#[init]`.
|
||||
|
||||
v0.5.x code:
|
||||
|
||||
``` rust
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
static mut BUFFER: [u8; 1024] = [0; 1024];
|
||||
let buffer: &'static mut [u8; 1024] = BUFFER;
|
||||
}
|
||||
```
|
||||
|
||||
v1.0.0 code:
|
||||
|
||||
``` rust
|
||||
#[init(local = [
|
||||
buffer: [u8; 1024] = [0; 1024]
|
||||
// type ^^^^^^^^^^^^ ^^^^^^^^^ initial value
|
||||
])]
|
||||
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
|
||||
let buffer: &'static mut [u8; 1024] = cx.local.buffer;
|
||||
|
||||
(Shared {}, Local {}, init::Monotonics())
|
||||
}
|
||||
```
|
||||
|
||||
## Init always returns late resources
|
||||
|
||||
In order to make the API more symmetric the #[init]-task always returns a late resource.
|
||||
|
||||
From this:
|
||||
|
||||
``` rust
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
const APP: () = {
|
||||
#[init]
|
||||
fn init(_: init::Context) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
}
|
||||
|
||||
// [more code]
|
||||
};
|
||||
```
|
||||
|
||||
to this:
|
||||
|
||||
``` rust
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
#[shared]
|
||||
struct MySharedResources {}
|
||||
|
||||
#[local]
|
||||
struct MyLocalResources {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
(MySharedResources, MyLocalResources, init::Monotonics())
|
||||
}
|
||||
|
||||
// [more code]
|
||||
}
|
||||
```
|
||||
|
||||
## Spawn from anywhere
|
||||
|
||||
With the new spawn/spawn_after/spawn_at interface,
|
||||
old code requiring the context `cx` for spawning such as:
|
||||
|
||||
``` rust
|
||||
#[task(spawn = [bar])]
|
||||
fn foo(cx: foo::Context) {
|
||||
cx.spawn.bar().unwrap();
|
||||
}
|
||||
|
||||
#[task(schedule = [bar])]
|
||||
fn bar(cx: bar::Context) {
|
||||
cx.schedule.foo(/* ... */).unwrap();
|
||||
}
|
||||
```
|
||||
|
||||
Will now be written as:
|
||||
|
||||
``` rust
|
||||
#[task]
|
||||
fn foo(_c: foo::Context) {
|
||||
bar::spawn().unwrap();
|
||||
}
|
||||
|
||||
#[task]
|
||||
fn bar(_c: bar::Context) {
|
||||
// Takes a Duration, relative to “now”
|
||||
let spawn_handle = foo::spawn_after(/* ... */);
|
||||
}
|
||||
|
||||
#[task]
|
||||
fn bar(_c: bar::Context) {
|
||||
// Takes an Instant
|
||||
let spawn_handle = foo::spawn_at(/* ... */);
|
||||
}
|
||||
```
|
||||
|
||||
Thus the requirement of having access to the context is dropped.
|
||||
|
||||
Note that the attributes `spawn`/`schedule` in the task definition are no longer needed.
|
||||
|
||||
---
|
||||
|
||||
## Additions
|
||||
|
||||
### Extern tasks
|
||||
|
||||
Both software and hardware tasks can now be defined external to the `mod app`.
|
||||
Previously this was possible only by implementing a trampoline calling out the task implementation.
|
||||
|
||||
See examples `examples/extern_binds.rs` and `examples/extern_spawn.rs`.
|
||||
|
||||
This enables breaking apps into multiple files.
|
||||
|
|
@ -87,7 +87,7 @@ mod app {
|
|||
# V2.0.0
|
||||
|
||||
``` rust
|
||||
{{ #include ../../../../../examples/stm32f3_blinky/src/main.rs }}
|
||||
{{ #include ../../../../examples/stm32f3_blinky/src/main.rs }}
|
||||
```
|
||||
|
||||
## A diff between the two projects
|
||||
Loading…
Add table
Add a link
Reference in a new issue