aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-executor')
-rw-r--r--embassy-executor/Cargo.toml11
-rw-r--r--embassy-executor/src/arch/avr.rs72
-rw-r--r--embassy-executor/src/lib.rs3
3 files changed, 82 insertions, 4 deletions
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml
index b6b156c9f..d6fe8ee8b 100644
--- a/embassy-executor/Cargo.toml
+++ b/embassy-executor/Cargo.toml
@@ -40,7 +40,7 @@ critical-section = "1.1"
40 40
41document-features = "0.2.7" 41document-features = "0.2.7"
42 42
43# needed for riscv 43# needed for riscv and avr
44# remove when https://github.com/rust-lang/rust/pull/114499 is merged 44# remove when https://github.com/rust-lang/rust/pull/114499 is merged
45portable-atomic = { version = "1.5", optional = true } 45portable-atomic = { version = "1.5", optional = true }
46 46
@@ -51,6 +51,9 @@ cortex-m = { version = "0.7.6", optional = true }
51wasm-bindgen = { version = "0.2.82", optional = true } 51wasm-bindgen = { version = "0.2.82", optional = true }
52js-sys = { version = "0.3", optional = true } 52js-sys = { version = "0.3", optional = true }
53 53
54# arch-avr dependencies
55avr-device = { version = "0.5.3", optional = true }
56
54[dev-dependencies] 57[dev-dependencies]
55critical-section = { version = "1.1", features = ["std"] } 58critical-section = { version = "1.1", features = ["std"] }
56 59
@@ -78,6 +81,8 @@ arch-cortex-m = ["_arch", "dep:cortex-m"]
78arch-riscv32 = ["_arch", "dep:portable-atomic"] 81arch-riscv32 = ["_arch", "dep:portable-atomic"]
79## WASM 82## WASM
80arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"] 83arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"]
84## AVR
85arch-avr = ["_arch", "dep:portable-atomic", "dep:avr-device"]
81 86
82#! ### Executor 87#! ### Executor
83 88
@@ -88,11 +93,11 @@ executor-interrupt = []
88 93
89#! ### Task Arena Size 94#! ### Task Arena Size
90#! Sets the [task arena](#task-arena) size. Necessary if you’re not using `nightly`. 95#! Sets the [task arena](#task-arena) size. Necessary if you’re not using `nightly`.
91#! 96#!
92#! <details> 97#! <details>
93#! <summary>Preconfigured Task Arena Sizes:</summary> 98#! <summary>Preconfigured Task Arena Sizes:</summary>
94#! <!-- rustdoc requires the following blank line for the feature list to render correctly! --> 99#! <!-- rustdoc requires the following blank line for the feature list to render correctly! -->
95#! 100#!
96 101
97# BEGIN AUTOGENERATED CONFIG FEATURES 102# BEGIN AUTOGENERATED CONFIG FEATURES
98# Generated by gen_config.py. DO NOT EDIT. 103# Generated by gen_config.py. DO NOT EDIT.
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")]
2compile_error!("`executor-interrupt` is not supported with `arch-avr`.");
3
4#[cfg(feature = "executor-thread")]
5pub use thread::*;
6#[cfg(feature = "executor-thread")]
7mod 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/lib.rs b/embassy-executor/src/lib.rs
index eea118ade..6a2e493a2 100644
--- a/embassy-executor/src/lib.rs
+++ b/embassy-executor/src/lib.rs
@@ -23,9 +23,10 @@ macro_rules! check_at_most_one {
23 check_at_most_one!(@amo [$($f)*] [$($f)*] []); 23 check_at_most_one!(@amo [$($f)*] [$($f)*] []);
24 }; 24 };
25} 25}
26check_at_most_one!("arch-cortex-m", "arch-riscv32", "arch-std", "arch-wasm",); 26check_at_most_one!("arch-avr", "arch-cortex-m", "arch-riscv32", "arch-std", "arch-wasm",);
27 27
28#[cfg(feature = "_arch")] 28#[cfg(feature = "_arch")]
29#[cfg_attr(feature = "arch-avr", path = "arch/avr.rs")]
29#[cfg_attr(feature = "arch-cortex-m", path = "arch/cortex_m.rs")] 30#[cfg_attr(feature = "arch-cortex-m", path = "arch/cortex_m.rs")]
30#[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")] 31#[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")]
31#[cfg_attr(feature = "arch-std", path = "arch/std.rs")] 32#[cfg_attr(feature = "arch-std", path = "arch/std.rs")]