From 1443f3386b3b216dc50306d14f5dacce29b2bf97 Mon Sep 17 00:00:00 2001 From: Oleksandr Babak Date: Fri, 6 Sep 2024 11:34:30 +0200 Subject: fix: remove stable nightly feature --- embassy-executor/src/lib.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'embassy-executor/src/lib.rs') diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index 553ed76d3..6a2e493a2 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -1,5 +1,4 @@ #![cfg_attr(not(any(feature = "arch-std", feature = "arch-wasm")), no_std)] -#![cfg_attr(feature = "nightly", feature(waker_getters))] #![allow(clippy::new_without_default)] #![doc = include_str!("../README.md")] #![warn(missing_docs)] -- cgit From 9e6e09a8d747ec90aae215df8471dfe349993487 Mon Sep 17 00:00:00 2001 From: Dummyc0m Date: Sun, 6 Oct 2024 23:23:33 -0700 Subject: executor/spin: introduce an architecture agnostic executor Spin polls the raw executor and never sleeps. It is useful for disabling any power features associated with wfi/wfe-like instructions. When implementing support for the CH32V30x MCU, the wfi instruction had issues interacting with the USB OTG peripheral and appeared to be non-spec-compliant. 1. When sending a USB Data-in packet, the USB peripheral appears to be unable to read the system main memory while in WFI. This manifests in the USB peripheral sending all or partially zeroed DATA packets. Disabling WFI works around this issue. 2. The WFI instruction does not wake up the processor when MIE is disabled. The MCU provides a WFITOWFE bit to emulate the WFE instruction on arm, which, when enabled, ignores the MIE and allows the processor to wake up. This works around the non-compliant WFI implementation. Co-authored-by: Codetector Co-authored-by: Dummyc0m --- embassy-executor/src/lib.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'embassy-executor/src/lib.rs') diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index 6a2e493a2..d816539ac 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -23,7 +23,14 @@ macro_rules! check_at_most_one { check_at_most_one!(@amo [$($f)*] [$($f)*] []); }; } -check_at_most_one!("arch-avr", "arch-cortex-m", "arch-riscv32", "arch-std", "arch-wasm",); +check_at_most_one!( + "arch-avr", + "arch-cortex-m", + "arch-riscv32", + "arch-std", + "arch-wasm", + "arch-spin", +); #[cfg(feature = "_arch")] #[cfg_attr(feature = "arch-avr", path = "arch/avr.rs")] @@ -31,6 +38,7 @@ check_at_most_one!("arch-avr", "arch-cortex-m", "arch-riscv32", "arch-std", "arc #[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")] #[cfg_attr(feature = "arch-std", path = "arch/std.rs")] #[cfg_attr(feature = "arch-wasm", path = "arch/wasm.rs")] +#[cfg_attr(feature = "arch-spin", path = "arch/spin.rs")] mod arch; #[cfg(feature = "_arch")] -- cgit From 1e850ae79149e737c1ba39a383596eabcb0bb940 Mon Sep 17 00:00:00 2001 From: Dániel Buga Date: Wed, 6 Nov 2024 10:44:01 +0100 Subject: Detect and allow older nightlies --- embassy-executor/src/lib.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'embassy-executor/src/lib.rs') diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index d816539ac..8e07a8b18 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(not(any(feature = "arch-std", feature = "arch-wasm")), no_std)] +#![cfg_attr(all(feature = "nightly", not(at_least_2024_09_06)), feature(waker_getters))] #![allow(clippy::new_without_default)] #![doc = include_str!("../README.md")] #![warn(missing_docs)] -- cgit From baeb59b5b8d63ef9bb6ecada518ea8b911d2dc30 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 12 Nov 2024 16:28:26 +0100 Subject: executor: use WakerHack unconditionally even if `nightly` feature is enabled. (#3528) This ensures the executor compiles with all recent nightly versions, including the stable-but-with-nightly-features-enabled xtensa rustc. --- embassy-executor/src/lib.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'embassy-executor/src/lib.rs') diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index 8e07a8b18..d816539ac 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -1,5 +1,4 @@ #![cfg_attr(not(any(feature = "arch-std", feature = "arch-wasm")), no_std)] -#![cfg_attr(all(feature = "nightly", not(at_least_2024_09_06)), feature(waker_getters))] #![allow(clippy::new_without_default)] #![doc = include_str!("../README.md")] #![warn(missing_docs)] -- cgit From 695a6da322aa2d75c8f702b2ed8b67f9ad12c3a0 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 28 Mar 2025 18:59:02 +0100 Subject: Statically allocate task pools on stable Rust. Thanks @0e4ef622 for the awesome idea of how to do it and the first implementation. Co-Authored-By: Matthew Tran <0e4ef622@gmail.com> --- embassy-executor/src/lib.rs | 178 +++++++++++++++++++++++++------------------- 1 file changed, 103 insertions(+), 75 deletions(-) (limited to 'embassy-executor/src/lib.rs') diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index d816539ac..5485f6a6a 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -50,101 +50,129 @@ pub mod raw; mod spawner; pub use spawner::*; -mod config { - #![allow(unused)] - include!(concat!(env!("OUT_DIR"), "/config.rs")); -} - /// Implementation details for embassy macros. /// Do not use. Used for macros and HALs only. Not covered by semver guarantees. #[doc(hidden)] #[cfg(not(feature = "nightly"))] pub mod _export { - use core::alloc::Layout; - use core::cell::{Cell, UnsafeCell}; + use core::cell::UnsafeCell; use core::future::Future; use core::mem::MaybeUninit; - use core::ptr::null_mut; - - use critical_section::{CriticalSection, Mutex}; - use crate::raw::TaskPool; - - struct Arena { - buf: UnsafeCell>, - ptr: Mutex>, + pub trait TaskFn: Copy { + type Fut: Future + 'static; } - unsafe impl Sync for Arena {} - unsafe impl Send for Arena {} - - impl Arena { - const fn new() -> Self { - Self { - buf: UnsafeCell::new(MaybeUninit::uninit()), - ptr: Mutex::new(Cell::new(null_mut())), - } - } - - fn alloc(&'static self, cs: CriticalSection) -> &'static mut MaybeUninit { - let layout = Layout::new::(); - - let start = self.buf.get().cast::(); - let end = unsafe { start.add(N) }; - - let mut ptr = self.ptr.borrow(cs).get(); - if ptr.is_null() { - ptr = self.buf.get().cast::(); - } - - let bytes_left = (end as usize) - (ptr as usize); - let align_offset = (ptr as usize).next_multiple_of(layout.align()) - (ptr as usize); - - if align_offset + layout.size() > bytes_left { - panic!("embassy-executor: task arena is full. You must increase the arena size, see the documentation for details: https://docs.embassy.dev/embassy-executor/"); + macro_rules! task_fn_impl { + ($($Tn:ident),*) => { + impl TaskFn<($($Tn,)*)> for F + where + F: Copy + FnOnce($($Tn,)*) -> Fut, + Fut: Future + 'static, + { + type Fut = Fut; } + }; + } - let res = unsafe { ptr.add(align_offset) }; - let ptr = unsafe { ptr.add(align_offset + layout.size()) }; + task_fn_impl!(); + task_fn_impl!(T0); + task_fn_impl!(T0, T1); + task_fn_impl!(T0, T1, T2); + task_fn_impl!(T0, T1, T2, T3); + task_fn_impl!(T0, T1, T2, T3, T4); + task_fn_impl!(T0, T1, T2, T3, T4, T5); + task_fn_impl!(T0, T1, T2, T3, T4, T5, T6); + task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7); + task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8); + task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9); + task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); + task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11); + task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12); + task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13); + task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14); + task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15); + + #[allow(private_bounds)] + #[repr(C)] + pub struct TaskPoolHolder + where + Align: Alignment, + { + data: UnsafeCell<[MaybeUninit; SIZE]>, + align: Align, + } - self.ptr.borrow(cs).set(ptr); + unsafe impl Send for TaskPoolHolder where Align: Alignment {} + unsafe impl Sync for TaskPoolHolder where Align: Alignment {} - unsafe { &mut *(res as *mut MaybeUninit) } + #[allow(private_bounds)] + impl TaskPoolHolder + where + Align: Alignment, + { + pub const fn get(&self) -> *const u8 { + self.data.get().cast() } } - static ARENA: Arena<{ crate::config::TASK_ARENA_SIZE }> = Arena::new(); + #[allow(private_bounds)] + #[repr(transparent)] + pub struct Align([::Archetype; 0]) + where + Self: Alignment; - pub struct TaskPoolRef { - // type-erased `&'static mut TaskPool` - // Needed because statics can't have generics. - ptr: Mutex>, + trait Alignment { + /// A zero-sized type of particular alignment. + type Archetype: Copy + Eq + PartialEq + Send + Sync + Unpin; } - unsafe impl Sync for TaskPoolRef {} - unsafe impl Send for TaskPoolRef {} - - impl TaskPoolRef { - pub const fn new() -> Self { - Self { - ptr: Mutex::new(Cell::new(null_mut())), - } - } - /// Get the pool for this ref, allocating it from the arena the first time. - /// - /// safety: for a given TaskPoolRef instance, must always call with the exact - /// same generic params. - pub unsafe fn get(&'static self) -> &'static TaskPool { - critical_section::with(|cs| { - let ptr = self.ptr.borrow(cs); - if ptr.get().is_null() { - let pool = ARENA.alloc::>(cs); - pool.write(TaskPool::new()); - ptr.set(pool as *mut _ as _); + macro_rules! aligns { + ($($AlignX:ident: $n:literal,)*) => { + $( + #[derive(Copy, Clone, Eq, PartialEq)] + #[repr(align($n))] + struct $AlignX {} + impl Alignment for Align<$n> { + type Archetype = $AlignX; } - - unsafe { &*(ptr.get() as *const _) } - }) - } + )* + }; } + + aligns!( + Align1: 1, + Align2: 2, + Align4: 4, + Align8: 8, + Align16: 16, + Align32: 32, + Align64: 64, + Align128: 128, + Align256: 256, + Align512: 512, + Align1024: 1024, + Align2048: 2048, + Align4096: 4096, + Align8192: 8192, + Align16384: 16384, + ); + #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] + aligns!( + Align32768: 32768, + Align65536: 65536, + Align131072: 131072, + Align262144: 262144, + Align524288: 524288, + Align1048576: 1048576, + Align2097152: 2097152, + Align4194304: 4194304, + Align8388608: 8388608, + Align16777216: 16777216, + Align33554432: 33554432, + Align67108864: 67108864, + Align134217728: 134217728, + Align268435456: 268435456, + Align536870912: 536870912, + ); } -- cgit From 034e9fc218f1a348f451f56a5b9f3941fc046b1a Mon Sep 17 00:00:00 2001 From: Matthew Tran <0e4ef622@gmail.com> Date: Sat, 29 Mar 2025 02:45:48 -0500 Subject: Move macro helper functions to embassy-executor --- embassy-executor/src/lib.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'embassy-executor/src/lib.rs') diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index 5485f6a6a..d6bd63665 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -59,6 +59,8 @@ pub mod _export { use core::future::Future; use core::mem::MaybeUninit; + use crate::raw::TaskPool; + pub trait TaskFn: Copy { type Fut: Future + 'static; } @@ -116,6 +118,30 @@ pub mod _export { } } + pub const fn task_pool_size(_: F) -> usize + where + F: TaskFn, + Fut: Future + 'static, + { + size_of::>() + } + + pub const fn task_pool_align(_: F) -> usize + where + F: TaskFn, + Fut: Future + 'static, + { + align_of::>() + } + + pub const fn task_pool_new(_: F) -> TaskPool + where + F: TaskFn, + Fut: Future + 'static, + { + TaskPool::new() + } + #[allow(private_bounds)] #[repr(transparent)] pub struct Align([::Archetype; 0]) -- cgit From ef8d168df6fa1d8020d7490e4469d196a35077ce Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Fri, 4 Apr 2025 01:33:51 -0700 Subject: executor: add executor selection to #[embassy_executor::main] --- embassy-executor/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'embassy-executor/src/lib.rs') diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index d6bd63665..d6fd3d651 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -44,6 +44,8 @@ mod arch; #[cfg(feature = "_arch")] #[allow(unused_imports)] // don't warn if the module is empty. pub use arch::*; +#[cfg(not(feature = "_arch"))] +pub use embassy_executor_macros::main_unspecified as main; pub mod raw; -- cgit From 5a07ea5d851768223e2e41342e69d14c1afb2b2b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 9 Mar 2025 20:55:11 +0100 Subject: Add support for Cortex-A/R --- embassy-executor/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'embassy-executor/src/lib.rs') diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index d6fd3d651..dfe420bab 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -26,6 +26,7 @@ macro_rules! check_at_most_one { check_at_most_one!( "arch-avr", "arch-cortex-m", + "arch-cortex-ar", "arch-riscv32", "arch-std", "arch-wasm", @@ -35,6 +36,7 @@ check_at_most_one!( #[cfg(feature = "_arch")] #[cfg_attr(feature = "arch-avr", path = "arch/avr.rs")] #[cfg_attr(feature = "arch-cortex-m", path = "arch/cortex_m.rs")] +#[cfg_attr(feature = "arch-cortex-ar", path = "arch/cortex_ar.rs")] #[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")] #[cfg_attr(feature = "arch-std", path = "arch/std.rs")] #[cfg_attr(feature = "arch-wasm", path = "arch/wasm.rs")] -- cgit