From 27985009579e82673dcaf7a6a715fcf50c184863 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Mon, 29 Jan 2024 20:56:15 +0100 Subject: [PATCH] Make RTIC 2 work on stable by using `main`'s stack as an allocator --- .github/workflows/build.yml | 10 +- book/en/src/SUMMARY.md | 1 - book/en/src/migration_v1_v2.md | 10 +- .../src/migration_v1_v2/complete_example.md | 1 - book/en/src/migration_v1_v2/nightly.md | 5 - book/en/src/preface.md | 2 - .../nrf52840_blinky/src/bin/blinky_rtc.rs | 1 - .../nrf52840_blinky/src/bin/blinky_timer.rs | 1 - examples/rp2040_local_i2c_init/src/main.rs | 1 - examples/stm32f3_blinky/README.md | 4 +- examples/stm32f3_blinky/src/main.rs | 1 - examples/stm32f411_rtc_interrupt/Cargo.lock | 175 +++++++----------- examples/stm32f411_rtc_interrupt/Cargo.toml | 4 +- examples/stm32f411_rtc_interrupt/README.md | 2 +- examples/stm32f411_rtc_interrupt/src/main.rs | 1 - examples/teensy4_blinky/examples/with_logs.rs | 1 - examples/teensy4_blinky/src/main.rs | 1 - rtic-macros/CHANGELOG.md | 1 + rtic-macros/src/codegen/async_dispatchers.rs | 20 +- rtic-macros/src/codegen/bindings/cortex.rs | 24 +++ rtic-macros/src/codegen/bindings/esp32c3.rs | 33 +++- rtic-macros/src/codegen/bindings/template.rs | 7 + rtic-macros/src/codegen/main.rs | 35 +++- rtic-macros/src/codegen/module.rs | 24 ++- rtic-macros/src/codegen/util.rs | 9 +- rtic-monotonics/CHANGELOG.md | 4 + rtic-monotonics/rust-toolchain.toml | 4 - rtic/CHANGELOG.md | 2 + rtic/ci/expected/executor-size.run | 1 + rtic/examples/async-channel-done.rs | 1 - rtic/examples/async-channel-no-receiver.rs | 1 - rtic/examples/async-channel-no-sender.rs | 1 - rtic/examples/async-channel-try.rs | 1 - rtic/examples/async-channel.rs | 1 - rtic/examples/async-delay.rs | 1 - rtic/examples/async-task-multiple-prios.rs | 1 - rtic/examples/async-task.rs | 1 - rtic/examples/async-timeout.rs | 1 - rtic/examples/big-struct-opt.rs | 1 - rtic/examples/common.rs | 1 - rtic/examples/destructure.rs | 1 - rtic/examples/executor-size.rs | 42 +++++ rtic/examples/extern_spawn.rs | 1 - rtic/examples/locals.rs | 1 - rtic/examples/lock-free.rs | 1 - rtic/examples/lock.rs | 1 - rtic/examples/multilock.rs | 1 - rtic/examples/not-sync.rs | 1 - rtic/examples/only-shared-access.rs | 1 - rtic/examples/pool.rs_old | 1 - rtic/examples/preempt.rs | 1 - rtic/examples/prio-inversion.rs | 1 - rtic/examples/ramfunc.rs | 1 - rtic/examples/spawn.rs | 1 - rtic/examples/spawn_arguments.rs | 1 - rtic/examples/spawn_err.rs | 1 - rtic/examples/spawn_loop.rs | 1 - rtic/examples/static.rs | 1 - rtic/examples/task.rs | 1 - rtic/examples/zero-prio-task.rs | 1 - rtic/src/export/cortex_common.rs | 2 +- rtic/src/export/executor.rs | 95 +++++++++- rtic/src/export/riscv_common.rs | 8 + rtic/src/lib.rs | 4 +- rust-toolchain.toml | 2 +- xtask/src/cargo_command.rs | 22 +-- 66 files changed, 368 insertions(+), 222 deletions(-) delete mode 100644 book/en/src/migration_v1_v2/nightly.md delete mode 100644 rtic-monotonics/rust-toolchain.toml create mode 100644 rtic/ci/expected/executor-size.run create mode 100644 rtic/examples/executor-size.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 79d2255bb1..578ca407b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: - thumbv8-base - thumbv8-main toolchain: - - nightly + - stable steps: - name: Checkout uses: actions/checkout@v4 @@ -76,7 +76,7 @@ jobs: - thumbv8-base - thumbv8-main toolchain: - - nightly + - stable steps: - name: Checkout uses: actions/checkout@v4 @@ -112,7 +112,7 @@ jobs: - thumbv8-base - thumbv8-main toolchain: - - nightly + - stable steps: - name: Checkout uses: actions/checkout@v4 @@ -146,7 +146,7 @@ jobs: strategy: matrix: toolchain: - - nightly + - stable steps: - name: Checkout uses: actions/checkout@v4 @@ -237,7 +237,7 @@ jobs: - thumbv7 - thumbv6 toolchain: - - nightly + - stable steps: - name: Checkout uses: actions/checkout@v4 diff --git a/book/en/src/SUMMARY.md b/book/en/src/SUMMARY.md index 40832844af..028cb47f79 100644 --- a/book/en/src/SUMMARY.md +++ b/book/en/src/SUMMARY.md @@ -28,7 +28,6 @@ --- - [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) diff --git a/book/en/src/migration_v1_v2.md b/book/en/src/migration_v1_v2.md index a66b1859cc..05ef66c9fe 100644 --- a/book/en/src/migration_v1_v2.md +++ b/book/en/src/migration_v1_v2.md @@ -2,7 +2,7 @@ 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`. 3. Software tasks are now required to be `async`, and using them correctly. 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). #### 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`. -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. -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. + +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`. +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. +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. diff --git a/book/en/src/migration_v1_v2/complete_example.md b/book/en/src/migration_v1_v2/complete_example.md index e76fa4d7dc..47ac2deb6a 100644 --- a/book/en/src/migration_v1_v2/complete_example.md +++ b/book/en/src/migration_v1_v2/complete_example.md @@ -97,7 +97,6 @@ _Note_: This diff may not be 100% accurate, but it displays the important change ``` diff #![no_main] #![no_std] -+#![feature(type_alias_impl_trait)] use panic_rtt_target as _; use rtic::app; diff --git a/book/en/src/migration_v1_v2/nightly.md b/book/en/src/migration_v1_v2/nightly.md deleted file mode 100644 index 768d1b8026..0000000000 --- a/book/en/src/migration_v1_v2/nightly.md +++ /dev/null @@ -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. diff --git a/book/en/src/preface.md b/book/en/src/preface.md index 7c015ee1bb..2c8c31e208 100644 --- a/book/en/src/preface.md +++ b/book/en/src/preface.md @@ -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! -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). So with the technical stuff out of the way, what does `async/await` bring to the table? diff --git a/examples/nrf52840_blinky/src/bin/blinky_rtc.rs b/examples/nrf52840_blinky/src/bin/blinky_rtc.rs index e515659ee3..dbdd0b0fa4 100644 --- a/examples/nrf52840_blinky/src/bin/blinky_rtc.rs +++ b/examples/nrf52840_blinky/src/bin/blinky_rtc.rs @@ -2,7 +2,6 @@ #![deny(warnings)] #![no_main] #![no_std] -#![feature(type_alias_impl_trait)] use nrf52840_blinky::hal; diff --git a/examples/nrf52840_blinky/src/bin/blinky_timer.rs b/examples/nrf52840_blinky/src/bin/blinky_timer.rs index 53ccf4e7e6..c1342f479b 100644 --- a/examples/nrf52840_blinky/src/bin/blinky_timer.rs +++ b/examples/nrf52840_blinky/src/bin/blinky_timer.rs @@ -2,7 +2,6 @@ #![deny(warnings)] #![no_main] #![no_std] -#![feature(type_alias_impl_trait)] use nrf52840_blinky::hal; diff --git a/examples/rp2040_local_i2c_init/src/main.rs b/examples/rp2040_local_i2c_init/src/main.rs index a7ec08d022..97049dce2f 100644 --- a/examples/rp2040_local_i2c_init/src/main.rs +++ b/examples/rp2040_local_i2c_init/src/main.rs @@ -1,6 +1,5 @@ #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] #[rtic::app( device = rp_pico::hal::pac, diff --git a/examples/stm32f3_blinky/README.md b/examples/stm32f3_blinky/README.md index 51526612dd..1994dd3af5 100644 --- a/examples/stm32f3_blinky/README.md +++ b/examples/stm32f3_blinky/README.md @@ -6,12 +6,12 @@ Working example of simple LED blinking application for STM32 F303 Nucleo-64 boar ### 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 ```bash -$ cargo +nightly embed +$ cargo embed ``` ### Setup environment, flash and run program diff --git a/examples/stm32f3_blinky/src/main.rs b/examples/stm32f3_blinky/src/main.rs index b6da714b93..28dc7c205b 100644 --- a/examples/stm32f3_blinky/src/main.rs +++ b/examples/stm32f3_blinky/src/main.rs @@ -2,7 +2,6 @@ #![deny(warnings)] #![no_main] #![no_std] -#![feature(type_alias_impl_trait)] use panic_rtt_target as _; use rtic::app; diff --git a/examples/stm32f411_rtc_interrupt/Cargo.lock b/examples/stm32f411_rtc_interrupt/Cargo.lock index 8401900a6f..08bf790fda 100644 --- a/examples/stm32f411_rtc_interrupt/Cargo.lock +++ b/examples/stm32f411_rtc_interrupt/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. 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]] name = "atomic-polyfill" version = "1.0.3" @@ -20,19 +11,13 @@ dependencies = [ "critical-section", ] -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - [[package]] name = "bare-metal" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" dependencies = [ - "rustc_version 0.2.3", + "rustc_version", ] [[package]] @@ -124,7 +109,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -148,13 +133,22 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + [[package]] name = "embedded-dma" version = "0.2.0" @@ -176,25 +170,25 @@ dependencies = [ [[package]] name = "embedded-hal" -version = "1.0.0-rc.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2894bc2f0457b8ca3d6b8ab8aad64d9337583672494013457f86c5a9146c0e22" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" [[package]] name = "embedded-hal-nb" -version = "1.0.0-rc.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257e3bb0163c69195acb0ebe0083b017b963235861d5ea9741626abdc55f39c9" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" dependencies = [ - "embedded-hal 1.0.0-rc.1", + "embedded-hal 1.0.0", "nb 1.1.0", ] [[package]] name = "embedded-storage" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "156d7a2fdd98ebbf9ae579cbceca3058cff946e13f8e17b90e3511db0508c723" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" [[package]] name = "enumflags2" @@ -213,7 +207,7 @@ checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -243,21 +237,21 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-task", @@ -273,9 +267,9 @@ checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" [[package]] name = "hash32" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" dependencies = [ "byteorder", ] @@ -288,36 +282,29 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heapless" -version = "0.7.16" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "atomic-polyfill 0.1.11", "hash32", - "rustc_version 0.4.0", - "spin", "stable_deref_trait", ] [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", "hashbrown", ] [[package]] -name = "lock_api" -version = "0.4.11" +name = "litrs" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "nb" @@ -352,6 +339,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + [[package]] name = "powerfmt" version = "0.2.0" @@ -384,18 +377,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -427,7 +420,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "857ce76a2517808a303bcb7e5b6d4a9c1d84e5de88b302aec2e53744633c0f4d" dependencies = [ - "atomic-polyfill 1.0.3", + "atomic-polyfill", "bare-metal 1.0.0", "cortex-m", "critical-section", @@ -466,33 +459,34 @@ dependencies = [ [[package]] name = "rtic-monotonics" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75936ddc03d8946dd256c89270501186916db5505692e1207912404231a05774" +checksum = "058c2397dbd5bb4c5650a0e368c3920953e458805ff5097a0511b8147b3619d7" dependencies = [ - "atomic-polyfill 1.0.3", + "atomic-polyfill", "cfg-if", - "embedded-hal 1.0.0-rc.1", + "embedded-hal 1.0.0", "fugit", "rtic-time", ] [[package]] name = "rtic-sync" -version = "1.0.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc586db4c7ee4a85482ebb0542f34ffaee16bd8b8c552081f07492f531aca9f" +checksum = "5a243123bcfb0bbbbf27b89c13de35670875a8725ec69763062e8a5903e69e93" dependencies = [ "critical-section", "heapless", + "portable-atomic", "rtic-common", ] [[package]] name = "rtic-time" -version = "1.0.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55127cfa37ad32522eca2b70a12298bdb035c75ee3a4e403af8773ffe1a64bd3" +checksum = "75b232e7aebc045cfea81cdd164bc2727a10aca9a4568d406d0a5661cdfd0f19" dependencies = [ "critical-section", "futures-util", @@ -505,24 +499,9 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 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]] name = "semver" version = "0.9.0" @@ -532,27 +511,12 @@ dependencies = [ "semver-parser", ] -[[package]] -name = "semver" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" - [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "stable_deref_trait" version = "1.2.0" @@ -573,16 +537,17 @@ dependencies = [ [[package]] name = "stm32f4xx-hal" -version = "0.18.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80faf7c1b60e623f84584c5eddb634618e11afb5634eb871b678ef9251cef0a1" +checksum = "10c41454f262c0be0c35b8cfc0d971e598281f7a9be32e894dc97a0b21deadfe" dependencies = [ "bare-metal 1.0.0", "cortex-m", "cortex-m-rt", + "document-features", "embedded-dma", "embedded-hal 0.2.7", - "embedded-hal 1.0.0-rc.1", + "embedded-hal 1.0.0", "embedded-hal-nb", "embedded-storage", "enumflags2", @@ -609,9 +574,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -620,29 +585,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "time" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "powerfmt", diff --git a/examples/stm32f411_rtc_interrupt/Cargo.toml b/examples/stm32f411_rtc_interrupt/Cargo.toml index 90053a2c28..e8ccbf215c 100644 --- a/examples/stm32f411_rtc_interrupt/Cargo.toml +++ b/examples/stm32f411_rtc_interrupt/Cargo.toml @@ -18,8 +18,8 @@ defmt-rtt = { version = "0.4.0"} rtic-sync = "1.0.2" [dependencies.stm32f4xx-hal] -version = "0.18.0" -features = ["rt", "stm32f411"] # replace the model of your microcontroller here +version = "0.20.0" +features = ["stm32f411"] # replace the model of your microcontroller here # this lets you use `cargo fix`! [[bin]] diff --git a/examples/stm32f411_rtc_interrupt/README.md b/examples/stm32f411_rtc_interrupt/README.md index 55b7a7d645..689ea9d36c 100644 --- a/examples/stm32f411_rtc_interrupt/README.md +++ b/examples/stm32f411_rtc_interrupt/README.md @@ -6,7 +6,7 @@ After configured, it will listen to periodic wake-up interrupts happening every ## How-to ### 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 Install `probe-rs` and configure it using the [debugging extension for VScode](https://probe.rs/docs/tools/debugger/). diff --git a/examples/stm32f411_rtc_interrupt/src/main.rs b/examples/stm32f411_rtc_interrupt/src/main.rs index 71ce96f8ae..55bebeed78 100644 --- a/examples/stm32f411_rtc_interrupt/src/main.rs +++ b/examples/stm32f411_rtc_interrupt/src/main.rs @@ -2,7 +2,6 @@ #![deny(warnings)] #![no_main] #![no_std] -#![feature(type_alias_impl_trait)] use panic_halt as _; diff --git a/examples/teensy4_blinky/examples/with_logs.rs b/examples/teensy4_blinky/examples/with_logs.rs index e8442464fb..82c7154690 100644 --- a/examples/teensy4_blinky/examples/with_logs.rs +++ b/examples/teensy4_blinky/examples/with_logs.rs @@ -1,7 +1,6 @@ #![deny(warnings)] #![no_main] #![no_std] -#![feature(type_alias_impl_trait)] use bsp::pins::common::{P0, P1}; imxrt_uart_panic::register!(LPUART6, P1, P0, 115200, teensy4_panic::sos); diff --git a/examples/teensy4_blinky/src/main.rs b/examples/teensy4_blinky/src/main.rs index fad088c45f..443e6059a6 100644 --- a/examples/teensy4_blinky/src/main.rs +++ b/examples/teensy4_blinky/src/main.rs @@ -2,7 +2,6 @@ #![deny(warnings)] #![no_main] #![no_std] -#![feature(type_alias_impl_trait)] #[panic_handler] fn panic(_: &::core::panic::PanicInfo) -> ! { diff --git a/rtic-macros/CHANGELOG.md b/rtic-macros/CHANGELOG.md index daee6c3864..8e7947068c 100644 --- a/rtic-macros/CHANGELOG.md +++ b/rtic-macros/CHANGELOG.md @@ -9,6 +9,7 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top! ### Added +- RTIC v2 now works on stable. - Unstable ESP32-C3 support. ### Changed diff --git a/rtic-macros/src/codegen/async_dispatchers.rs b/rtic-macros/src/codegen/async_dispatchers.rs index 54db2b3453..9144b2a3f1 100644 --- a/rtic-macros/src/codegen/async_dispatchers.rs +++ b/rtic-macros/src/codegen/async_dispatchers.rs @@ -2,7 +2,7 @@ use crate::syntax::ast::App; use crate::{ analyze::Analysis, codegen::{ - bindings::{async_entry, interrupt_entry, interrupt_exit, handler_config}, + bindings::{async_entry, handler_config, interrupt_entry, interrupt_exit}, util, }, }; @@ -17,15 +17,12 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { // Generate executor definition and priority in global scope 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"); items.push(quote!( - #[allow(non_camel_case_types)] - type #type_name = impl core::future::Future; #[allow(non_upper_case_globals)] - static #exec_name: rtic::export::executor::AsyncTaskExecutor<#type_name> = - rtic::export::executor::AsyncTaskExecutor::new(); + static #exec_name: rtic::export::executor::AsyncTaskExecutorPtr = + rtic::export::executor::AsyncTaskExecutorPtr::new(); )); } @@ -50,13 +47,18 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { for name in channel.tasks.iter() { 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 // let task = &app.software_tasks[name]; // let cfgs = &task.cfgs; stmts.push(quote!( - #exec_name.poll(|| { - #exec_name.set_pending(); + let exec = rtic::export::executor::AsyncTaskExecutor::#from_ptr_n_args(#name, &#exec_name); + exec.poll(|| { + let exec = rtic::export::executor::AsyncTaskExecutor::#from_ptr_n_args(#name, &#exec_name); + exec.set_pending(); #pend_interrupt }); )); @@ -68,7 +70,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { let entry_stmts = interrupt_entry(app, analysis); let exit_stmts = interrupt_exit(app, analysis); let async_entry_stmts = async_entry(app, analysis, dispatcher_name.clone()); - let config = handler_config(app,analysis,dispatcher_name.clone()); + let config = handler_config(app, analysis, dispatcher_name.clone()); items.push(quote!( #[allow(non_snake_case)] #[doc = #doc] diff --git a/rtic-macros/src/codegen/bindings/cortex.rs b/rtic-macros/src/codegen/bindings/cortex.rs index ffa024591c..69b5ee553e 100644 --- a/rtic-macros/src/codegen/bindings/cortex.rs +++ b/rtic-macros/src/codegen/bindings/cortex.rs @@ -29,11 +29,35 @@ fn is_exception(name: &Ident) -> bool { | "SysTick" ) } + pub fn interrupt_ident() -> Ident { let span = Span::call_site(); Ident::new("interrupt", span) } +pub fn check_stack_overflow_before_init( + _app: &App, + _analysis: &CodegenAnalysis, +) -> Vec { + 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")] mod source_masking { use super::*; diff --git a/rtic-macros/src/codegen/bindings/esp32c3.rs b/rtic-macros/src/codegen/bindings/esp32c3.rs index a8d58b7342..4b14caed43 100644 --- a/rtic-macros/src/codegen/bindings/esp32c3.rs +++ b/rtic-macros/src/codegen/bindings/esp32c3.rs @@ -72,7 +72,7 @@ mod esp32c3 { } pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec { let mut stmts = vec![]; - let mut curr_cpu_id:u8 = 1; //cpu interrupt id 0 is reserved + let mut curr_cpu_id: u8 = 1; //cpu interrupt id 0 is reserved let rt_err = util::rt_err_ident(); let max_prio: usize = 15; //unfortunately this is not part of pac, but we know that max prio is 15. let interrupt_ids = analysis.interrupts.iter().map(|(p, (id, _))| (p, id)); @@ -158,6 +158,29 @@ mod esp32c3 { vec![] } + pub fn check_stack_overflow_before_init( + _app: &App, + _analysis: &CodegenAnalysis, + ) -> Vec { + 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( _app: &App, _analysis: &CodegenAnalysis, @@ -199,11 +222,9 @@ mod esp32c3 { .values() .filter_map(|task| Some((&task.args.priority, &task.args.binds))), ) { - if *name == dispatcher_name{ - let ret = &("cpu_int_".to_owned()+&curr_cpu_id.to_string()+"_handler"); - stmts.push( - quote!(#[export_name = #ret]) - ); + if *name == dispatcher_name { + let ret = &("cpu_int_".to_owned() + &curr_cpu_id.to_string() + "_handler"); + stmts.push(quote!(#[export_name = #ret])); } curr_cpu_id += 1; } diff --git a/rtic-macros/src/codegen/bindings/template.rs b/rtic-macros/src/codegen/bindings/template.rs index d929dd8c8e..b5488b7ce9 100644 --- a/rtic-macros/src/codegen/bindings/template.rs +++ b/rtic-macros/src/codegen/bindings/template.rs @@ -43,6 +43,13 @@ pub fn interrupt_exit(_app: &App, _analysis: &CodegenAnalysis) -> Vec Vec { + vec![] +} + pub fn async_entry( _app: &App, _analysis: &CodegenAnalysis, diff --git a/rtic-macros/src/codegen/main.rs b/rtic-macros/src/codegen/main.rs index 3848ab0be6..56127962b4 100644 --- a/rtic-macros/src/codegen/main.rs +++ b/rtic-macros/src/codegen/main.rs @@ -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 quote::quote; -use super::{assertions, post_init, pre_init}; - /// Generates code for `fn main` pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { 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(); quote!(#dispatcher();) } 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 init_name = &app.init.name; + let msp_check = bindings::check_stack_overflow_before_init(app, analysis); + quote!( #[doc(hidden)] #[no_mangle] @@ -38,9 +55,15 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { 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. __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)* }); diff --git a/rtic-macros/src/codegen/module.rs b/rtic-macros/src/codegen/module.rs index 7d3ac54844..c8afe076fa 100644 --- a/rtic-macros/src/codegen/module.rs +++ b/rtic-macros/src/codegen/module.rs @@ -21,6 +21,11 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { 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 { 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!(core)); + values.push(quote!(executors_size)); } 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() { - Some(quote!(core: rtic::export::Peripherals,)) + Some(quote!(core: rtic::export::Peripherals, executors_size: usize)) } else { 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 from_ptr_n_args = util::from_ptr_n_args_ident(spawnee.inputs.len()); let (input_args, input_tupled, input_untupled, input_ty) = util::regroup_inputs(&spawnee.inputs); - let type_name = util::internal_task_ident(name, "F"); - // Spawn caller items.push(quote!( #(#cfgs)* @@ -159,18 +164,11 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { #[allow(non_snake_case)] #[doc(hidden)] 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. unsafe { - if #exec_name.try_allocate() { - let f = tait_hack(#(#input_untupled,)*); - #exec_name.spawn(f); + let exec = rtic::export::executor::AsyncTaskExecutor::#from_ptr_n_args(#name, &#exec_name); + if exec.try_allocate() { + exec.spawn(#name(unsafe { #name::Context::new() } #(,#input_untupled)*)); #pend_interrupt Ok(()) diff --git a/rtic-macros/src/codegen/util.rs b/rtic-macros/src/codegen/util.rs index 430e853e36..b4682ee8b5 100644 --- a/rtic-macros/src/codegen/util.rs +++ b/rtic-macros/src/codegen/util.rs @@ -8,7 +8,6 @@ pub use super::bindings::interrupt_ident; const RTIC_INTERNAL: &str = "__rtic_internal"; - /// Mark a name as internal pub fn mark_internal_name(name: &str) -> Ident { Ident::new(&format!("{RTIC_INTERNAL}_{name}"), Span::call_site()) @@ -166,3 +165,11 @@ pub fn rt_err_ident() -> Ident { 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()) +} diff --git a/rtic-monotonics/CHANGELOG.md b/rtic-monotonics/CHANGELOG.md index 609145a076..af391434d7 100644 --- a/rtic-monotonics/CHANGELOG.md +++ b/rtic-monotonics/CHANGELOG.md @@ -7,6 +7,10 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top! ## Unreleased +### Changed + +- Removed unused `rust-toolchain.toml` + ## v1.5.0 - 2024-01-10 ### Changed diff --git a/rtic-monotonics/rust-toolchain.toml b/rtic-monotonics/rust-toolchain.toml deleted file mode 100644 index e28b55de64..0000000000 --- a/rtic-monotonics/rust-toolchain.toml +++ /dev/null @@ -1,4 +0,0 @@ -[toolchain] -channel = "nightly" -components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] -targets = [ "thumbv6m-none-eabi", "thumbv7m-none-eabi" ] diff --git a/rtic/CHANGELOG.md b/rtic/CHANGELOG.md index 83c2b196ca..6fc9e3fe18 100644 --- a/rtic/CHANGELOG.md +++ b/rtic/CHANGELOG.md @@ -19,6 +19,8 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top! ### Changed +- RTIC v2 now works on stable. + ## [v2.0.1] - 2023-07-25 ### Added diff --git a/rtic/ci/expected/executor-size.run b/rtic/ci/expected/executor-size.run new file mode 100644 index 0000000000..2bb0d06bbc --- /dev/null +++ b/rtic/ci/expected/executor-size.run @@ -0,0 +1 @@ +init, total executor size = 9 diff --git a/rtic/examples/async-channel-done.rs b/rtic/examples/async-channel-done.rs index 62ed656c68..e9b98879c1 100644 --- a/rtic/examples/async-channel-done.rs +++ b/rtic/examples/async-channel-done.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/async-channel-no-receiver.rs b/rtic/examples/async-channel-no-receiver.rs index ab590e6236..7e416beb09 100644 --- a/rtic/examples/async-channel-no-receiver.rs +++ b/rtic/examples/async-channel-no-receiver.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/async-channel-no-sender.rs b/rtic/examples/async-channel-no-sender.rs index 852dc1d27f..c4f043c5d5 100644 --- a/rtic/examples/async-channel-no-sender.rs +++ b/rtic/examples/async-channel-no-sender.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/async-channel-try.rs b/rtic/examples/async-channel-try.rs index 2e2af52e5d..92c6ab68b5 100644 --- a/rtic/examples/async-channel-try.rs +++ b/rtic/examples/async-channel-try.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/async-channel.rs b/rtic/examples/async-channel.rs index 9798901a4d..642e218c33 100644 --- a/rtic/examples/async-channel.rs +++ b/rtic/examples/async-channel.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/async-delay.rs b/rtic/examples/async-delay.rs index 98d67f9c6b..9ccfc02aba 100644 --- a/rtic/examples/async-delay.rs +++ b/rtic/examples/async-delay.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/async-task-multiple-prios.rs b/rtic/examples/async-task-multiple-prios.rs index 7580b51c31..39b6d60168 100644 --- a/rtic/examples/async-task-multiple-prios.rs +++ b/rtic/examples/async-task-multiple-prios.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/async-task.rs b/rtic/examples/async-task.rs index 1ca1802160..1867c4d15a 100644 --- a/rtic/examples/async-task.rs +++ b/rtic/examples/async-task.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/async-timeout.rs b/rtic/examples/async-timeout.rs index 341a501083..e5e129f405 100644 --- a/rtic/examples/async-timeout.rs +++ b/rtic/examples/async-timeout.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use cortex_m_semihosting::{debug, hprintln}; use panic_semihosting as _; diff --git a/rtic/examples/big-struct-opt.rs b/rtic/examples/big-struct-opt.rs index 4326247a8b..109cc5dc27 100644 --- a/rtic/examples/big-struct-opt.rs +++ b/rtic/examples/big-struct-opt.rs @@ -7,7 +7,6 @@ #![no_std] #![deny(warnings)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/common.rs b/rtic/examples/common.rs index 27ad0ad917..7f6873907b 100644 --- a/rtic/examples/common.rs +++ b/rtic/examples/common.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/destructure.rs b/rtic/examples/destructure.rs index dd1633c08c..ac351878ef 100644 --- a/rtic/examples/destructure.rs +++ b/rtic/examples/destructure.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/executor-size.rs b/rtic/examples/executor-size.rs new file mode 100644 index 0000000000..d825729a11 --- /dev/null +++ b/rtic/examples/executor-size.rs @@ -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); + } +} diff --git a/rtic/examples/extern_spawn.rs b/rtic/examples/extern_spawn.rs index 2ab5550cbb..7f68b4268f 100644 --- a/rtic/examples/extern_spawn.rs +++ b/rtic/examples/extern_spawn.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use cortex_m_semihosting::{debug, hprintln}; use panic_semihosting as _; diff --git a/rtic/examples/locals.rs b/rtic/examples/locals.rs index f01027cfc0..5d5e246d49 100644 --- a/rtic/examples/locals.rs +++ b/rtic/examples/locals.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/lock-free.rs b/rtic/examples/lock-free.rs index c17d70d36b..c9d2ab0542 100644 --- a/rtic/examples/lock-free.rs +++ b/rtic/examples/lock-free.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/lock.rs b/rtic/examples/lock.rs index c09d99db12..091a1b016a 100644 --- a/rtic/examples/lock.rs +++ b/rtic/examples/lock.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/multilock.rs b/rtic/examples/multilock.rs index ba9588bfdb..77245aeaad 100644 --- a/rtic/examples/multilock.rs +++ b/rtic/examples/multilock.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/not-sync.rs b/rtic/examples/not-sync.rs index 1a7986420c..09ba77e927 100644 --- a/rtic/examples/not-sync.rs +++ b/rtic/examples/not-sync.rs @@ -4,7 +4,6 @@ #![no_std] #![deny(warnings)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use core::marker::PhantomData; use panic_semihosting as _; diff --git a/rtic/examples/only-shared-access.rs b/rtic/examples/only-shared-access.rs index 23ae67ef63..c83dca597f 100644 --- a/rtic/examples/only-shared-access.rs +++ b/rtic/examples/only-shared-access.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/pool.rs_old b/rtic/examples/pool.rs_old index 92c10c4339..b399202b51 100644 --- a/rtic/examples/pool.rs_old +++ b/rtic/examples/pool.rs_old @@ -3,7 +3,6 @@ #![no_main] #![no_std] #![deny(warnings)] -#![feature(type_alias_impl_trait)] use heapless::{ pool, diff --git a/rtic/examples/preempt.rs b/rtic/examples/preempt.rs index f1a92b0231..62c67dc6d7 100644 --- a/rtic/examples/preempt.rs +++ b/rtic/examples/preempt.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; use rtic::app; diff --git a/rtic/examples/prio-inversion.rs b/rtic/examples/prio-inversion.rs index 1c2f7fd851..36dcbe24a8 100644 --- a/rtic/examples/prio-inversion.rs +++ b/rtic/examples/prio-inversion.rs @@ -7,7 +7,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; use rtic::app; diff --git a/rtic/examples/ramfunc.rs b/rtic/examples/ramfunc.rs index 11349268be..d072ecb7ee 100644 --- a/rtic/examples/ramfunc.rs +++ b/rtic/examples/ramfunc.rs @@ -4,7 +4,6 @@ #![no_main] #![no_std] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/spawn.rs b/rtic/examples/spawn.rs index 58f9bc00c0..448bcda2eb 100644 --- a/rtic/examples/spawn.rs +++ b/rtic/examples/spawn.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/spawn_arguments.rs b/rtic/examples/spawn_arguments.rs index 5ca700fba1..61c4608555 100644 --- a/rtic/examples/spawn_arguments.rs +++ b/rtic/examples/spawn_arguments.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/spawn_err.rs b/rtic/examples/spawn_err.rs index abe62953bd..e5a942021c 100644 --- a/rtic/examples/spawn_err.rs +++ b/rtic/examples/spawn_err.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/spawn_loop.rs b/rtic/examples/spawn_loop.rs index 2da25d1472..13e386a479 100644 --- a/rtic/examples/spawn_loop.rs +++ b/rtic/examples/spawn_loop.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/static.rs b/rtic/examples/static.rs index aa39940ee8..fec73fc236 100644 --- a/rtic/examples/static.rs +++ b/rtic/examples/static.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/task.rs b/rtic/examples/task.rs index 9b06bb49c8..b6b6bbd55b 100644 --- a/rtic/examples/task.rs +++ b/rtic/examples/task.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use panic_semihosting as _; diff --git a/rtic/examples/zero-prio-task.rs b/rtic/examples/zero-prio-task.rs index dbe1959e67..8cfd7053be 100644 --- a/rtic/examples/zero-prio-task.rs +++ b/rtic/examples/zero-prio-task.rs @@ -5,7 +5,6 @@ #![deny(warnings)] #![deny(unsafe_code)] #![deny(missing_docs)] -#![feature(type_alias_impl_trait)] use core::marker::PhantomData; use panic_semihosting as _; diff --git a/rtic/src/export/cortex_common.rs b/rtic/src/export/cortex_common.rs index 112d9c960b..443e24d932 100644 --- a/rtic/src/export/cortex_common.rs +++ b/rtic/src/export/cortex_common.rs @@ -1,4 +1,4 @@ -pub use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC}; +pub use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC, register::msp}; #[inline] #[must_use] diff --git a/rtic/src/export/executor.rs b/rtic/src/export/executor.rs index 36e47d7e43..5d808a14d9 100644 --- a/rtic/src/export/executor.rs +++ b/rtic/src/export/executor.rs @@ -1,8 +1,8 @@ -use super::atomic::{AtomicBool, Ordering}; +use super::atomic::{AtomicBool, AtomicPtr, Ordering}; use core::{ cell::UnsafeCell, future::Future, - mem::{self, MaybeUninit}, + mem::{self, ManuallyDrop, MaybeUninit}, pin::Pin, task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, }; @@ -28,6 +28,30 @@ unsafe fn waker_drop(_: *const ()) { //============ // 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(&self, executor: &ManuallyDrop>) { + 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. pub struct AsyncTaskExecutor { // `task` is protected by the `running` flag. @@ -38,6 +62,24 @@ pub struct AsyncTaskExecutor { unsafe impl Sync for AsyncTaskExecutor {} +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 AsyncTaskExecutor { /// Create a new executor. #[inline(always)] @@ -49,6 +91,55 @@ impl AsyncTaskExecutor { } } + // 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. #[inline(always)] pub fn is_running(&self) -> bool { diff --git a/rtic/src/export/riscv_common.rs b/rtic/src/export/riscv_common.rs index 06c3968659..6189335f0d 100644 --- a/rtic/src/export/riscv_common.rs +++ b/rtic/src/export/riscv_common.rs @@ -1,2 +1,10 @@ /// GENERIC RE-EXPORTS: needed for all RTIC backends 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 +} diff --git a/rtic/src/lib.rs b/rtic/src/lib.rs index e394ea3f5e..bbdd5e23f1 100644 --- a/rtic/src/lib.rs +++ b/rtic/src/lib.rs @@ -9,8 +9,8 @@ //! //! # Minimum Supported Rust Version (MSRV) //! -//! This crate is compiled and tested with the latest nightly toolchain (rolling). -//! If you run into compilation errors, try the latest nightly release of the rust toolchain. +//! This crate is compiled and tested with the latest stable toolchain (rolling). +//! If you run into compilation errors, try the latest stable release of the rust toolchain. //! //! # Semantic Versioning //! diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 339b5f23c8..40cbafa1c3 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly" +channel = "stable" components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] targets = [ "thumbv6m-none-eabi", "thumbv7m-none-eabi", "thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi" ] diff --git a/xtask/src/cargo_command.rs b/xtask/src/cargo_command.rs index 1d5f3c5730..c5387c2703 100644 --- a/xtask/src/cargo_command.rs +++ b/xtask/src/cargo_command.rs @@ -483,7 +483,7 @@ impl<'a> CargoCommand<'a> { // Target is added by build_args target: _, } => self.build_args( - true, + false, cargoarg, features, Some(mode), @@ -501,7 +501,7 @@ impl<'a> CargoCommand<'a> { // deny_warnings is exposed through `extra_env` deny_warnings: _, } => self.build_args( - true, + false, cargoarg, features, Some(mode), @@ -518,7 +518,7 @@ impl<'a> CargoCommand<'a> { dir: _, // deny_warnings is exposed through `extra_env` deny_warnings: _, - } => self.build_args(true, cargoarg, features, Some(mode), p(package)), + } => self.build_args(false, cargoarg, features, Some(mode), p(package)), CargoCommand::Check { cargoarg, package, @@ -530,7 +530,7 @@ impl<'a> CargoCommand<'a> { target: _, // deny_warnings is exposed through `extra_env` deny_warnings: _, - } => self.build_args(true, cargoarg, features, Some(mode), p(package)), + } => self.build_args(false, cargoarg, features, Some(mode), p(package)), CargoCommand::Clippy { cargoarg, package, @@ -546,7 +546,7 @@ impl<'a> CargoCommand<'a> { }; 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 { cargoarg, @@ -556,7 +556,7 @@ impl<'a> CargoCommand<'a> { deny_warnings: _, } => { 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 { package, @@ -572,7 +572,7 @@ impl<'a> CargoCommand<'a> { }; let package = p(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 } => { let mut args = vec![]; @@ -597,7 +597,7 @@ impl<'a> CargoCommand<'a> { let extra = if *check_only { Some("--check") } else { None }; let package = p(package); self.build_args( - true, + false, cargoarg, &None, None, @@ -616,7 +616,7 @@ impl<'a> CargoCommand<'a> { // deny_warnings is exposed through `extra_env` deny_warnings: _, } => self.build_args( - true, + false, cargoarg, features, Some(mode), @@ -632,7 +632,7 @@ impl<'a> CargoCommand<'a> { // deny_warnings is exposed through `extra_env` deny_warnings: _, } => self.build_args( - true, + false, cargoarg, features, Some(mode), @@ -655,7 +655,7 @@ impl<'a> CargoCommand<'a> { .into_iter() .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) } } }