From f32565b4af78aa08f36420477d66c352bda2d129 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 2 May 2024 16:58:04 +0100 Subject: [PATCH] Embassy enable thread and interrupt by default, enable embassy when building docs (#1485) * Remove interrupt and thread executor embassy features * Reserve sw interrupt 3 (4) instead of 0 for multicore systems with the embassy feature enabled * Remove uneeded #[feature()] from examples * Fix HIL tests * Add thread mode context id and fix up examples * improve embassy module docs * changelog * fixup hil tests * Fixup usb examples --- esp-hal/CHANGELOG.md | 4 + esp-hal/Cargo.toml | 8 +- esp-hal/src/embassy/executor/mod.rs | 43 +++------ esp-hal/src/embassy/executor/thread.rs | 44 ++++++--- esp-hal/src/embassy/mod.rs | 96 ++++--------------- esp-hal/src/system.rs | 29 +++--- examples/Cargo.toml | 3 - examples/README.md | 2 +- examples/src/bin/embassy_hello_world.rs | 3 +- .../src/bin/embassy_hello_world_systimer.rs | 3 +- examples/src/bin/embassy_i2c.rs | 3 +- .../embassy_i2c_bmp180_calibration_data.rs | 2 +- examples/src/bin/embassy_i2s_read.rs | 3 +- examples/src/bin/embassy_i2s_sound.rs | 3 +- examples/src/bin/embassy_multicore.rs | 11 ++- .../src/bin/embassy_multicore_interrupt.rs | 31 +++--- examples/src/bin/embassy_multiprio.rs | 8 +- examples/src/bin/embassy_parl_io_rx.rs | 3 +- examples/src/bin/embassy_parl_io_tx.rs | 3 +- examples/src/bin/embassy_rmt_rx.rs | 3 +- examples/src/bin/embassy_rmt_tx.rs | 3 +- examples/src/bin/embassy_serial.rs | 8 +- examples/src/bin/embassy_spi.rs | 3 +- examples/src/bin/embassy_systimer_delay.rs | 3 +- examples/src/bin/embassy_twai.rs | 8 +- examples/src/bin/embassy_usb_serial.rs | 2 +- examples/src/bin/embassy_usb_serial_jtag.rs | 9 +- examples/src/bin/embassy_wait.rs | 3 +- hil-test/Cargo.toml | 4 +- hil-test/tests/gpio.rs | 2 +- hil-test/tests/uart_async.rs | 2 +- 31 files changed, 147 insertions(+), 205 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index badf76e82..18867b951 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - i2c: i2c1_handler used I2C0 register block by mistake (#1487) - Removed ESP32 specific code for resolutions > 16 bit in ledc embedded_hal::pwm max_duty_cycle function. (#1441) - Fixed division by zero in ledc embedded_hal::pwm set_duty_cycle function and converted to set_duty_hw instead of set_duty to eliminate loss of granularity. (#1441) +- Embassy examples now build on stable (#1485) ### Changed @@ -32,6 +33,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Make software interrupts shareable (#1500) - The `SystemParts` struct has been renamed to `SystemControl`, and now has a constructor which takes the `SYSTEM` peripheral (#1495) - Timer abstraction: refactor `systimer` and `timer` modules into a common `timer` module (#1527) +- Removed the `embassy-executor-thread` and `embassy-executor-interrupt` features, they are now enabled by default when `embassy` is enabled. (#1485) +- Software interrupt 3 is now used instead of software interrupt 0 on the thread aware executor on multicore systems (#1485) +- Timer abstraction: refactor `systimer` and `timer` modules into a common `timer` module (#1527) ### Removed diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index f14cc4789..c6b7608c5 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -170,11 +170,7 @@ ufmt = ["dep:ufmt-write"] #! ### Embassy Feature Flags ## Enable support for `embassy`, a modern asynchronous embedded framework. -embassy = ["embassy-time-driver", "procmacros/embassy"] -## Use the interrupt-mode embassy executor. -embassy-executor-interrupt = ["embassy", "embassy-executor"] -## Use the thread-mode embassy executor. -embassy-executor-thread = ["embassy", "embassy-executor"] +embassy = ["embassy-time-driver", "procmacros/embassy", "embassy-executor"] ## Uses hardware timers as alarms for the executors. Using this feature ## limits the number of executors to the number of hardware alarms provided ## by the time driver. @@ -217,6 +213,8 @@ ci = [ "embedded-hal-02", "ufmt", "async", + "embassy", + "embassy-time-timg0", ] [lints.clippy] diff --git a/esp-hal/src/embassy/executor/mod.rs b/esp-hal/src/embassy/executor/mod.rs index ef7c68b9a..983a3c8a4 100644 --- a/esp-hal/src/embassy/executor/mod.rs +++ b/esp-hal/src/embassy/executor/mod.rs @@ -1,41 +1,26 @@ -#[cfg(feature = "embassy-executor-thread")] -pub mod thread; +mod interrupt; +mod thread; -#[cfg(feature = "embassy-executor-thread")] +pub use interrupt::*; pub use thread::*; -#[cfg(feature = "embassy-executor-interrupt")] -pub mod interrupt; - -#[cfg(feature = "embassy-executor-interrupt")] -pub use interrupt::*; - -#[cfg(any( - feature = "embassy-executor-thread", - feature = "embassy-executor-interrupt", -))] #[export_name = "__pender"] fn __pender(context: *mut ()) { - #[cfg(feature = "embassy-executor-interrupt")] use crate::system::SoftwareInterrupt; let context = (context as usize).to_le_bytes(); - cfg_if::cfg_if! { - if #[cfg(feature = "embassy-executor-interrupt")] { - match context[0] { - #[cfg(feature = "embassy-executor-thread")] - 0 => thread::pend_thread_mode(context[1] as usize), - - #[cfg(not(feature = "embassy-executor-thread"))] - 0 => unsafe { SoftwareInterrupt::<0>::steal().raise() }, - 1 => unsafe { SoftwareInterrupt::<1>::steal().raise() }, - 2 => unsafe { SoftwareInterrupt::<2>::steal().raise() }, - 3 => unsafe { SoftwareInterrupt::<3>::steal().raise() }, - _ => {} - } - } else { - pend_thread_mode(context[1] as usize); + match context[0] { + // For interrupt executors, the context value is the + // software interrupt number + 0 => unsafe { SoftwareInterrupt::<0>::steal().raise() }, + 1 => unsafe { SoftwareInterrupt::<1>::steal().raise() }, + 2 => unsafe { SoftwareInterrupt::<2>::steal().raise() }, + 3 => unsafe { SoftwareInterrupt::<3>::steal().raise() }, + other => { + assert_eq!(other, THREAD_MODE_CONTEXT); + // THREAD_MODE_CONTEXT id is reserved for thread mode executors + thread::pend_thread_mode(context[1] as usize) } } } diff --git a/esp-hal/src/embassy/executor/thread.rs b/esp-hal/src/embassy/executor/thread.rs index e6f8ceaee..78416fe41 100644 --- a/esp-hal/src/embassy/executor/thread.rs +++ b/esp-hal/src/embassy/executor/thread.rs @@ -10,6 +10,8 @@ use crate::get_core; #[cfg(multi_core)] use crate::peripherals::SYSTEM; +pub(crate) const THREAD_MODE_CONTEXT: u8 = 16; + /// global atomic used to keep track of whether there is work to do since sev() /// is not available on either Xtensa or RISC-V #[cfg(not(multi_core))] @@ -19,15 +21,15 @@ static SIGNAL_WORK_THREAD_MODE: [AtomicBool; 2] = [AtomicBool::new(false), Atomi #[cfg(multi_core)] #[handler] -fn software0_interrupt() { +fn software3_interrupt() { // This interrupt is fired when the thread-mode executor's core needs to be // woken. It doesn't matter which core handles this interrupt first, the // point is just to wake up the core that is currently executing // `waiti`. let system = unsafe { &*SYSTEM::PTR }; system - .cpu_intr_from_cpu_0() - .write(|w| w.cpu_intr_from_cpu_0().bit(false)); + .cpu_intr_from_cpu_3() + .write(|w| w.cpu_intr_from_cpu_3().bit(false)); } pub(crate) fn pend_thread_mode(core: usize) { @@ -44,12 +46,21 @@ pub(crate) fn pend_thread_mode(core: usize) { let system = unsafe { &*SYSTEM::PTR }; system - .cpu_intr_from_cpu_0() - .write(|w| w.cpu_intr_from_cpu_0().bit(true)); + .cpu_intr_from_cpu_3() + .write(|w| w.cpu_intr_from_cpu_3().bit(true)); } } -/// Multi-core Xtensa Executor +/// A thread aware Executor +#[cfg_attr( + multi_core, + doc = r#" +This executor is capable of waking an +executor running on another core if work +needs to be completed there for a task to +progress on this core. +"# +)] pub struct Executor { inner: raw::Executor, not_send: PhantomData<*mut ()>, @@ -57,18 +68,27 @@ pub struct Executor { impl Executor { /// Create a new Executor. - /// - /// On multi_core systems this will use software-interrupt 0 which isn't - /// available for anything else. + #[cfg_attr( + multi_core, + doc = r#" + This will use software-interrupt 3 which isn't + available for anything else to wake the other core(s). + "# + )] pub fn new() -> Self { #[cfg(multi_core)] unsafe { - crate::system::SoftwareInterrupt::<0>::steal() - .set_interrupt_handler(software0_interrupt) + crate::system::SoftwareInterrupt::<3>::steal() + .set_interrupt_handler(software3_interrupt) } Self { - inner: raw::Executor::new(usize::from_le_bytes([0, get_core() as u8, 0, 0]) as *mut ()), + inner: raw::Executor::new(usize::from_le_bytes([ + THREAD_MODE_CONTEXT, + get_core() as u8, + 0, + 0, + ]) as *mut ()), not_send: PhantomData, } } diff --git a/esp-hal/src/embassy/mod.rs b/esp-hal/src/embassy/mod.rs index 188c861fb..b8c481bdc 100644 --- a/esp-hal/src/embassy/mod.rs +++ b/esp-hal/src/embassy/mod.rs @@ -1,81 +1,27 @@ -//! # Embassy driver +//! # Embassy //! -//! ## Overview -//! The `embassy` driver for ESP chips is an essential part of the Embassy -//! embedded async/await runtime and is used by applications to perform -//! time-based operations and schedule asynchronous tasks. It provides a -//! high-level API for handling timers and alarms, abstracting the underlying -//! hardware details, and allowing users to focus on application logic rather -//! than low-level timer management. +//! The [embassy](https://github.com/embassy-rs/embassy) project is a toolkit to leverage async Rust +//! in embedded applications. This module adds the required +//! support to use embassy on Espressif chips. //! -//! Here are important details about the module: -//! * `time_driver` module (`time_driver_systimer` or `time_driver_timg`, -//! depends on enabled feature) -//! - This module contains the implementations of the timer drivers for -//! different ESP chips.
It includes the `EmbassyTimer` struct, which -//! is responsible for handling alarms and timer events. -//! - `EmbassyTimer` struct represents timer driver for ESP chips. It -//! contains `alarms` - an array of `AlarmState` structs, which describe -//! the state of alarms associated with the timer driver. -//! * `AlarmState` struct -//! - This struct represents the state of an alarm. It contains information -//! about the alarm's timestamp, a callback function to be executed when -//! the alarm triggers, and a context pointer for passing user-defined -//! data to the callback. -//! * `executor` module -//! - This module contains the implementations of a multi-core safe -//! thread-mode and an interrupt-mode executor for Xtensa-based ESP chips. +//! ## Initialization //! -//! ## Example -//! The following example demonstrates how to use the `embassy` driver to -//! schedule asynchronous tasks.
In this example, we use the `embassy` -//! driver to wait for a GPIO 9 pin state to change. +//! Embassy **must** be initialized by calling [`init`], before beginning any +//! async operations. //! -//! ```no_run -//! #[cfg(feature = "embassy-time-systick")] -//! embassy::init( -//! &clocks, -//! esp_hal::systimer::SystemTimer::new(peripherals.SYSTIMER), -//! ); +//! [`init`] installs a [global time driver](https://github.com/embassy-rs/embassy/tree/main/embassy-time#global-time-driver) +//! allowing users to use [embassy-time](https://docs.rs/embassy-time/latest/embassy_time/) APIs in any async context +//! within their application. A time driver must be chosen by enabling the +//! correct feature on esp-hal, see the crate level documentation for more +//! details. //! -//! #[cfg(feature = "embassy-time-timg0")] -//! embassy::init(&clocks, timer_group0.timer0); +//! ## Executors //! -//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! // GPIO 9 as input -//! let input = io.pins.gpio9.into_pull_down_input(); -//! -//! // Async requires the GPIO interrupt to wake futures -//! esp_hal::interrupt::enable( -//! esp_hal::peripherals::Interrupt::GPIO, -//! esp_hal::interrupt::Priority::Priority1, -//! ) -//! .unwrap(); -//! -//! let executor = make_static!(Executor::new()); -//! executor.run(|spawner| { -//! spawner.spawn(ping(input)).ok(); -//! }); -//! ``` -//! -//! Where `ping` defined as: -//! ```no_run -//! async fn ping(mut pin: Gpio9>) { -//! loop { -//! esp_println::println!("Waiting..."); -//! pin.wait_for_rising_edge().await.unwrap(); -//! esp_println::println!("Ping!"); -//! Timer::after(Duration::from_millis(100)).await; -//! } -//! } -//! ``` -//! For more embassy-related examples check out the [examples repo](https://github.com/esp-rs/esp-hal/tree/main/esp32-hal/examples) -//! for a corresponding board. +//! We offer two executor types, a thread mode [`Executor`](executor::Executor) +//! and [`InterruptExecutor`](executor::InterruptExecutor). +//! An [`InterruptExecutor`](executor::InterruptExecutor) can be used to achieve +//! preemptive multitasking in async applications, which is usually something reserved for more traditional RTOS systems, read more about it in [the embassy documentation](https://embassy.dev/book/dev/runtime.html). -#[cfg(any( - feature = "embassy-executor-interrupt", - feature = "embassy-executor-thread" -))] pub mod executor; use core::cell::Cell; @@ -102,12 +48,12 @@ use time_driver::EmbassyTimer; use crate::clock::Clocks; -/// Initialise embassy -pub fn init(clocks: &Clocks, td: time_driver::TimerType) { - EmbassyTimer::init(clocks, td) +/// Initialize embassy +pub fn init(clocks: &Clocks, time_driver: time_driver::TimerType) { + EmbassyTimer::init(clocks, time_driver) } -pub struct AlarmState { +pub(crate) struct AlarmState { pub callback: Cell>, pub allocated: Cell, } diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index d28398818..9d1917d24 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -229,30 +229,33 @@ impl crate::peripheral::Peripheral for SoftwareInterrupt { impl crate::private::Sealed for SoftwareInterrupt {} /// This gives access to the available software interrupts. -/// -/// Please note: Software interrupt 0 is not available when using the -/// `embassy-executor-thread` feature +#[cfg_attr( + multi_core, + doc = r#" +Please note: Software interrupt 3 is reserved +for inter-processor communication when the `embassy` +feature is enabled."# +)] #[non_exhaustive] pub struct SoftwareInterruptControl { - #[cfg(not(all(feature = "embassy-executor-thread", multi_core)))] pub software_interrupt0: SoftwareInterrupt<0>, pub software_interrupt1: SoftwareInterrupt<1>, pub software_interrupt2: SoftwareInterrupt<2>, + #[cfg(not(all(feature = "embassy", multi_core)))] pub software_interrupt3: SoftwareInterrupt<3>, } impl SoftwareInterruptControl { fn new() -> Self { - // the thread-executor uses SW-INT0 when used on a multi-core system - // we cannot easily require `software_interrupt0` there since it's created - // before `main` via proc-macro - SoftwareInterruptControl { - #[cfg(not(all(feature = "embassy-executor-thread", multi_core)))] - software_interrupt0: SoftwareInterrupt, - software_interrupt1: SoftwareInterrupt, - software_interrupt2: SoftwareInterrupt, - software_interrupt3: SoftwareInterrupt, + software_interrupt0: SoftwareInterrupt {}, + software_interrupt1: SoftwareInterrupt {}, + software_interrupt2: SoftwareInterrupt {}, + // the thread-executor uses SW-INT3 when used on a multi-core system + // we cannot easily require `software_interrupt3` there since it's created + // before `main` via proc-macro so we cfg it away from users + #[cfg(not(all(feature = "embassy", multi_core)))] + software_interrupt3: SoftwareInterrupt {}, } } } diff --git a/examples/Cargo.toml b/examples/Cargo.toml index d98ba62f0..14b02c74f 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -63,9 +63,6 @@ embedded-hal = ["esp-hal/embedded-hal"] embassy = ["esp-hal/embassy"] -embassy-executor-thread = ["esp-hal/embassy-executor-thread"] -embassy-executor-interrupt = ["esp-hal/embassy-executor-interrupt"] - embassy-time-systick-16mhz = ["esp-hal/embassy-time-systick-16mhz"] embassy-time-timg0 = ["esp-hal/embassy-time-timg0"] embassy-generic-timers = ["embassy-time/generic-queue-8"] diff --git a/examples/README.md b/examples/README.md index 3b3dcfd2e..ba0f3ffc6 100644 --- a/examples/README.md +++ b/examples/README.md @@ -40,7 +40,7 @@ To demonstrated, in `src/bin/embassy_hello_world.rs` you will see the following: ```rust //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: embassy embassy-generic-timers embassy-time-timg0 embassy-executor-thread +//% FEATURES: embassy embassy-generic-timers embassy-time-timg0 ``` Another thing to be aware of is the GPIO pins being used. We have tried to use pins available the DevKit-C boards from Espressif, however this is being done on a best-effort basis. diff --git a/examples/src/bin/embassy_hello_world.rs b/examples/src/bin/embassy_hello_world.rs index 26ac4549d..55eb879fc 100644 --- a/examples/src/bin/embassy_hello_world.rs +++ b/examples/src/bin/embassy_hello_world.rs @@ -4,11 +4,10 @@ //! concurrently. //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: embassy embassy-time-timg0 embassy-executor-thread embassy-generic-timers +//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; diff --git a/examples/src/bin/embassy_hello_world_systimer.rs b/examples/src/bin/embassy_hello_world_systimer.rs index b11796ead..80636d749 100644 --- a/examples/src/bin/embassy_hello_world_systimer.rs +++ b/examples/src/bin/embassy_hello_world_systimer.rs @@ -6,11 +6,10 @@ //! It's not supported on ESP32, on ESP32-S2 the frequency of the systimer is different (so it's left out here) //% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s3 -//% FEATURES: embassy embassy-time-systick-16mhz embassy-executor-thread embassy-generic-timers +//% FEATURES: embassy embassy-time-systick-16mhz embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; diff --git a/examples/src/bin/embassy_i2c.rs b/examples/src/bin/embassy_i2c.rs index 2ca34f068..8c57d8d2a 100644 --- a/examples/src/bin/embassy_i2c.rs +++ b/examples/src/bin/embassy_i2c.rs @@ -11,11 +11,10 @@ //! LIS3DH to get accelerometer data. //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; diff --git a/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs b/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs index fb3cc3720..34b5ed7f6 100644 --- a/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs +++ b/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs @@ -12,7 +12,7 @@ //! //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] diff --git a/examples/src/bin/embassy_i2s_read.rs b/examples/src/bin/embassy_i2s_read.rs index 08009d46c..dba429a59 100644 --- a/examples/src/bin/embassy_i2s_read.rs +++ b/examples/src/bin/embassy_i2s_read.rs @@ -12,11 +12,10 @@ //! You can also inspect the MCLK, BCLK and WS with a logic analyzer. //% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use esp_backtrace as _; diff --git a/examples/src/bin/embassy_i2s_sound.rs b/examples/src/bin/embassy_i2s_sound.rs index df80e35bb..32bdc1440 100644 --- a/examples/src/bin/embassy_i2s_sound.rs +++ b/examples/src/bin/embassy_i2s_sound.rs @@ -27,11 +27,10 @@ //! | XSMT | +3V3 | //% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use esp_backtrace as _; diff --git a/examples/src/bin/embassy_multicore.rs b/examples/src/bin/embassy_multicore.rs index 46ddc6a96..b0bf2a76a 100644 --- a/examples/src/bin/embassy_multicore.rs +++ b/examples/src/bin/embassy_multicore.rs @@ -4,11 +4,10 @@ //! signal set by the task running on the other core. //% CHIPS: esp32 esp32s3 -//% FEATURES: embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use core::ptr::addr_of_mut; @@ -28,7 +27,7 @@ use esp_hal::{ timer::timg::TimerGroup, }; use esp_println::println; -use static_cell::make_static; +use static_cell::StaticCell; static mut APP_CORE_STACK: Stack<8192> = Stack::new(); @@ -64,13 +63,15 @@ async fn main(_spawner: Spawner) { let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL); - let led_ctrl_signal = &*make_static!(Signal::new()); + static LED_CTRL: StaticCell> = StaticCell::new(); + let led_ctrl_signal = &*LED_CTRL.init(Signal::new()); let led = io.pins.gpio0.into_push_pull_output(); let _guard = cpu_control .start_app_core(unsafe { &mut *addr_of_mut!(APP_CORE_STACK) }, move || { - let executor = make_static!(Executor::new()); + static EXECUTOR: StaticCell = StaticCell::new(); + let executor = EXECUTOR.init(Executor::new()); executor.run(|spawner| { spawner.spawn(control_led(led, led_ctrl_signal)).ok(); }); diff --git a/examples/src/bin/embassy_multicore_interrupt.rs b/examples/src/bin/embassy_multicore_interrupt.rs index d2908ee5e..b62e3a2ff 100644 --- a/examples/src/bin/embassy_multicore_interrupt.rs +++ b/examples/src/bin/embassy_multicore_interrupt.rs @@ -4,11 +4,10 @@ //! signal set by the task running on the other core. //% CHIPS: esp32 esp32s3 -//% FEATURES: embassy embassy-executor-interrupt embassy-time-timg0 embassy-generic-timers +//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use core::ptr::addr_of_mut; @@ -28,7 +27,7 @@ use esp_hal::{ timer::timg::TimerGroup, }; use esp_println::println; -use static_cell::make_static; +use static_cell::StaticCell; static mut APP_CORE_STACK: Stack<8192> = Stack::new(); @@ -83,29 +82,31 @@ fn main() -> ! { let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL); - let led_ctrl_signal = &*make_static!(Signal::new()); + static LED_CTRL: StaticCell> = StaticCell::new(); + let led_ctrl_signal = &*LED_CTRL.init(Signal::new()); let led = io.pins.gpio0.into_push_pull_output(); + static EXECUTOR_CORE_1: StaticCell> = StaticCell::new(); let executor_core1 = InterruptExecutor::new(system.software_interrupt_control.software_interrupt1); - let executor_core1 = make_static!(executor_core1); + let executor_core1 = EXECUTOR_CORE_1.init(executor_core1); - let cpu1_fnctn = move || { - let spawner = executor_core1.start(Priority::Priority1); - - spawner.spawn(control_led(led, led_ctrl_signal)).ok(); - - // Just loop to show that the main thread does not need to poll the executor. - loop {} - }; let _guard = cpu_control - .start_app_core(unsafe { &mut *addr_of_mut!(APP_CORE_STACK) }, cpu1_fnctn) + .start_app_core(unsafe { &mut *addr_of_mut!(APP_CORE_STACK) }, move || { + let spawner = executor_core1.start(Priority::Priority1); + + spawner.spawn(control_led(led, led_ctrl_signal)).ok(); + + // Just loop to show that the main thread does not need to poll the executor. + loop {} + }) .unwrap(); + static EXECUTOR_CORE_0: StaticCell> = StaticCell::new(); let executor_core0 = InterruptExecutor::new(system.software_interrupt_control.software_interrupt0); - let executor_core0 = make_static!(executor_core0); + let executor_core0 = EXECUTOR_CORE_0.init(executor_core0); let spawner = executor_core0.start(Priority::Priority1); spawner.spawn(enable_disable_led(led_ctrl_signal)).ok(); diff --git a/examples/src/bin/embassy_multiprio.rs b/examples/src/bin/embassy_multiprio.rs index 403af9ca7..9bc6d93a8 100644 --- a/examples/src/bin/embassy_multiprio.rs +++ b/examples/src/bin/embassy_multiprio.rs @@ -16,11 +16,10 @@ // The interrupt-executor is created in `main` and is used to spawn `high_prio`. //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: embassy embassy-executor-interrupt embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_time::{Duration, Instant, Ticker, Timer}; @@ -35,7 +34,7 @@ use esp_hal::{ timer::timg::TimerGroup, }; use esp_println::println; -use static_cell::make_static; +use static_cell::StaticCell; /// Periodically print something. #[embassy_executor::task] @@ -83,8 +82,9 @@ async fn main(low_prio_spawner: Spawner) { let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); embassy::init(&clocks, timg0); + static EXECUTOR: StaticCell> = StaticCell::new(); let executor = InterruptExecutor::new(system.software_interrupt_control.software_interrupt2); - let executor = make_static!(executor); + let executor = EXECUTOR.init(executor); let spawner = executor.start(Priority::Priority3); spawner.must_spawn(high_prio()); diff --git a/examples/src/bin/embassy_parl_io_rx.rs b/examples/src/bin/embassy_parl_io_rx.rs index c0be0866c..51bb353be 100644 --- a/examples/src/bin/embassy_parl_io_rx.rs +++ b/examples/src/bin/embassy_parl_io_rx.rs @@ -4,11 +4,10 @@ //! Uses GPIO 1, 2, 3 and 4 as the data pins. //% CHIPS: esp32c6 esp32h2 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; diff --git a/examples/src/bin/embassy_parl_io_tx.rs b/examples/src/bin/embassy_parl_io_tx.rs index 0378df55d..a873396d6 100644 --- a/examples/src/bin/embassy_parl_io_tx.rs +++ b/examples/src/bin/embassy_parl_io_tx.rs @@ -8,11 +8,10 @@ //! You can use a logic analyzer to see how the pins are used. //% CHIPS: esp32c6 esp32h2 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; diff --git a/examples/src/bin/embassy_rmt_rx.rs b/examples/src/bin/embassy_rmt_rx.rs index ea3e27471..d559cbae1 100644 --- a/examples/src/bin/embassy_rmt_rx.rs +++ b/examples/src/bin/embassy_rmt_rx.rs @@ -2,11 +2,10 @@ //! Connect GPIO5 to GPIO4 //% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; diff --git a/examples/src/bin/embassy_rmt_tx.rs b/examples/src/bin/embassy_rmt_tx.rs index 1e33e9689..d0b9456e7 100644 --- a/examples/src/bin/embassy_rmt_tx.rs +++ b/examples/src/bin/embassy_rmt_tx.rs @@ -3,11 +3,10 @@ //! Connect a logic analyzer to GPIO4 to see the generated pulses. //% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; diff --git a/examples/src/bin/embassy_serial.rs b/examples/src/bin/embassy_serial.rs index 5de67d5e5..e0ddb9a9a 100644 --- a/examples/src/bin/embassy_serial.rs +++ b/examples/src/bin/embassy_serial.rs @@ -5,10 +5,9 @@ #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers use embassy_executor::Spawner; use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal}; @@ -23,7 +22,7 @@ use esp_hal::{ uart::{config::AtCmdConfig, Uart, UartRx, UartTx}, Async, }; -use static_cell::make_static; +use static_cell::StaticCell; // rx_fifo_full_threshold const READ_BUF_SIZE: usize = 64; @@ -91,7 +90,8 @@ async fn main(spawner: Spawner) { .unwrap(); let (tx, rx) = uart0.split(); - let signal = &*make_static!(Signal::new()); + static SIGNAL: StaticCell> = StaticCell::new(); + let signal = &*SIGNAL.init(Signal::new()); spawner.spawn(reader(rx, &signal)).ok(); spawner.spawn(writer(tx, &signal)).ok(); diff --git a/examples/src/bin/embassy_spi.rs b/examples/src/bin/embassy_spi.rs index 46afc87fc..fec1f878f 100644 --- a/examples/src/bin/embassy_spi.rs +++ b/examples/src/bin/embassy_spi.rs @@ -15,11 +15,10 @@ //! This is an example of running the embassy executor with SPI. //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; diff --git a/examples/src/bin/embassy_systimer_delay.rs b/examples/src/bin/embassy_systimer_delay.rs index 1bda407a9..3f9ebf3a4 100644 --- a/examples/src/bin/embassy_systimer_delay.rs +++ b/examples/src/bin/embassy_systimer_delay.rs @@ -3,11 +3,10 @@ //! This is an example of using the `DelayNs` trait implementation //% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: embassy embassy-time-timg0 embassy-executor-thread embassy-generic-timers async +//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers async #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embedded_hal_async::delay::DelayNs; diff --git a/examples/src/bin/embassy_twai.rs b/examples/src/bin/embassy_twai.rs index 4d6ac16ff..35aa26404 100644 --- a/examples/src/bin/embassy_twai.rs +++ b/examples/src/bin/embassy_twai.rs @@ -11,11 +11,10 @@ //! with `IS_SENDER` set to `true`. //% CHIPS: esp32c3 esp32c6 esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_sync::{blocking_mutex::raw::NoopRawMutex, channel::Channel}; @@ -33,7 +32,7 @@ use esp_hal::{ twai::{self, EspTwaiFrame, TwaiRx, TwaiTx}, }; use esp_println::println; -use static_cell::make_static; +use static_cell::StaticCell; type TwaiOutbox = Channel; @@ -133,7 +132,8 @@ async fn main(spawner: Spawner) { ) .unwrap(); - let channel = &*make_static!(Channel::new()); + static CHANNEL: StaticCell = StaticCell::new(); + let channel = &*CHANNEL.init(Channel::new()); spawner.spawn(receiver(rx, channel)).ok(); spawner.spawn(transmitter(tx, channel)).ok(); diff --git a/examples/src/bin/embassy_usb_serial.rs b/examples/src/bin/embassy_usb_serial.rs index ab064c752..e6ca68fac 100644 --- a/examples/src/bin/embassy_usb_serial.rs +++ b/examples/src/bin/embassy_usb_serial.rs @@ -3,7 +3,7 @@ //! This example should be built in release mode. //% CHIPS: esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] diff --git a/examples/src/bin/embassy_usb_serial_jtag.rs b/examples/src/bin/embassy_usb_serial_jtag.rs index c5fd6fa8b..8eb6d2c5f 100644 --- a/examples/src/bin/embassy_usb_serial_jtag.rs +++ b/examples/src/bin/embassy_usb_serial_jtag.rs @@ -3,11 +3,10 @@ //! Most dev-kits use a USB-UART-bridge - in that case you won't see any output. //% CHIPS: esp32c3 esp32c6 esp32h2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal}; @@ -22,7 +21,7 @@ use esp_hal::{ usb_serial_jtag::{UsbSerialJtag, UsbSerialJtagRx, UsbSerialJtagTx}, Async, }; -use static_cell::make_static; +use static_cell::StaticCell; const MAX_BUFFER_SIZE: usize = 512; @@ -76,7 +75,9 @@ async fn main(spawner: Spawner) -> () { let (tx, rx) = UsbSerialJtag::new_async(peripherals.USB_DEVICE).split(); - let signal = &*make_static!(Signal::new()); + static SIGNAL: StaticCell>> = + StaticCell::new(); + let signal = &*SIGNAL.init(Signal::new()); spawner.spawn(reader(rx, &signal)).unwrap(); spawner.spawn(writer(tx, &signal)).unwrap(); diff --git a/examples/src/bin/embassy_wait.rs b/examples/src/bin/embassy_wait.rs index 8c367f130..d4ca2ef46 100644 --- a/examples/src/bin/embassy_wait.rs +++ b/examples/src/bin/embassy_wait.rs @@ -3,11 +3,10 @@ //! This is an example of asynchronously `Wait`ing for a pin state to change. //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: async embassy embassy-executor-thread embassy-time-timg0 embassy-generic-timers +//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers #![no_std] #![no_main] -#![feature(type_alias_impl_trait)] use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index 66ac0e2a1..f68219678 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -88,7 +88,7 @@ p192 = { version = "0.13.0", default-features = false, features = p256 = { version = "0.13.2", default-features = false, features = ["arithmetic"] } [features] -default = ["async", "embassy", "embassy-executor-thread", "embassy-time-timg0"] +default = ["async", "embassy", "embassy-time-timg0"] # Device support (required!): esp32 = [ @@ -117,8 +117,6 @@ embassy = [ "embedded-test/external-executor", "esp-hal?/embassy", ] -embassy-executor-interrupt = ["esp-hal?/embassy-executor-interrupt"] -embassy-executor-thread = ["esp-hal?/embassy-executor-thread"] embassy-time-systick-16mhz = ["esp-hal?/embassy-time-systick-16mhz"] embassy-time-systick-80mhz = ["esp-hal?/embassy-time-systick-80mhz"] embassy-time-timg0 = ["esp-hal?/embassy-time-timg0"] diff --git a/hil-test/tests/gpio.rs b/hil-test/tests/gpio.rs index cce2b2c17..1cfc878b0 100644 --- a/hil-test/tests/gpio.rs +++ b/hil-test/tests/gpio.rs @@ -71,7 +71,7 @@ pub fn interrupt_handler() { } #[cfg(test)] -#[embedded_test::tests(executor = esp_hal::embassy::executor::thread::Executor::new())] +#[embedded_test::tests(executor = esp_hal::embassy::executor::Executor::new())] mod tests { use defmt::assert_eq; use embassy_time::{Duration, Timer}; diff --git a/hil-test/tests/uart_async.rs b/hil-test/tests/uart_async.rs index 4592de0bf..4a282f95d 100644 --- a/hil-test/tests/uart_async.rs +++ b/hil-test/tests/uart_async.rs @@ -47,7 +47,7 @@ impl Context { } #[cfg(test)] -#[embedded_test::tests(executor = esp_hal::embassy::executor::thread::Executor::new())] +#[embedded_test::tests(executor = esp_hal::embassy::executor::Executor::new())] mod tests { use defmt::assert_eq;