Make RTIC 2 work on stable by using main's stack as an allocator

This commit is contained in:
Emil Fresk 2024-01-29 20:56:15 +01:00
parent d2e84799c7
commit 2798500957
66 changed files with 368 additions and 222 deletions

View file

@ -43,7 +43,7 @@ jobs:
- thumbv8-base - thumbv8-base
- thumbv8-main - thumbv8-main
toolchain: toolchain:
- nightly - stable
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -76,7 +76,7 @@ jobs:
- thumbv8-base - thumbv8-base
- thumbv8-main - thumbv8-main
toolchain: toolchain:
- nightly - stable
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -112,7 +112,7 @@ jobs:
- thumbv8-base - thumbv8-base
- thumbv8-main - thumbv8-main
toolchain: toolchain:
- nightly - stable
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -146,7 +146,7 @@ jobs:
strategy: strategy:
matrix: matrix:
toolchain: toolchain:
- nightly - stable
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -237,7 +237,7 @@ jobs:
- thumbv7 - thumbv7
- thumbv6 - thumbv6
toolchain: toolchain:
- nightly - stable
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4

View file

@ -28,7 +28,6 @@
--- ---
- [Migrating from v1.0.x to v2.0.0](./migration_v1_v2.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) - [Migrating to `rtic-monotonics`](./migration_v1_v2/monotonics.md)
- [Software tasks must now be `async`](./migration_v1_v2/async_tasks.md) - [Software tasks must now be `async`](./migration_v1_v2/async_tasks.md)
- [Using and understanding `rtic-sync`](./migration_v1_v2/rtic-sync.md) - [Using and understanding `rtic-sync`](./migration_v1_v2/rtic-sync.md)

View file

@ -2,7 +2,7 @@
Migrating a project from RTIC `v1.0.x` to `v2.0.0` involves the following steps: Migrating a project from RTIC `v1.0.x` to `v2.0.0` involves the following steps:
1. `v2.0.0` requires [`#![type_alias_impl_trait]`](https://github.com/rust-lang/rust/issues/63063) and Rust Nightly. 1. `v2.1.0` works on Rust Stable from 1.75 (**recommended**), while older versions require a `nightly` compiler via the use of [`#![type_alias_impl_trait]`](https://github.com/rust-lang/rust/issues/63063).
2. Migrating from the monotonics included in `v1.0.x` to `rtic-time` and `rtic-monotonics`, replacing `spawn_after`, `spawn_at`. 2. Migrating from the monotonics included in `v1.0.x` to `rtic-time` and `rtic-monotonics`, replacing `spawn_after`, `spawn_at`.
3. Software tasks are now required to be `async`, and using them correctly. 3. Software tasks are now required to be `async`, and using them correctly.
4. Understanding and using data types provided by `rtic-sync`. 4. Understanding and using data types provided by `rtic-sync`.
@ -12,7 +12,7 @@ For a detailed description of the changes, refer to the subchapters.
If you wish to see a code example of changes required, you can check out [the full example migration page](./migration_v1_v2/complete_example.md). If you wish to see a code example of changes required, you can check out [the full example migration page](./migration_v1_v2/complete_example.md).
#### TL;DR (Too Long; Didn't Read) #### TL;DR (Too Long; Didn't Read)
1. Add `#![type_alias_impl_trait]` to your crate, and use `cargo +nightly`.
2. Instead of `spawn_after` and `spawn_at`, you now use the `async` functions `delay`, `delay_until` (and related) with impls provided by `rtic-monotonics`. 1. Instead of `spawn_after` and `spawn_at`, you now use the `async` functions `delay`, `delay_until` (and related) with impls provided by `rtic-monotonics`.
3. Software tasks _must_ be `async fn`s now. Not returning from a task is allowed so long as there is an `await` in the task. You can still `lock` shared resources. 2. Software tasks _must_ be `async fn`s now. Not returning from a task is allowed so long as there is an `await` in the task. You can still `lock` shared resources.
4. Use `rtic_sync::arbiter::Arbiter` to `await` access to a shared resource, and `rtic_sync::channel::Channel` to communicate between tasks instead of `spawn`-ing new ones. 3. Use `rtic_sync::arbiter::Arbiter` to `await` access to a shared resource, and `rtic_sync::channel::Channel` to communicate between tasks instead of `spawn`-ing new ones.

View file

@ -97,7 +97,6 @@ _Note_: This diff may not be 100% accurate, but it displays the important change
``` diff ``` diff
#![no_main] #![no_main]
#![no_std] #![no_std]
+#![feature(type_alias_impl_trait)]
use panic_rtt_target as _; use panic_rtt_target as _;
use rtic::app; use rtic::app;

View file

@ -1,5 +0,0 @@
# RTIC now requires Rust Nightly
The new `async` features require that you use a nightly compiler, and that the feature `type_alias_impl_trait` is enabled for your applications.
To enable this feature, you must add the line `#![feature(type_alias_impl_trait)]` to the root file of your project, on the lines below or above where `#![no_std]` and `#![no_main]` are defined.

View file

@ -141,8 +141,6 @@ Asynchronous programming in various forms are getting increased popularity and l
The Rust standard library provides collections for dynamically allocated data-structures which are useful to manage execution contexts at run-time. However, in the setting of resource constrained real-time systems, dynamic allocations are problematic (both regarding performance and reliability - Rust runs into a *panic* on an out-of-memory condition). Thus, static allocation is the preferable approach! The Rust standard library provides collections for dynamically allocated data-structures which are useful to manage execution contexts at run-time. However, in the setting of resource constrained real-time systems, dynamic allocations are problematic (both regarding performance and reliability - Rust runs into a *panic* on an out-of-memory condition). Thus, static allocation is the preferable approach!
RTIC provides a mechanism for `async`/`await` that relies solely on static allocations. However, the implementation relies on the `#![feature(type_alias_impl_trait)]` (TAIT) which is undergoing stabilization (thus RTIC v2.x currently requires a *nightly* toolchain). Technically, using TAIT, the compiler determines the size of each execution context allowing static allocation.
From a modelling perspective `async/await` lifts the run-to-completion requirement of SRP, and each section of code between two yield points (`await`s) can be seen as an individual task. The compiler will reject any attempt to `await` while holding a resource (not doing so would break the strict LIFO requirement on resource usage under SRP). From a modelling perspective `async/await` lifts the run-to-completion requirement of SRP, and each section of code between two yield points (`await`s) can be seen as an individual task. The compiler will reject any attempt to `await` while holding a resource (not doing so would break the strict LIFO requirement on resource usage under SRP).
So with the technical stuff out of the way, what does `async/await` bring to the table? So with the technical stuff out of the way, what does `async/await` bring to the table?

View file

@ -2,7 +2,6 @@
#![deny(warnings)] #![deny(warnings)]
#![no_main] #![no_main]
#![no_std] #![no_std]
#![feature(type_alias_impl_trait)]
use nrf52840_blinky::hal; use nrf52840_blinky::hal;

View file

@ -2,7 +2,6 @@
#![deny(warnings)] #![deny(warnings)]
#![no_main] #![no_main]
#![no_std] #![no_std]
#![feature(type_alias_impl_trait)]
use nrf52840_blinky::hal; use nrf52840_blinky::hal;

View file

@ -1,6 +1,5 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![feature(type_alias_impl_trait)]
#[rtic::app( #[rtic::app(
device = rp_pico::hal::pac, device = rp_pico::hal::pac,

View file

@ -6,12 +6,12 @@ Working example of simple LED blinking application for STM32 F303 Nucleo-64 boar
### Build ### Build
Run `cargo +nightly build` to compile the code. If you run it for the first time, it will take some time to download and compile dependencies. Run `cargo build --release` to compile the code. If you run it for the first time, it will take some time to download and compile dependencies.
After that, you can use for example the cargo-embed tool to flash and run it After that, you can use for example the cargo-embed tool to flash and run it
```bash ```bash
$ cargo +nightly embed $ cargo embed
``` ```
### Setup environment, flash and run program ### Setup environment, flash and run program

View file

@ -2,7 +2,6 @@
#![deny(warnings)] #![deny(warnings)]
#![no_main] #![no_main]
#![no_std] #![no_std]
#![feature(type_alias_impl_trait)]
use panic_rtt_target as _; use panic_rtt_target as _;
use rtic::app; use rtic::app;

View file

@ -2,15 +2,6 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "atomic-polyfill"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
dependencies = [
"critical-section",
]
[[package]] [[package]]
name = "atomic-polyfill" name = "atomic-polyfill"
version = "1.0.3" version = "1.0.3"
@ -20,19 +11,13 @@ dependencies = [
"critical-section", "critical-section",
] ]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]] [[package]]
name = "bare-metal" name = "bare-metal"
version = "0.2.5" version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
dependencies = [ dependencies = [
"rustc_version 0.2.3", "rustc_version",
] ]
[[package]] [[package]]
@ -124,7 +109,7 @@ dependencies = [
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -148,13 +133,22 @@ dependencies = [
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.3.9" version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [ dependencies = [
"powerfmt", "powerfmt",
] ]
[[package]]
name = "document-features"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95"
dependencies = [
"litrs",
]
[[package]] [[package]]
name = "embedded-dma" name = "embedded-dma"
version = "0.2.0" version = "0.2.0"
@ -176,25 +170,25 @@ dependencies = [
[[package]] [[package]]
name = "embedded-hal" name = "embedded-hal"
version = "1.0.0-rc.1" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2894bc2f0457b8ca3d6b8ab8aad64d9337583672494013457f86c5a9146c0e22" checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
[[package]] [[package]]
name = "embedded-hal-nb" name = "embedded-hal-nb"
version = "1.0.0-rc.1" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "257e3bb0163c69195acb0ebe0083b017b963235861d5ea9741626abdc55f39c9" checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605"
dependencies = [ dependencies = [
"embedded-hal 1.0.0-rc.1", "embedded-hal 1.0.0",
"nb 1.1.0", "nb 1.1.0",
] ]
[[package]] [[package]]
name = "embedded-storage" name = "embedded-storage"
version = "0.3.0" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "156d7a2fdd98ebbf9ae579cbceca3058cff946e13f8e17b90e3511db0508c723" checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032"
[[package]] [[package]]
name = "enumflags2" name = "enumflags2"
@ -213,7 +207,7 @@ checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -243,21 +237,21 @@ dependencies = [
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.29" version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.29" version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]] [[package]]
name = "futures-util" name = "futures-util"
version = "0.3.29" version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-task", "futures-task",
@ -273,9 +267,9 @@ checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
[[package]] [[package]]
name = "hash32" name = "hash32"
version = "0.2.1" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
dependencies = [ dependencies = [
"byteorder", "byteorder",
] ]
@ -288,36 +282,29 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]] [[package]]
name = "heapless" name = "heapless"
version = "0.7.16" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
dependencies = [ dependencies = [
"atomic-polyfill 0.1.11",
"hash32", "hash32",
"rustc_version 0.4.0",
"spin",
"stable_deref_trait", "stable_deref_trait",
] ]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.1.0" version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown", "hashbrown",
] ]
[[package]] [[package]]
name = "lock_api" name = "litrs"
version = "0.4.11" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]] [[package]]
name = "nb" name = "nb"
@ -352,6 +339,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "portable-atomic"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
version = "0.2.0" version = "0.2.0"
@ -384,18 +377,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.70" version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.33" version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -427,7 +420,7 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "857ce76a2517808a303bcb7e5b6d4a9c1d84e5de88b302aec2e53744633c0f4d" checksum = "857ce76a2517808a303bcb7e5b6d4a9c1d84e5de88b302aec2e53744633c0f4d"
dependencies = [ dependencies = [
"atomic-polyfill 1.0.3", "atomic-polyfill",
"bare-metal 1.0.0", "bare-metal 1.0.0",
"cortex-m", "cortex-m",
"critical-section", "critical-section",
@ -466,33 +459,34 @@ dependencies = [
[[package]] [[package]]
name = "rtic-monotonics" name = "rtic-monotonics"
version = "1.3.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75936ddc03d8946dd256c89270501186916db5505692e1207912404231a05774" checksum = "058c2397dbd5bb4c5650a0e368c3920953e458805ff5097a0511b8147b3619d7"
dependencies = [ dependencies = [
"atomic-polyfill 1.0.3", "atomic-polyfill",
"cfg-if", "cfg-if",
"embedded-hal 1.0.0-rc.1", "embedded-hal 1.0.0",
"fugit", "fugit",
"rtic-time", "rtic-time",
] ]
[[package]] [[package]]
name = "rtic-sync" name = "rtic-sync"
version = "1.0.2" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc586db4c7ee4a85482ebb0542f34ffaee16bd8b8c552081f07492f531aca9f" checksum = "5a243123bcfb0bbbbf27b89c13de35670875a8725ec69763062e8a5903e69e93"
dependencies = [ dependencies = [
"critical-section", "critical-section",
"heapless", "heapless",
"portable-atomic",
"rtic-common", "rtic-common",
] ]
[[package]] [[package]]
name = "rtic-time" name = "rtic-time"
version = "1.0.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55127cfa37ad32522eca2b70a12298bdb035c75ee3a4e403af8773ffe1a64bd3" checksum = "75b232e7aebc045cfea81cdd164bc2727a10aca9a4568d406d0a5661cdfd0f19"
dependencies = [ dependencies = [
"critical-section", "critical-section",
"futures-util", "futures-util",
@ -505,24 +499,9 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [ dependencies = [
"semver 0.9.0", "semver",
] ]
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver 1.0.20",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "semver" name = "semver"
version = "0.9.0" version = "0.9.0"
@ -532,27 +511,12 @@ dependencies = [
"semver-parser", "semver-parser",
] ]
[[package]]
name = "semver"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]] [[package]]
name = "semver-parser" name = "semver-parser"
version = "0.7.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.2.0" version = "1.2.0"
@ -573,16 +537,17 @@ dependencies = [
[[package]] [[package]]
name = "stm32f4xx-hal" name = "stm32f4xx-hal"
version = "0.18.0" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80faf7c1b60e623f84584c5eddb634618e11afb5634eb871b678ef9251cef0a1" checksum = "10c41454f262c0be0c35b8cfc0d971e598281f7a9be32e894dc97a0b21deadfe"
dependencies = [ dependencies = [
"bare-metal 1.0.0", "bare-metal 1.0.0",
"cortex-m", "cortex-m",
"cortex-m-rt", "cortex-m-rt",
"document-features",
"embedded-dma", "embedded-dma",
"embedded-hal 0.2.7", "embedded-hal 0.2.7",
"embedded-hal 1.0.0-rc.1", "embedded-hal 1.0.0",
"embedded-hal-nb", "embedded-hal-nb",
"embedded-storage", "embedded-storage",
"enumflags2", "enumflags2",
@ -609,9 +574,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.39" version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -620,29 +585,29 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.50" version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.50" version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.39", "syn 2.0.48",
] ]
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.30" version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e"
dependencies = [ dependencies = [
"deranged", "deranged",
"powerfmt", "powerfmt",

View file

@ -18,8 +18,8 @@ defmt-rtt = { version = "0.4.0"}
rtic-sync = "1.0.2" rtic-sync = "1.0.2"
[dependencies.stm32f4xx-hal] [dependencies.stm32f4xx-hal]
version = "0.18.0" version = "0.20.0"
features = ["rt", "stm32f411"] # replace the model of your microcontroller here features = ["stm32f411"] # replace the model of your microcontroller here
# this lets you use `cargo fix`! # this lets you use `cargo fix`!
[[bin]] [[bin]]

View file

@ -6,7 +6,7 @@ After configured, it will listen to periodic wake-up interrupts happening every
## How-to ## How-to
### Build ### Build
Run `cargo +nightly build` to compile the code. If you run it for the first time, it will take some time to download and compile dependencies. Run `cargo build --release` to compile the code. If you run it for the first time, it will take some time to download and compile dependencies.
### Run ### Run
Install `probe-rs` and configure it using the [debugging extension for VScode](https://probe.rs/docs/tools/debugger/). Install `probe-rs` and configure it using the [debugging extension for VScode](https://probe.rs/docs/tools/debugger/).

View file

@ -2,7 +2,6 @@
#![deny(warnings)] #![deny(warnings)]
#![no_main] #![no_main]
#![no_std] #![no_std]
#![feature(type_alias_impl_trait)]
use panic_halt as _; use panic_halt as _;

View file

@ -1,7 +1,6 @@
#![deny(warnings)] #![deny(warnings)]
#![no_main] #![no_main]
#![no_std] #![no_std]
#![feature(type_alias_impl_trait)]
use bsp::pins::common::{P0, P1}; use bsp::pins::common::{P0, P1};
imxrt_uart_panic::register!(LPUART6, P1, P0, 115200, teensy4_panic::sos); imxrt_uart_panic::register!(LPUART6, P1, P0, 115200, teensy4_panic::sos);

View file

@ -2,7 +2,6 @@
#![deny(warnings)] #![deny(warnings)]
#![no_main] #![no_main]
#![no_std] #![no_std]
#![feature(type_alias_impl_trait)]
#[panic_handler] #[panic_handler]
fn panic(_: &::core::panic::PanicInfo) -> ! { fn panic(_: &::core::panic::PanicInfo) -> ! {

View file

@ -9,6 +9,7 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
### Added ### Added
- RTIC v2 now works on stable.
- Unstable ESP32-C3 support. - Unstable ESP32-C3 support.
### Changed ### Changed

View file

@ -2,7 +2,7 @@ use crate::syntax::ast::App;
use crate::{ use crate::{
analyze::Analysis, analyze::Analysis,
codegen::{ codegen::{
bindings::{async_entry, interrupt_entry, interrupt_exit, handler_config}, bindings::{async_entry, handler_config, interrupt_entry, interrupt_exit},
util, util,
}, },
}; };
@ -17,15 +17,12 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
// Generate executor definition and priority in global scope // Generate executor definition and priority in global scope
for (name, _) in app.software_tasks.iter() { for (name, _) in app.software_tasks.iter() {
let type_name = util::internal_task_ident(name, "F");
let exec_name = util::internal_task_ident(name, "EXEC"); let exec_name = util::internal_task_ident(name, "EXEC");
items.push(quote!( items.push(quote!(
#[allow(non_camel_case_types)]
type #type_name = impl core::future::Future;
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
static #exec_name: rtic::export::executor::AsyncTaskExecutor<#type_name> = static #exec_name: rtic::export::executor::AsyncTaskExecutorPtr =
rtic::export::executor::AsyncTaskExecutor::new(); rtic::export::executor::AsyncTaskExecutorPtr::new();
)); ));
} }
@ -50,13 +47,18 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
for name in channel.tasks.iter() { for name in channel.tasks.iter() {
let exec_name = util::internal_task_ident(name, "EXEC"); let exec_name = util::internal_task_ident(name, "EXEC");
let from_ptr_n_args =
util::from_ptr_n_args_ident(app.software_tasks[name].inputs.len());
// TODO: Fix cfg // TODO: Fix cfg
// let task = &app.software_tasks[name]; // let task = &app.software_tasks[name];
// let cfgs = &task.cfgs; // let cfgs = &task.cfgs;
stmts.push(quote!( stmts.push(quote!(
#exec_name.poll(|| { let exec = rtic::export::executor::AsyncTaskExecutor::#from_ptr_n_args(#name, &#exec_name);
#exec_name.set_pending(); exec.poll(|| {
let exec = rtic::export::executor::AsyncTaskExecutor::#from_ptr_n_args(#name, &#exec_name);
exec.set_pending();
#pend_interrupt #pend_interrupt
}); });
)); ));

View file

@ -29,11 +29,35 @@ fn is_exception(name: &Ident) -> bool {
| "SysTick" | "SysTick"
) )
} }
pub fn interrupt_ident() -> Ident { pub fn interrupt_ident() -> Ident {
let span = Span::call_site(); let span = Span::call_site();
Ident::new("interrupt", span) Ident::new("interrupt", span)
} }
pub fn check_stack_overflow_before_init(
_app: &App,
_analysis: &CodegenAnalysis,
) -> Vec<TokenStream2> {
vec![quote!(
// Check for stack overflow using symbols from `cortex-m-rt`.
extern "C" {
pub static _stack_start: u32;
pub static __ebss: u32;
}
let stack_start = &_stack_start as *const _ as u32;
let ebss = &__ebss as *const _ as u32;
if stack_start > ebss {
// No flip-link usage, check the MSP for overflow.
if rtic::export::msp::read() <= ebss {
panic!("Stack overflow after allocating executors");
}
}
)]
}
#[cfg(feature = "cortex-m-source-masking")] #[cfg(feature = "cortex-m-source-masking")]
mod source_masking { mod source_masking {
use super::*; use super::*;

View file

@ -158,6 +158,29 @@ mod esp32c3 {
vec![] vec![]
} }
pub fn check_stack_overflow_before_init(
_app: &App,
_analysis: &CodegenAnalysis,
) -> Vec<TokenStream2> {
vec![quote!(
// Check for stack overflow using symbols from `risc-v-rt`.
extern "C" {
pub static _stack_start: u32;
pub static __ebss: u32;
}
let stack_start = &_stack_start as *const _ as u32;
let ebss = &__ebss as *const _ as u32;
if stack_start > ebss {
// No flip-link usage, check the SP for overflow.
if rtic::export::read_sp() <= ebss {
panic!("Stack overflow after allocating executors");
}
}
)]
}
pub fn async_entry( pub fn async_entry(
_app: &App, _app: &App,
_analysis: &CodegenAnalysis, _analysis: &CodegenAnalysis,
@ -201,9 +224,7 @@ mod esp32c3 {
) { ) {
if *name == dispatcher_name { if *name == dispatcher_name {
let ret = &("cpu_int_".to_owned() + &curr_cpu_id.to_string() + "_handler"); let ret = &("cpu_int_".to_owned() + &curr_cpu_id.to_string() + "_handler");
stmts.push( stmts.push(quote!(#[export_name = #ret]));
quote!(#[export_name = #ret])
);
} }
curr_cpu_id += 1; curr_cpu_id += 1;
} }

View file

@ -43,6 +43,13 @@ pub fn interrupt_exit(_app: &App, _analysis: &CodegenAnalysis) -> Vec<TokenStrea
vec![] vec![]
} }
pub fn check_stack_overflow_before_init(
_app: &App,
_analysis: &CodegenAnalysis,
) -> Vec<TokenStream2> {
vec![]
}
pub fn async_entry( pub fn async_entry(
_app: &App, _app: &App,
_analysis: &CodegenAnalysis, _analysis: &CodegenAnalysis,

View file

@ -1,9 +1,12 @@
use crate::{analyze::Analysis, codegen::util, syntax::ast::App}; use super::{assertions, post_init, pre_init};
use crate::{
analyze::Analysis,
codegen::{bindings, util},
syntax::ast::App,
};
use proc_macro2::TokenStream as TokenStream2; use proc_macro2::TokenStream as TokenStream2;
use quote::quote; use quote::quote;
use super::{assertions, post_init, pre_init};
/// Generates code for `fn main` /// Generates code for `fn main`
pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
let assertion_stmts = assertions::codegen(app, analysis); let assertion_stmts = assertions::codegen(app, analysis);
@ -19,12 +22,26 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
let dispatcher = util::zero_prio_dispatcher_ident(); let dispatcher = util::zero_prio_dispatcher_ident();
quote!(#dispatcher();) quote!(#dispatcher();)
} else { } else {
quote!(loop { quote!(loop {})
})
}; };
let mut executor_allocations = Vec::new();
for (name, _) in app.software_tasks.iter() {
let exec_name = util::internal_task_ident(name, "EXEC");
let new_n_args = util::new_n_args_ident(app.software_tasks[name].inputs.len());
executor_allocations.push(quote!(
let executor = ::core::mem::ManuallyDrop::new(rtic::export::executor::AsyncTaskExecutor::#new_n_args(#name));
executors_size += ::core::mem::size_of_val(&executor);
#exec_name.set_in_main(&executor);
));
}
let main = util::suffixed("main"); let main = util::suffixed("main");
let init_name = &app.init.name; let init_name = &app.init.name;
let msp_check = bindings::check_stack_overflow_before_init(app, analysis);
quote!( quote!(
#[doc(hidden)] #[doc(hidden)]
#[no_mangle] #[no_mangle]
@ -38,9 +55,15 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
f(); f();
} }
// Generate allocations for async executors.
let mut executors_size = 0;
#(#executor_allocations)*
#(#msp_check)*
// Wrap late_init_stmts in a function to ensure that stack space is reclaimed. // Wrap late_init_stmts in a function to ensure that stack space is reclaimed.
__rtic_init_resources(||{ __rtic_init_resources(||{
let (shared_resources, local_resources) = #init_name(#init_name::Context::new(core.into())); let (shared_resources, local_resources) = #init_name(#init_name::Context::new(core.into(), executors_size));
#(#post_init_stmts)* #(#post_init_stmts)*
}); });

View file

@ -21,6 +21,11 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
pub core: rtic::export::Peripherals pub core: rtic::export::Peripherals
)); ));
fields.push(quote!(
/// The space used to allocate async executors in bytes.
pub executors_size: usize
));
if app.args.peripherals { if app.args.peripherals {
let device = &app.args.device; let device = &app.args.device;
@ -40,6 +45,7 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
values.push(quote!(cs: rtic::export::CriticalSection::new())); values.push(quote!(cs: rtic::export::CriticalSection::new()));
values.push(quote!(core)); values.push(quote!(core));
values.push(quote!(executors_size));
} }
Context::Idle | Context::HardwareTask(_) | Context::SoftwareTask(_) => {} Context::Idle | Context::HardwareTask(_) | Context::SoftwareTask(_) => {}
@ -92,7 +98,7 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
}; };
let core = if ctxt.is_init() { let core = if ctxt.is_init() {
Some(quote!(core: rtic::export::Peripherals,)) Some(quote!(core: rtic::export::Peripherals, executors_size: usize))
} else { } else {
None None
}; };
@ -147,11 +153,10 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
}; };
let internal_spawn_ident = util::internal_task_ident(name, "spawn"); let internal_spawn_ident = util::internal_task_ident(name, "spawn");
let from_ptr_n_args = util::from_ptr_n_args_ident(spawnee.inputs.len());
let (input_args, input_tupled, input_untupled, input_ty) = let (input_args, input_tupled, input_untupled, input_ty) =
util::regroup_inputs(&spawnee.inputs); util::regroup_inputs(&spawnee.inputs);
let type_name = util::internal_task_ident(name, "F");
// Spawn caller // Spawn caller
items.push(quote!( items.push(quote!(
#(#cfgs)* #(#cfgs)*
@ -159,18 +164,11 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[doc(hidden)] #[doc(hidden)]
pub fn #internal_spawn_ident(#(#input_args,)*) -> Result<(), #input_ty> { pub fn #internal_spawn_ident(#(#input_args,)*) -> Result<(), #input_ty> {
// New TAIT requirement hack; the opaque type must be in the argument or return
// position of a function...
#[inline(always)]
fn tait_hack(#(#input_args,)*) -> #type_name {
#name(unsafe { #name::Context::new() } #(,#input_untupled)*)
}
// SAFETY: If `try_allocate` succeeds one must call `spawn`, which we do. // SAFETY: If `try_allocate` succeeds one must call `spawn`, which we do.
unsafe { unsafe {
if #exec_name.try_allocate() { let exec = rtic::export::executor::AsyncTaskExecutor::#from_ptr_n_args(#name, &#exec_name);
let f = tait_hack(#(#input_untupled,)*); if exec.try_allocate() {
#exec_name.spawn(f); exec.spawn(#name(unsafe { #name::Context::new() } #(,#input_untupled)*));
#pend_interrupt #pend_interrupt
Ok(()) Ok(())

View file

@ -8,7 +8,6 @@ pub use super::bindings::interrupt_ident;
const RTIC_INTERNAL: &str = "__rtic_internal"; const RTIC_INTERNAL: &str = "__rtic_internal";
/// Mark a name as internal /// Mark a name as internal
pub fn mark_internal_name(name: &str) -> Ident { pub fn mark_internal_name(name: &str) -> Ident {
Ident::new(&format!("{RTIC_INTERNAL}_{name}"), Span::call_site()) Ident::new(&format!("{RTIC_INTERNAL}_{name}"), Span::call_site())
@ -166,3 +165,11 @@ pub fn rt_err_ident() -> Ident {
Span::call_site(), Span::call_site(),
) )
} }
pub fn from_ptr_n_args_ident(n: usize) -> Ident {
Ident::new(&format!("from_ptr_{}_args", n + 1), Span::call_site())
}
pub fn new_n_args_ident(n: usize) -> Ident {
Ident::new(&format!("new_{}_args", n + 1), Span::call_site())
}

View file

@ -7,6 +7,10 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
## Unreleased ## Unreleased
### Changed
- Removed unused `rust-toolchain.toml`
## v1.5.0 - 2024-01-10 ## v1.5.0 - 2024-01-10
### Changed ### Changed

View file

@ -1,4 +0,0 @@
[toolchain]
channel = "nightly"
components = [ "rust-src", "rustfmt", "llvm-tools-preview" ]
targets = [ "thumbv6m-none-eabi", "thumbv7m-none-eabi" ]

View file

@ -19,6 +19,8 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
### Changed ### Changed
- RTIC v2 now works on stable.
## [v2.0.1] - 2023-07-25 ## [v2.0.1] - 2023-07-25
### Added ### Added

View file

@ -0,0 +1 @@
init, total executor size = 9

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use cortex_m_semihosting::{debug, hprintln}; use cortex_m_semihosting::{debug, hprintln};
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -7,7 +7,6 @@
#![no_std] #![no_std]
#![deny(warnings)] #![deny(warnings)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -0,0 +1,42 @@
//! examples/executor-size.rs
#![no_main]
#![no_std]
#![deny(warnings)]
#![deny(unsafe_code)]
#![deny(missing_docs)]
use panic_semihosting as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
#[shared]
struct Shared {}
#[local]
struct Local {}
#[init]
fn init(cx: init::Context) -> (Shared, Local) {
hprintln!("init, total executor size = {}", cx.executors_size);
foo::spawn().ok();
bar::spawn().ok();
baz::spawn().ok();
(Shared {}, Local {})
}
#[task]
async fn foo(_cx: foo::Context) {}
#[task]
async fn bar(_cx: bar::Context) {}
#[task]
async fn baz(_cx: baz::Context) {
debug::exit(debug::EXIT_SUCCESS);
}
}

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use cortex_m_semihosting::{debug, hprintln}; use cortex_m_semihosting::{debug, hprintln};
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -4,7 +4,6 @@
#![no_std] #![no_std]
#![deny(warnings)] #![deny(warnings)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use core::marker::PhantomData; use core::marker::PhantomData;
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -3,7 +3,6 @@
#![no_main] #![no_main]
#![no_std] #![no_std]
#![deny(warnings)] #![deny(warnings)]
#![feature(type_alias_impl_trait)]
use heapless::{ use heapless::{
pool, pool,

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;
use rtic::app; use rtic::app;

View file

@ -7,7 +7,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;
use rtic::app; use rtic::app;

View file

@ -4,7 +4,6 @@
#![no_main] #![no_main]
#![no_std] #![no_std]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -5,7 +5,6 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(type_alias_impl_trait)]
use core::marker::PhantomData; use core::marker::PhantomData;
use panic_semihosting as _; use panic_semihosting as _;

View file

@ -1,4 +1,4 @@
pub use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC}; pub use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC, register::msp};
#[inline] #[inline]
#[must_use] #[must_use]

View file

@ -1,8 +1,8 @@
use super::atomic::{AtomicBool, Ordering}; use super::atomic::{AtomicBool, AtomicPtr, Ordering};
use core::{ use core::{
cell::UnsafeCell, cell::UnsafeCell,
future::Future, future::Future,
mem::{self, MaybeUninit}, mem::{self, ManuallyDrop, MaybeUninit},
pin::Pin, pin::Pin,
task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
}; };
@ -28,6 +28,30 @@ unsafe fn waker_drop(_: *const ()) {
//============ //============
// AsyncTaskExecutor // AsyncTaskExecutor
/// Pointer to executor holder.
pub struct AsyncTaskExecutorPtr {
// Void pointer.
ptr: AtomicPtr<()>,
}
impl AsyncTaskExecutorPtr {
pub const fn new() -> Self {
Self {
ptr: AtomicPtr::new(core::ptr::null_mut()),
}
}
#[inline(always)]
pub fn set_in_main<F: Future>(&self, executor: &ManuallyDrop<AsyncTaskExecutor<F>>) {
self.ptr.store(executor as *const _ as _, Ordering::Relaxed);
}
#[inline(always)]
pub fn get(&self) -> *const () {
self.ptr.load(Ordering::Relaxed)
}
}
/// Executor for an async task. /// Executor for an async task.
pub struct AsyncTaskExecutor<F: Future> { pub struct AsyncTaskExecutor<F: Future> {
// `task` is protected by the `running` flag. // `task` is protected by the `running` flag.
@ -38,6 +62,24 @@ pub struct AsyncTaskExecutor<F: Future> {
unsafe impl<F: Future> Sync for AsyncTaskExecutor<F> {} unsafe impl<F: Future> Sync for AsyncTaskExecutor<F> {}
macro_rules! new_n_args {
($name:ident, $($t:ident),*) => {
#[inline(always)]
pub fn $name<$($t,)* Fun: Fn($($t,)*) -> F>(_f: Fun) -> Self {
Self::new()
}
};
}
macro_rules! from_ptr_n_args {
($name:ident, $($t:ident),*) => {
#[inline(always)]
pub unsafe fn $name<$($t,)* Fun: Fn($($t,)*) -> F>(_f: Fun, ptr: &AsyncTaskExecutorPtr) -> &Self {
&*(ptr.get() as *const _)
}
};
}
impl<F: Future> AsyncTaskExecutor<F> { impl<F: Future> AsyncTaskExecutor<F> {
/// Create a new executor. /// Create a new executor.
#[inline(always)] #[inline(always)]
@ -49,6 +91,55 @@ impl<F: Future> AsyncTaskExecutor<F> {
} }
} }
// Support for up to 16 arguments on async functions. Should be
// enough for now, else extend this list.
new_n_args!(new_0_args,);
new_n_args!(new_1_args, A1);
new_n_args!(new_2_args, A1, A2);
new_n_args!(new_3_args, A1, A2, A3);
new_n_args!(new_4_args, A1, A2, A3, A4);
new_n_args!(new_5_args, A1, A2, A3, A4, A5);
new_n_args!(new_6_args, A1, A2, A3, A4, A5, A6);
new_n_args!(new_7_args, A1, A2, A3, A4, A5, A6, A7);
new_n_args!(new_8_args, A1, A2, A3, A4, A5, A6, A7, A8);
new_n_args!(new_9_args, A1, A2, A3, A4, A5, A6, A7, A8, A9);
new_n_args!(new_10_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
new_n_args!(new_11_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
#[rustfmt::skip]
new_n_args!(new_12_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
#[rustfmt::skip]
new_n_args!(new_13_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
#[rustfmt::skip]
new_n_args!(new_14_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
#[rustfmt::skip]
new_n_args!(new_15_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15);
#[rustfmt::skip]
new_n_args!(new_16_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16);
from_ptr_n_args!(from_ptr_0_args,);
from_ptr_n_args!(from_ptr_1_args, A1);
from_ptr_n_args!(from_ptr_2_args, A1, A2);
from_ptr_n_args!(from_ptr_3_args, A1, A2, A3);
from_ptr_n_args!(from_ptr_4_args, A1, A2, A3, A4);
from_ptr_n_args!(from_ptr_5_args, A1, A2, A3, A4, A5);
from_ptr_n_args!(from_ptr_6_args, A1, A2, A3, A4, A5, A6);
from_ptr_n_args!(from_ptr_7_args, A1, A2, A3, A4, A5, A6, A7);
from_ptr_n_args!(from_ptr_8_args, A1, A2, A3, A4, A5, A6, A7, A8);
from_ptr_n_args!(from_ptr_9_args, A1, A2, A3, A4, A5, A6, A7, A8, A9);
from_ptr_n_args!(from_ptr_10_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
#[rustfmt::skip]
from_ptr_n_args!(from_ptr_11_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
#[rustfmt::skip]
from_ptr_n_args!(from_ptr_12_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
#[rustfmt::skip]
from_ptr_n_args!(from_ptr_13_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
#[rustfmt::skip]
from_ptr_n_args!(from_ptr_14_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
#[rustfmt::skip]
from_ptr_n_args!(from_ptr_15_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15);
#[rustfmt::skip]
from_ptr_n_args!(from_ptr_16_args, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16);
/// Check if there is an active task in the executor. /// Check if there is an active task in the executor.
#[inline(always)] #[inline(always)]
pub fn is_running(&self) -> bool { pub fn is_running(&self) -> bool {

View file

@ -1,2 +1,10 @@
/// GENERIC RE-EXPORTS: needed for all RTIC backends /// GENERIC RE-EXPORTS: needed for all RTIC backends
pub use riscv::interrupt; pub use riscv::interrupt;
/// Read the stack pointer.
#[inline(always)]
pub fn read_sp() -> u32 {
let r;
unsafe { asm!("mv {}, sp", out(reg) r, options(nomem, nostack, preserves_flags)) };
r
}

View file

@ -9,8 +9,8 @@
//! //!
//! # Minimum Supported Rust Version (MSRV) //! # Minimum Supported Rust Version (MSRV)
//! //!
//! This crate is compiled and tested with the latest nightly toolchain (rolling). //! This crate is compiled and tested with the latest stable toolchain (rolling).
//! If you run into compilation errors, try the latest nightly release of the rust toolchain. //! If you run into compilation errors, try the latest stable release of the rust toolchain.
//! //!
//! # Semantic Versioning //! # Semantic Versioning
//! //!

View file

@ -1,4 +1,4 @@
[toolchain] [toolchain]
channel = "nightly" channel = "stable"
components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] components = [ "rust-src", "rustfmt", "llvm-tools-preview" ]
targets = [ "thumbv6m-none-eabi", "thumbv7m-none-eabi", "thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi" ] targets = [ "thumbv6m-none-eabi", "thumbv7m-none-eabi", "thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi" ]

View file

@ -483,7 +483,7 @@ impl<'a> CargoCommand<'a> {
// Target is added by build_args // Target is added by build_args
target: _, target: _,
} => self.build_args( } => self.build_args(
true, false,
cargoarg, cargoarg,
features, features,
Some(mode), Some(mode),
@ -501,7 +501,7 @@ impl<'a> CargoCommand<'a> {
// deny_warnings is exposed through `extra_env` // deny_warnings is exposed through `extra_env`
deny_warnings: _, deny_warnings: _,
} => self.build_args( } => self.build_args(
true, false,
cargoarg, cargoarg,
features, features,
Some(mode), Some(mode),
@ -518,7 +518,7 @@ impl<'a> CargoCommand<'a> {
dir: _, dir: _,
// deny_warnings is exposed through `extra_env` // deny_warnings is exposed through `extra_env`
deny_warnings: _, deny_warnings: _,
} => self.build_args(true, cargoarg, features, Some(mode), p(package)), } => self.build_args(false, cargoarg, features, Some(mode), p(package)),
CargoCommand::Check { CargoCommand::Check {
cargoarg, cargoarg,
package, package,
@ -530,7 +530,7 @@ impl<'a> CargoCommand<'a> {
target: _, target: _,
// deny_warnings is exposed through `extra_env` // deny_warnings is exposed through `extra_env`
deny_warnings: _, deny_warnings: _,
} => self.build_args(true, cargoarg, features, Some(mode), p(package)), } => self.build_args(false, cargoarg, features, Some(mode), p(package)),
CargoCommand::Clippy { CargoCommand::Clippy {
cargoarg, cargoarg,
package, package,
@ -546,7 +546,7 @@ impl<'a> CargoCommand<'a> {
}; };
let extra = p(package).chain(deny_warnings); let extra = p(package).chain(deny_warnings);
self.build_args(true, cargoarg, features, None, extra) self.build_args(false, cargoarg, features, None, extra)
} }
CargoCommand::Doc { CargoCommand::Doc {
cargoarg, cargoarg,
@ -556,7 +556,7 @@ impl<'a> CargoCommand<'a> {
deny_warnings: _, deny_warnings: _,
} => { } => {
let extra = Self::extra_args(arguments.as_ref()); let extra = Self::extra_args(arguments.as_ref());
self.build_args(true, cargoarg, features, None, extra) self.build_args(false, cargoarg, features, None, extra)
} }
CargoCommand::Test { CargoCommand::Test {
package, package,
@ -572,7 +572,7 @@ impl<'a> CargoCommand<'a> {
}; };
let package = p(package); let package = p(package);
let extra = extra.into_iter().chain(package); let extra = extra.into_iter().chain(package);
self.build_args(true, &None, features, None, extra) self.build_args(false, &None, features, None, extra)
} }
CargoCommand::Book { arguments } => { CargoCommand::Book { arguments } => {
let mut args = vec![]; let mut args = vec![];
@ -597,7 +597,7 @@ impl<'a> CargoCommand<'a> {
let extra = if *check_only { Some("--check") } else { None }; let extra = if *check_only { Some("--check") } else { None };
let package = p(package); let package = p(package);
self.build_args( self.build_args(
true, false,
cargoarg, cargoarg,
&None, &None,
None, None,
@ -616,7 +616,7 @@ impl<'a> CargoCommand<'a> {
// deny_warnings is exposed through `extra_env` // deny_warnings is exposed through `extra_env`
deny_warnings: _, deny_warnings: _,
} => self.build_args( } => self.build_args(
true, false,
cargoarg, cargoarg,
features, features,
Some(mode), Some(mode),
@ -632,7 +632,7 @@ impl<'a> CargoCommand<'a> {
// deny_warnings is exposed through `extra_env` // deny_warnings is exposed through `extra_env`
deny_warnings: _, deny_warnings: _,
} => self.build_args( } => self.build_args(
true, false,
cargoarg, cargoarg,
features, features,
Some(mode), Some(mode),
@ -655,7 +655,7 @@ impl<'a> CargoCommand<'a> {
.into_iter() .into_iter()
.chain(Self::extra_args(arguments.as_ref())); .chain(Self::extra_args(arguments.as_ref()));
self.build_args(true, cargoarg, features, Some(mode), extra) self.build_args(false, cargoarg, features, Some(mode), extra)
} }
} }
} }