aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci-nightly.sh3
-rw-r--r--embassy-executor-macros/src/lib.rs7
-rw-r--r--embassy-executor-macros/src/macros/main.rs14
-rw-r--r--embassy-executor/Cargo.toml11
-rw-r--r--embassy-executor/src/arch/avr.rs72
-rw-r--r--embassy-executor/src/lib.rs3
6 files changed, 106 insertions, 4 deletions
diff --git a/ci-nightly.sh b/ci-nightly.sh
index 1fc9692b5..46b19c5b7 100755
--- a/ci-nightly.sh
+++ b/ci-nightly.sh
@@ -28,3 +28,6 @@ cargo batch \
28 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread,integrated-timers \ 28 --- build --release --manifest-path embassy-executor/Cargo.toml --target riscv32imac-unknown-none-elf --features nightly,arch-riscv32,executor-thread,integrated-timers \
29 --- build --release --manifest-path examples/nrf52840-rtic/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840-rtic \ 29 --- build --release --manifest-path examples/nrf52840-rtic/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/nrf52840-rtic \
30 30
31cargo build --release --manifest-path embassy-executor/Cargo.toml --target avr-unknown-gnu-atmega328 -Z build-std=core,alloc --features nightly,arch-avr,avr-device/atmega328p
32cargo build --release --manifest-path embassy-executor/Cargo.toml --target avr-unknown-gnu-atmega328 -Z build-std=core,alloc --features nightly,arch-avr,integrated-timers,avr-device/atmega328p
33
diff --git a/embassy-executor-macros/src/lib.rs b/embassy-executor-macros/src/lib.rs
index c9d58746a..5461fe04c 100644
--- a/embassy-executor-macros/src/lib.rs
+++ b/embassy-executor-macros/src/lib.rs
@@ -62,6 +62,13 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream {
62 task::run(&args.meta, f).unwrap_or_else(|x| x).into() 62 task::run(&args.meta, f).unwrap_or_else(|x| x).into()
63} 63}
64 64
65#[proc_macro_attribute]
66pub fn main_avr(args: TokenStream, item: TokenStream) -> TokenStream {
67 let args = syn::parse_macro_input!(args as Args);
68 let f = syn::parse_macro_input!(item as syn::ItemFn);
69 main::run(&args.meta, f, main::avr()).unwrap_or_else(|x| x).into()
70}
71
65/// Creates a new `executor` instance and declares an application entry point for Cortex-M spawning the corresponding function body as an async task. 72/// Creates a new `executor` instance and declares an application entry point for Cortex-M spawning the corresponding function body as an async task.
66/// 73///
67/// The following restrictions apply: 74/// The following restrictions apply:
diff --git a/embassy-executor-macros/src/macros/main.rs b/embassy-executor-macros/src/macros/main.rs
index 3c0d58567..088e64d1c 100644
--- a/embassy-executor-macros/src/macros/main.rs
+++ b/embassy-executor-macros/src/macros/main.rs
@@ -12,6 +12,20 @@ struct Args {
12 entry: Option<String>, 12 entry: Option<String>,
13} 13}
14 14
15pub fn avr() -> TokenStream {
16 quote! {
17 #[avr_device::entry]
18 fn main() -> ! {
19 let mut executor = ::embassy_executor::Executor::new();
20 let executor = unsafe { __make_static(&mut executor) };
21
22 executor.run(|spawner| {
23 spawner.must_spawn(__embassy_main(spawner));
24 })
25 }
26 }
27}
28
15pub fn riscv(args: &[NestedMeta]) -> TokenStream { 29pub fn riscv(args: &[NestedMeta]) -> TokenStream {
16 let maybe_entry = match Args::from_list(args) { 30 let maybe_entry = match Args::from_list(args) {
17 Ok(args) => args.entry, 31 Ok(args) => args.entry,
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")]