diff options
Diffstat (limited to 'embassy-executor')
| -rw-r--r-- | embassy-executor/CHANGELOG.md | 4 | ||||
| -rw-r--r-- | embassy-executor/Cargo.toml | 100 | ||||
| -rw-r--r-- | embassy-executor/README.md | 2 | ||||
| -rw-r--r-- | embassy-executor/gen_config.py | 6 | ||||
| -rw-r--r-- | embassy-executor/src/arch/avr.rs | 72 | ||||
| -rw-r--r-- | embassy-executor/src/arch/riscv32.rs | 2 | ||||
| -rw-r--r-- | embassy-executor/src/fmt.rs | 3 | ||||
| -rw-r--r-- | embassy-executor/src/lib.rs | 6 | ||||
| -rw-r--r-- | embassy-executor/src/raw/mod.rs | 39 | ||||
| -rw-r--r-- | embassy-executor/src/raw/timer_queue.rs | 12 | ||||
| -rw-r--r-- | embassy-executor/tests/test.rs | 16 |
11 files changed, 218 insertions, 44 deletions
diff --git a/embassy-executor/CHANGELOG.md b/embassy-executor/CHANGELOG.md index 5c6749230..77c64fd8e 100644 --- a/embassy-executor/CHANGELOG.md +++ b/embassy-executor/CHANGELOG.md | |||
| @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 7 | 7 | ||
| 8 | ## Unreleased | 8 | ## Unreleased |
| 9 | 9 | ||
| 10 | ## 0.5.0 - 2024-01-11 | ||
| 11 | |||
| 12 | - Updated to `embassy-time-driver 0.1`, `embassy-time-queue-driver 0.1`, compatible with `embassy-time v0.3` and higher. | ||
| 13 | |||
| 10 | ## 0.4.0 - 2023-12-05 | 14 | ## 0.4.0 - 2023-12-05 |
| 11 | 15 | ||
| 12 | - Removed `arch-xtensa`. Use the executor provided by the HAL crate (`esp-hal`, `esp32s3-hal`, etc...) instead. | 16 | - Removed `arch-xtensa`. Use the executor provided by the HAL crate (`esp-hal`, `esp32s3-hal`, etc...) instead. |
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index ec5aca46d..431165cee 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml | |||
| @@ -1,10 +1,11 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "embassy-executor" | 2 | name = "embassy-executor" |
| 3 | version = "0.4.0" | 3 | version = "0.5.0" |
| 4 | edition = "2021" | 4 | edition = "2021" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | description = "async/await executor designed for embedded usage" | 6 | description = "async/await executor designed for embedded usage" |
| 7 | repository = "https://github.com/embassy-rs/embassy" | 7 | repository = "https://github.com/embassy-rs/embassy" |
| 8 | documentation = "https://docs.embassy.dev/embassy-executor" | ||
| 8 | categories = [ | 9 | categories = [ |
| 9 | "embedded", | 10 | "embedded", |
| 10 | "no-std", | 11 | "no-std", |
| @@ -14,7 +15,7 @@ categories = [ | |||
| 14 | [package.metadata.embassy_docs] | 15 | [package.metadata.embassy_docs] |
| 15 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/" | 16 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-executor-v$VERSION/embassy-executor/src/" |
| 16 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/" | 17 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-executor/src/" |
| 17 | features = ["nightly", "defmt"] | 18 | features = ["defmt"] |
| 18 | flavors = [ | 19 | flavors = [ |
| 19 | { name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] }, | 20 | { name = "std", target = "x86_64-unknown-linux-gnu", features = ["arch-std", "executor-thread"] }, |
| 20 | { name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] }, | 21 | { name = "wasm", target = "wasm32-unknown-unknown", features = ["arch-wasm", "executor-thread"] }, |
| @@ -25,7 +26,7 @@ flavors = [ | |||
| 25 | [package.metadata.docs.rs] | 26 | [package.metadata.docs.rs] |
| 26 | default-target = "thumbv7em-none-eabi" | 27 | default-target = "thumbv7em-none-eabi" |
| 27 | targets = ["thumbv7em-none-eabi"] | 28 | targets = ["thumbv7em-none-eabi"] |
| 28 | features = ["nightly", "defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"] | 29 | features = ["defmt", "arch-cortex-m", "executor-thread", "executor-interrupt"] |
| 29 | 30 | ||
| 30 | [dependencies] | 31 | [dependencies] |
| 31 | defmt = { version = "0.3", optional = true } | 32 | defmt = { version = "0.3", optional = true } |
| @@ -33,11 +34,13 @@ log = { version = "0.4.14", optional = true } | |||
| 33 | rtos-trace = { version = "0.1.2", optional = true } | 34 | rtos-trace = { version = "0.1.2", optional = true } |
| 34 | 35 | ||
| 35 | embassy-executor-macros = { version = "0.4.0", path = "../embassy-executor-macros" } | 36 | embassy-executor-macros = { version = "0.4.0", path = "../embassy-executor-macros" } |
| 36 | embassy-time = { version = "0.2", path = "../embassy-time", optional = true} | 37 | embassy-time-driver = { version = "0.1.0", path = "../embassy-time-driver", optional = true } |
| 38 | embassy-time-queue-driver = { version = "0.1.0", path = "../embassy-time-queue-driver", optional = true } | ||
| 37 | critical-section = "1.1" | 39 | critical-section = "1.1" |
| 38 | 40 | ||
| 39 | # needed for riscv | 41 | document-features = "0.2.7" |
| 40 | # remove when https://github.com/rust-lang/rust/pull/114499 is merged | 42 | |
| 43 | # needed for AVR | ||
| 41 | portable-atomic = { version = "1.5", optional = true } | 44 | portable-atomic = { version = "1.5", optional = true } |
| 42 | 45 | ||
| 43 | # arch-cortex-m dependencies | 46 | # arch-cortex-m dependencies |
| @@ -47,72 +50,137 @@ cortex-m = { version = "0.7.6", optional = true } | |||
| 47 | wasm-bindgen = { version = "0.2.82", optional = true } | 50 | wasm-bindgen = { version = "0.2.82", optional = true } |
| 48 | js-sys = { version = "0.3", optional = true } | 51 | js-sys = { version = "0.3", optional = true } |
| 49 | 52 | ||
| 53 | # arch-avr dependencies | ||
| 54 | avr-device = { version = "0.5.3", optional = true } | ||
| 55 | |||
| 50 | [dev-dependencies] | 56 | [dev-dependencies] |
| 51 | critical-section = { version = "1.1", features = ["std"] } | 57 | critical-section = { version = "1.1", features = ["std"] } |
| 52 | 58 | ||
| 53 | 59 | ||
| 54 | [features] | 60 | [features] |
| 55 | 61 | ||
| 56 | # Architecture | 62 | ## Enable nightly-only features |
| 63 | nightly = ["embassy-executor-macros/nightly"] | ||
| 64 | |||
| 65 | # Enables turbo wakers, which requires patching core. Not surfaced in the docs by default due to | ||
| 66 | # being an complicated advanced and undocumented feature. | ||
| 67 | # See: https://github.com/embassy-rs/embassy/pull/1263 | ||
| 68 | turbowakers = [] | ||
| 69 | |||
| 70 | ## Use the executor-integrated `embassy-time` timer queue. | ||
| 71 | integrated-timers = ["dep:embassy-time-driver", "dep:embassy-time-queue-driver"] | ||
| 72 | |||
| 73 | #! ### Architecture | ||
| 57 | _arch = [] # some arch was picked | 74 | _arch = [] # some arch was picked |
| 75 | ## std | ||
| 58 | arch-std = ["_arch", "critical-section/std"] | 76 | arch-std = ["_arch", "critical-section/std"] |
| 77 | ## Cortex-M | ||
| 59 | arch-cortex-m = ["_arch", "dep:cortex-m"] | 78 | arch-cortex-m = ["_arch", "dep:cortex-m"] |
| 60 | arch-riscv32 = ["_arch", "dep:portable-atomic"] | 79 | ## RISC-V 32 |
| 80 | arch-riscv32 = ["_arch"] | ||
| 81 | ## WASM | ||
| 61 | arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"] | 82 | arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"] |
| 83 | ## AVR | ||
| 84 | arch-avr = ["_arch", "dep:portable-atomic", "dep:avr-device"] | ||
| 62 | 85 | ||
| 63 | # Enable the thread-mode executor (using WFE/SEV in Cortex-M, WFI in other embedded archs) | 86 | #! ### Executor |
| 87 | |||
| 88 | ## Enable the thread-mode executor (using WFE/SEV in Cortex-M, WFI in other embedded archs) | ||
| 64 | executor-thread = [] | 89 | executor-thread = [] |
| 65 | # Enable the interrupt-mode executor (available in Cortex-M only) | 90 | ## Enable the interrupt-mode executor (available in Cortex-M only) |
| 66 | executor-interrupt = [] | 91 | executor-interrupt = [] |
| 67 | 92 | ||
| 68 | # Enable nightly-only features | 93 | #! ### Task Arena Size |
| 69 | nightly = ["embassy-executor-macros/nightly"] | 94 | #! Sets the [task arena](#task-arena) size. Necessary if you’re not using `nightly`. |
| 70 | 95 | #! | |
| 71 | turbowakers = [] | 96 | #! <details> |
| 72 | 97 | #! <summary>Preconfigured Task Arena Sizes:</summary> | |
| 73 | integrated-timers = ["dep:embassy-time"] | 98 | #! <!-- rustdoc requires the following blank line for the feature list to render correctly! --> |
| 99 | #! | ||
| 74 | 100 | ||
| 75 | # BEGIN AUTOGENERATED CONFIG FEATURES | 101 | # BEGIN AUTOGENERATED CONFIG FEATURES |
| 76 | # Generated by gen_config.py. DO NOT EDIT. | 102 | # Generated by gen_config.py. DO NOT EDIT. |
| 103 | ## 64 | ||
| 77 | task-arena-size-64 = [] | 104 | task-arena-size-64 = [] |
| 105 | ## 128 | ||
| 78 | task-arena-size-128 = [] | 106 | task-arena-size-128 = [] |
| 107 | ## 192 | ||
| 79 | task-arena-size-192 = [] | 108 | task-arena-size-192 = [] |
| 109 | ## 256 | ||
| 80 | task-arena-size-256 = [] | 110 | task-arena-size-256 = [] |
| 111 | ## 320 | ||
| 81 | task-arena-size-320 = [] | 112 | task-arena-size-320 = [] |
| 113 | ## 384 | ||
| 82 | task-arena-size-384 = [] | 114 | task-arena-size-384 = [] |
| 115 | ## 512 | ||
| 83 | task-arena-size-512 = [] | 116 | task-arena-size-512 = [] |
| 117 | ## 640 | ||
| 84 | task-arena-size-640 = [] | 118 | task-arena-size-640 = [] |
| 119 | ## 768 | ||
| 85 | task-arena-size-768 = [] | 120 | task-arena-size-768 = [] |
| 121 | ## 1024 | ||
| 86 | task-arena-size-1024 = [] | 122 | task-arena-size-1024 = [] |
| 123 | ## 1280 | ||
| 87 | task-arena-size-1280 = [] | 124 | task-arena-size-1280 = [] |
| 125 | ## 1536 | ||
| 88 | task-arena-size-1536 = [] | 126 | task-arena-size-1536 = [] |
| 127 | ## 2048 | ||
| 89 | task-arena-size-2048 = [] | 128 | task-arena-size-2048 = [] |
| 129 | ## 2560 | ||
| 90 | task-arena-size-2560 = [] | 130 | task-arena-size-2560 = [] |
| 131 | ## 3072 | ||
| 91 | task-arena-size-3072 = [] | 132 | task-arena-size-3072 = [] |
| 133 | ## 4096 (default) | ||
| 92 | task-arena-size-4096 = [] # Default | 134 | task-arena-size-4096 = [] # Default |
| 135 | ## 5120 | ||
| 93 | task-arena-size-5120 = [] | 136 | task-arena-size-5120 = [] |
| 137 | ## 6144 | ||
| 94 | task-arena-size-6144 = [] | 138 | task-arena-size-6144 = [] |
| 139 | ## 8192 | ||
| 95 | task-arena-size-8192 = [] | 140 | task-arena-size-8192 = [] |
| 141 | ## 10240 | ||
| 96 | task-arena-size-10240 = [] | 142 | task-arena-size-10240 = [] |
| 143 | ## 12288 | ||
| 97 | task-arena-size-12288 = [] | 144 | task-arena-size-12288 = [] |
| 145 | ## 16384 | ||
| 98 | task-arena-size-16384 = [] | 146 | task-arena-size-16384 = [] |
| 147 | ## 20480 | ||
| 99 | task-arena-size-20480 = [] | 148 | task-arena-size-20480 = [] |
| 149 | ## 24576 | ||
| 100 | task-arena-size-24576 = [] | 150 | task-arena-size-24576 = [] |
| 151 | ## 32768 | ||
| 101 | task-arena-size-32768 = [] | 152 | task-arena-size-32768 = [] |
| 153 | ## 40960 | ||
| 102 | task-arena-size-40960 = [] | 154 | task-arena-size-40960 = [] |
| 155 | ## 49152 | ||
| 103 | task-arena-size-49152 = [] | 156 | task-arena-size-49152 = [] |
| 157 | ## 65536 | ||
| 104 | task-arena-size-65536 = [] | 158 | task-arena-size-65536 = [] |
| 159 | ## 81920 | ||
| 105 | task-arena-size-81920 = [] | 160 | task-arena-size-81920 = [] |
| 161 | ## 98304 | ||
| 106 | task-arena-size-98304 = [] | 162 | task-arena-size-98304 = [] |
| 163 | ## 131072 | ||
| 107 | task-arena-size-131072 = [] | 164 | task-arena-size-131072 = [] |
| 165 | ## 163840 | ||
| 108 | task-arena-size-163840 = [] | 166 | task-arena-size-163840 = [] |
| 167 | ## 196608 | ||
| 109 | task-arena-size-196608 = [] | 168 | task-arena-size-196608 = [] |
| 169 | ## 262144 | ||
| 110 | task-arena-size-262144 = [] | 170 | task-arena-size-262144 = [] |
| 171 | ## 327680 | ||
| 111 | task-arena-size-327680 = [] | 172 | task-arena-size-327680 = [] |
| 173 | ## 393216 | ||
| 112 | task-arena-size-393216 = [] | 174 | task-arena-size-393216 = [] |
| 175 | ## 524288 | ||
| 113 | task-arena-size-524288 = [] | 176 | task-arena-size-524288 = [] |
| 177 | ## 655360 | ||
| 114 | task-arena-size-655360 = [] | 178 | task-arena-size-655360 = [] |
| 179 | ## 786432 | ||
| 115 | task-arena-size-786432 = [] | 180 | task-arena-size-786432 = [] |
| 181 | ## 1048576 | ||
| 116 | task-arena-size-1048576 = [] | 182 | task-arena-size-1048576 = [] |
| 117 | 183 | ||
| 118 | # END AUTOGENERATED CONFIG FEATURES | 184 | # END AUTOGENERATED CONFIG FEATURES |
| 185 | |||
| 186 | #! </details> | ||
diff --git a/embassy-executor/README.md b/embassy-executor/README.md index 80ecfc71a..aa9d59907 100644 --- a/embassy-executor/README.md +++ b/embassy-executor/README.md | |||
| @@ -22,7 +22,7 @@ Tasks are allocated from the arena when spawned for the first time. If the task | |||
| 22 | The arena size can be configured in two ways: | 22 | The arena size can be configured in two ways: |
| 23 | 23 | ||
| 24 | - Via Cargo features: enable a Cargo feature like `task-arena-size-8192`. Only a selection of values | 24 | - Via Cargo features: enable a Cargo feature like `task-arena-size-8192`. Only a selection of values |
| 25 | is available, check `Cargo.toml` for the list. | 25 | is available, see [Task Area Sizes](#task-arena-size) for reference. |
| 26 | - Via environment variables at build time: set the variable named `EMBASSY_EXECUTOR_TASK_ARENA_SIZE`. For example | 26 | - Via environment variables at build time: set the variable named `EMBASSY_EXECUTOR_TASK_ARENA_SIZE`. For example |
| 27 | `EMBASSY_EXECUTOR_TASK_ARENA_SIZE=4321 cargo build`. You can also set them in the `[env]` section of `.cargo/config.toml`. | 27 | `EMBASSY_EXECUTOR_TASK_ARENA_SIZE=4321 cargo build`. You can also set them in the `[env]` section of `.cargo/config.toml`. |
| 28 | Any value can be set, unlike with Cargo features. | 28 | Any value can be set, unlike with Cargo features. |
diff --git a/embassy-executor/gen_config.py b/embassy-executor/gen_config.py index e427d29f4..cf32bd530 100644 --- a/embassy-executor/gen_config.py +++ b/embassy-executor/gen_config.py | |||
| @@ -45,6 +45,12 @@ things = "" | |||
| 45 | for f in features: | 45 | for f in features: |
| 46 | name = f["name"].replace("_", "-") | 46 | name = f["name"].replace("_", "-") |
| 47 | for val in f["vals"]: | 47 | for val in f["vals"]: |
| 48 | things += f"## {val}" | ||
| 49 | if val == f["default"]: | ||
| 50 | things += " (default)\n" | ||
| 51 | else: | ||
| 52 | things += "\n" | ||
| 53 | |||
| 48 | things += f"{name}-{val} = []" | 54 | things += f"{name}-{val} = []" |
| 49 | if val == f["default"]: | 55 | if val == f["default"]: |
| 50 | things += " # Default" | 56 | things += " # Default" |
diff --git a/embassy-executor/src/arch/avr.rs b/embassy-executor/src/arch/avr.rs new file mode 100644 index 000000000..70085d04d --- /dev/null +++ b/embassy-executor/src/arch/avr.rs | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | #[cfg(feature = "executor-interrupt")] | ||
| 2 | compile_error!("`executor-interrupt` is not supported with `arch-avr`."); | ||
| 3 | |||
| 4 | #[cfg(feature = "executor-thread")] | ||
| 5 | pub use thread::*; | ||
| 6 | #[cfg(feature = "executor-thread")] | ||
| 7 | mod thread { | ||
| 8 | use core::marker::PhantomData; | ||
| 9 | |||
| 10 | pub use embassy_executor_macros::main_avr as main; | ||
| 11 | use portable_atomic::{AtomicBool, Ordering}; | ||
| 12 | |||
| 13 | use crate::{raw, Spawner}; | ||
| 14 | |||
| 15 | static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false); | ||
| 16 | |||
| 17 | #[export_name = "__pender"] | ||
| 18 | fn __pender(_context: *mut ()) { | ||
| 19 | SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst); | ||
| 20 | } | ||
| 21 | |||
| 22 | /// avr Executor | ||
| 23 | pub struct Executor { | ||
| 24 | inner: raw::Executor, | ||
| 25 | not_send: PhantomData<*mut ()>, | ||
| 26 | } | ||
| 27 | |||
| 28 | impl Executor { | ||
| 29 | /// Create a new Executor. | ||
| 30 | pub fn new() -> Self { | ||
| 31 | Self { | ||
| 32 | inner: raw::Executor::new(core::ptr::null_mut()), | ||
| 33 | not_send: PhantomData, | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | /// Run the executor. | ||
| 38 | /// | ||
| 39 | /// The `init` closure is called with a [`Spawner`] that spawns tasks on | ||
| 40 | /// this executor. Use it to spawn the initial task(s). After `init` returns, | ||
| 41 | /// the executor starts running the tasks. | ||
| 42 | /// | ||
| 43 | /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`), | ||
| 44 | /// for example by passing it as an argument to the initial tasks. | ||
| 45 | /// | ||
| 46 | /// This function requires `&'static mut self`. This means you have to store the | ||
| 47 | /// Executor instance in a place where it'll live forever and grants you mutable | ||
| 48 | /// access. There's a few ways to do this: | ||
| 49 | /// | ||
| 50 | /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe) | ||
| 51 | /// - a `static mut` (unsafe) | ||
| 52 | /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) | ||
| 53 | /// | ||
| 54 | /// This function never returns. | ||
| 55 | pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { | ||
| 56 | init(self.inner.spawner()); | ||
| 57 | |||
| 58 | loop { | ||
| 59 | unsafe { | ||
| 60 | avr_device::interrupt::disable(); | ||
| 61 | if !SIGNAL_WORK_THREAD_MODE.swap(false, Ordering::SeqCst) { | ||
| 62 | avr_device::interrupt::enable(); | ||
| 63 | avr_device::asm::sleep(); | ||
| 64 | } else { | ||
| 65 | avr_device::interrupt::enable(); | ||
| 66 | self.inner.poll(); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | } | ||
| 72 | } | ||
diff --git a/embassy-executor/src/arch/riscv32.rs b/embassy-executor/src/arch/riscv32.rs index c56f502d3..01e63a9fd 100644 --- a/embassy-executor/src/arch/riscv32.rs +++ b/embassy-executor/src/arch/riscv32.rs | |||
| @@ -6,9 +6,9 @@ pub use thread::*; | |||
| 6 | #[cfg(feature = "executor-thread")] | 6 | #[cfg(feature = "executor-thread")] |
| 7 | mod thread { | 7 | mod thread { |
| 8 | use core::marker::PhantomData; | 8 | use core::marker::PhantomData; |
| 9 | use core::sync::atomic::{AtomicBool, Ordering}; | ||
| 9 | 10 | ||
| 10 | pub use embassy_executor_macros::main_riscv as main; | 11 | pub use embassy_executor_macros::main_riscv as main; |
| 11 | use portable_atomic::{AtomicBool, Ordering}; | ||
| 12 | 12 | ||
| 13 | use crate::{raw, Spawner}; | 13 | use crate::{raw, Spawner}; |
| 14 | 14 | ||
diff --git a/embassy-executor/src/fmt.rs b/embassy-executor/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-executor/src/fmt.rs +++ b/embassy-executor/src/fmt.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | #![allow(unused_macros)] | 2 | #![allow(unused)] |
| 3 | 3 | ||
| 4 | use core::fmt::{Debug, Display, LowerHex}; | 4 | use core::fmt::{Debug, Display, LowerHex}; |
| 5 | 5 | ||
| @@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> { | |||
| 229 | } | 229 | } |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | #[allow(unused)] | ||
| 233 | pub(crate) struct Bytes<'a>(pub &'a [u8]); | 232 | pub(crate) struct Bytes<'a>(pub &'a [u8]); |
| 234 | 233 | ||
| 235 | impl<'a> Debug for Bytes<'a> { | 234 | impl<'a> Debug for Bytes<'a> { |
diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index 4c6900a6d..6a2e493a2 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs | |||
| @@ -3,6 +3,9 @@ | |||
| 3 | #![doc = include_str!("../README.md")] | 3 | #![doc = include_str!("../README.md")] |
| 4 | #![warn(missing_docs)] | 4 | #![warn(missing_docs)] |
| 5 | 5 | ||
| 6 | //! ## Feature flags | ||
| 7 | #![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)] | ||
| 8 | |||
| 6 | // This mod MUST go first, so that the others see its macros. | 9 | // This mod MUST go first, so that the others see its macros. |
| 7 | pub(crate) mod fmt; | 10 | pub(crate) mod fmt; |
| 8 | 11 | ||
| @@ -20,9 +23,10 @@ macro_rules! check_at_most_one { | |||
| 20 | check_at_most_one!(@amo [$($f)*] [$($f)*] []); | 23 | check_at_most_one!(@amo [$($f)*] [$($f)*] []); |
| 21 | }; | 24 | }; |
| 22 | } | 25 | } |
| 23 | check_at_most_one!("arch-cortex-m", "arch-riscv32", "arch-std", "arch-wasm",); | 26 | check_at_most_one!("arch-avr", "arch-cortex-m", "arch-riscv32", "arch-std", "arch-wasm",); |
| 24 | 27 | ||
| 25 | #[cfg(feature = "_arch")] | 28 | #[cfg(feature = "_arch")] |
| 29 | #[cfg_attr(feature = "arch-avr", path = "arch/avr.rs")] | ||
| 26 | #[cfg_attr(feature = "arch-cortex-m", path = "arch/cortex_m.rs")] | 30 | #[cfg_attr(feature = "arch-cortex-m", path = "arch/cortex_m.rs")] |
| 27 | #[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")] | 31 | #[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")] |
| 28 | #[cfg_attr(feature = "arch-std", path = "arch/std.rs")] | 32 | #[cfg_attr(feature = "arch-std", path = "arch/std.rs")] |
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index b16a1c7c3..d9ea5c005 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs | |||
| @@ -30,9 +30,7 @@ use core::ptr::NonNull; | |||
| 30 | use core::task::{Context, Poll}; | 30 | use core::task::{Context, Poll}; |
| 31 | 31 | ||
| 32 | #[cfg(feature = "integrated-timers")] | 32 | #[cfg(feature = "integrated-timers")] |
| 33 | use embassy_time::driver::{self, AlarmHandle}; | 33 | use embassy_time_driver::AlarmHandle; |
| 34 | #[cfg(feature = "integrated-timers")] | ||
| 35 | use embassy_time::Instant; | ||
| 36 | #[cfg(feature = "rtos-trace")] | 34 | #[cfg(feature = "rtos-trace")] |
| 37 | use rtos_trace::trace; | 35 | use rtos_trace::trace; |
| 38 | 36 | ||
| @@ -50,7 +48,7 @@ pub(crate) struct TaskHeader { | |||
| 50 | poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>, | 48 | poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>, |
| 51 | 49 | ||
| 52 | #[cfg(feature = "integrated-timers")] | 50 | #[cfg(feature = "integrated-timers")] |
| 53 | pub(crate) expires_at: SyncUnsafeCell<Instant>, | 51 | pub(crate) expires_at: SyncUnsafeCell<u64>, |
| 54 | #[cfg(feature = "integrated-timers")] | 52 | #[cfg(feature = "integrated-timers")] |
| 55 | pub(crate) timer_queue_item: timer_queue::TimerQueueItem, | 53 | pub(crate) timer_queue_item: timer_queue::TimerQueueItem, |
| 56 | } | 54 | } |
| @@ -123,7 +121,7 @@ impl<F: Future + 'static> TaskStorage<F> { | |||
| 123 | poll_fn: SyncUnsafeCell::new(None), | 121 | poll_fn: SyncUnsafeCell::new(None), |
| 124 | 122 | ||
| 125 | #[cfg(feature = "integrated-timers")] | 123 | #[cfg(feature = "integrated-timers")] |
| 126 | expires_at: SyncUnsafeCell::new(Instant::from_ticks(0)), | 124 | expires_at: SyncUnsafeCell::new(0), |
| 127 | #[cfg(feature = "integrated-timers")] | 125 | #[cfg(feature = "integrated-timers")] |
| 128 | timer_queue_item: timer_queue::TimerQueueItem::new(), | 126 | timer_queue_item: timer_queue::TimerQueueItem::new(), |
| 129 | }, | 127 | }, |
| @@ -164,7 +162,7 @@ impl<F: Future + 'static> TaskStorage<F> { | |||
| 164 | this.raw.state.despawn(); | 162 | this.raw.state.despawn(); |
| 165 | 163 | ||
| 166 | #[cfg(feature = "integrated-timers")] | 164 | #[cfg(feature = "integrated-timers")] |
| 167 | this.raw.expires_at.set(Instant::MAX); | 165 | this.raw.expires_at.set(u64::MAX); |
| 168 | } | 166 | } |
| 169 | Poll::Pending => {} | 167 | Poll::Pending => {} |
| 170 | } | 168 | } |
| @@ -328,7 +326,7 @@ pub(crate) struct SyncExecutor { | |||
| 328 | impl SyncExecutor { | 326 | impl SyncExecutor { |
| 329 | pub(crate) fn new(pender: Pender) -> Self { | 327 | pub(crate) fn new(pender: Pender) -> Self { |
| 330 | #[cfg(feature = "integrated-timers")] | 328 | #[cfg(feature = "integrated-timers")] |
| 331 | let alarm = unsafe { unwrap!(driver::allocate_alarm()) }; | 329 | let alarm = unsafe { unwrap!(embassy_time_driver::allocate_alarm()) }; |
| 332 | 330 | ||
| 333 | Self { | 331 | Self { |
| 334 | run_queue: RunQueue::new(), | 332 | run_queue: RunQueue::new(), |
| @@ -377,18 +375,19 @@ impl SyncExecutor { | |||
| 377 | /// Same as [`Executor::poll`], plus you must only call this on the thread this executor was created. | 375 | /// Same as [`Executor::poll`], plus you must only call this on the thread this executor was created. |
| 378 | pub(crate) unsafe fn poll(&'static self) { | 376 | pub(crate) unsafe fn poll(&'static self) { |
| 379 | #[cfg(feature = "integrated-timers")] | 377 | #[cfg(feature = "integrated-timers")] |
| 380 | driver::set_alarm_callback(self.alarm, Self::alarm_callback, self as *const _ as *mut ()); | 378 | embassy_time_driver::set_alarm_callback(self.alarm, Self::alarm_callback, self as *const _ as *mut ()); |
| 381 | 379 | ||
| 382 | #[allow(clippy::never_loop)] | 380 | #[allow(clippy::never_loop)] |
| 383 | loop { | 381 | loop { |
| 384 | #[cfg(feature = "integrated-timers")] | 382 | #[cfg(feature = "integrated-timers")] |
| 385 | self.timer_queue.dequeue_expired(Instant::now(), wake_task_no_pend); | 383 | self.timer_queue |
| 384 | .dequeue_expired(embassy_time_driver::now(), wake_task_no_pend); | ||
| 386 | 385 | ||
| 387 | self.run_queue.dequeue_all(|p| { | 386 | self.run_queue.dequeue_all(|p| { |
| 388 | let task = p.header(); | 387 | let task = p.header(); |
| 389 | 388 | ||
| 390 | #[cfg(feature = "integrated-timers")] | 389 | #[cfg(feature = "integrated-timers")] |
| 391 | task.expires_at.set(Instant::MAX); | 390 | task.expires_at.set(u64::MAX); |
| 392 | 391 | ||
| 393 | if !task.state.run_dequeue() { | 392 | if !task.state.run_dequeue() { |
| 394 | // If task is not running, ignore it. This can happen in the following scenario: | 393 | // If task is not running, ignore it. This can happen in the following scenario: |
| @@ -418,7 +417,7 @@ impl SyncExecutor { | |||
| 418 | // If this is already in the past, set_alarm might return false | 417 | // If this is already in the past, set_alarm might return false |
| 419 | // In that case do another poll loop iteration. | 418 | // In that case do another poll loop iteration. |
| 420 | let next_expiration = self.timer_queue.next_expiration(); | 419 | let next_expiration = self.timer_queue.next_expiration(); |
| 421 | if driver::set_alarm(self.alarm, next_expiration.as_ticks()) { | 420 | if embassy_time_driver::set_alarm(self.alarm, next_expiration) { |
| 422 | break; | 421 | break; |
| 423 | } | 422 | } |
| 424 | } | 423 | } |
| @@ -568,8 +567,8 @@ pub fn wake_task_no_pend(task: TaskRef) { | |||
| 568 | struct TimerQueue; | 567 | struct TimerQueue; |
| 569 | 568 | ||
| 570 | #[cfg(feature = "integrated-timers")] | 569 | #[cfg(feature = "integrated-timers")] |
| 571 | impl embassy_time::queue::TimerQueue for TimerQueue { | 570 | impl embassy_time_queue_driver::TimerQueue for TimerQueue { |
| 572 | fn schedule_wake(&'static self, at: Instant, waker: &core::task::Waker) { | 571 | fn schedule_wake(&'static self, at: u64, waker: &core::task::Waker) { |
| 573 | let task = waker::task_from_waker(waker); | 572 | let task = waker::task_from_waker(waker); |
| 574 | let task = task.header(); | 573 | let task = task.header(); |
| 575 | unsafe { | 574 | unsafe { |
| @@ -580,7 +579,16 @@ impl embassy_time::queue::TimerQueue for TimerQueue { | |||
| 580 | } | 579 | } |
| 581 | 580 | ||
| 582 | #[cfg(feature = "integrated-timers")] | 581 | #[cfg(feature = "integrated-timers")] |
| 583 | embassy_time::timer_queue_impl!(static TIMER_QUEUE: TimerQueue = TimerQueue); | 582 | embassy_time_queue_driver::timer_queue_impl!(static TIMER_QUEUE: TimerQueue = TimerQueue); |
| 583 | |||
| 584 | #[cfg(all(feature = "rtos-trace", feature = "integrated-timers"))] | ||
| 585 | const fn gcd(a: u64, b: u64) -> u64 { | ||
| 586 | if b == 0 { | ||
| 587 | a | ||
| 588 | } else { | ||
| 589 | gcd(b, a % b) | ||
| 590 | } | ||
| 591 | } | ||
| 584 | 592 | ||
| 585 | #[cfg(feature = "rtos-trace")] | 593 | #[cfg(feature = "rtos-trace")] |
| 586 | impl rtos_trace::RtosTraceOSCallbacks for Executor { | 594 | impl rtos_trace::RtosTraceOSCallbacks for Executor { |
| @@ -589,7 +597,8 @@ impl rtos_trace::RtosTraceOSCallbacks for Executor { | |||
| 589 | } | 597 | } |
| 590 | #[cfg(feature = "integrated-timers")] | 598 | #[cfg(feature = "integrated-timers")] |
| 591 | fn time() -> u64 { | 599 | fn time() -> u64 { |
| 592 | Instant::now().as_micros() | 600 | const GCD_1M: u64 = gcd(embassy_time_driver::TICK_HZ, 1_000_000); |
| 601 | embassy_time_driver::now() * (1_000_000 / GCD_1M) / (embassy_time_driver::TICK_HZ / GCD_1M) | ||
| 593 | } | 602 | } |
| 594 | #[cfg(not(feature = "integrated-timers"))] | 603 | #[cfg(not(feature = "integrated-timers"))] |
| 595 | fn time() -> u64 { | 604 | fn time() -> u64 { |
diff --git a/embassy-executor/src/raw/timer_queue.rs b/embassy-executor/src/raw/timer_queue.rs index 59a3b43f5..94a5f340b 100644 --- a/embassy-executor/src/raw/timer_queue.rs +++ b/embassy-executor/src/raw/timer_queue.rs | |||
| @@ -1,7 +1,5 @@ | |||
| 1 | use core::cmp::min; | 1 | use core::cmp::min; |
| 2 | 2 | ||
| 3 | use embassy_time::Instant; | ||
| 4 | |||
| 5 | use super::TaskRef; | 3 | use super::TaskRef; |
| 6 | use crate::raw::util::SyncUnsafeCell; | 4 | use crate::raw::util::SyncUnsafeCell; |
| 7 | 5 | ||
| @@ -30,7 +28,7 @@ impl TimerQueue { | |||
| 30 | 28 | ||
| 31 | pub(crate) unsafe fn update(&self, p: TaskRef) { | 29 | pub(crate) unsafe fn update(&self, p: TaskRef) { |
| 32 | let task = p.header(); | 30 | let task = p.header(); |
| 33 | if task.expires_at.get() != Instant::MAX { | 31 | if task.expires_at.get() != u64::MAX { |
| 34 | if task.state.timer_enqueue() { | 32 | if task.state.timer_enqueue() { |
| 35 | task.timer_queue_item.next.set(self.head.get()); | 33 | task.timer_queue_item.next.set(self.head.get()); |
| 36 | self.head.set(Some(p)); | 34 | self.head.set(Some(p)); |
| @@ -38,18 +36,18 @@ impl TimerQueue { | |||
| 38 | } | 36 | } |
| 39 | } | 37 | } |
| 40 | 38 | ||
| 41 | pub(crate) unsafe fn next_expiration(&self) -> Instant { | 39 | pub(crate) unsafe fn next_expiration(&self) -> u64 { |
| 42 | let mut res = Instant::MAX; | 40 | let mut res = u64::MAX; |
| 43 | self.retain(|p| { | 41 | self.retain(|p| { |
| 44 | let task = p.header(); | 42 | let task = p.header(); |
| 45 | let expires = task.expires_at.get(); | 43 | let expires = task.expires_at.get(); |
| 46 | res = min(res, expires); | 44 | res = min(res, expires); |
| 47 | expires != Instant::MAX | 45 | expires != u64::MAX |
| 48 | }); | 46 | }); |
| 49 | res | 47 | res |
| 50 | } | 48 | } |
| 51 | 49 | ||
| 52 | pub(crate) unsafe fn dequeue_expired(&self, now: Instant, on_task: impl Fn(TaskRef)) { | 50 | pub(crate) unsafe fn dequeue_expired(&self, now: u64, on_task: impl Fn(TaskRef)) { |
| 53 | self.retain(|p| { | 51 | self.retain(|p| { |
| 54 | let task = p.header(); | 52 | let task = p.header(); |
| 55 | if task.expires_at.get() <= now { | 53 | if task.expires_at.get() <= now { |
diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index 0dbd391e8..348cc7dc4 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | #![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] | 1 | #![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] |
| 2 | 2 | ||
| 3 | use std::boxed::Box; | 3 | use std::boxed::Box; |
| 4 | use std::future::poll_fn; | 4 | use std::future::poll_fn; |
| @@ -135,3 +135,17 @@ fn executor_task_self_wake_twice() { | |||
| 135 | ] | 135 | ] |
| 136 | ) | 136 | ) |
| 137 | } | 137 | } |
| 138 | |||
| 139 | #[test] | ||
| 140 | fn executor_task_cfg_args() { | ||
| 141 | // simulate cfg'ing away argument c | ||
| 142 | #[task] | ||
| 143 | async fn task1(a: u32, b: u32, #[cfg(any())] c: u32) { | ||
| 144 | let (_, _) = (a, b); | ||
| 145 | } | ||
| 146 | |||
| 147 | #[task] | ||
| 148 | async fn task2(a: u32, b: u32, #[cfg(all())] c: u32) { | ||
| 149 | let (_, _, _) = (a, b, c); | ||
| 150 | } | ||
| 151 | } | ||
