From 24510e3322340c39fc3de0b36ed557e067fb19ee Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Sun, 21 Apr 2024 22:57:13 +0100 Subject: [PATCH] Add thread mode context id and fix up examples --- esp-hal/src/embassy/executor/interrupt.rs | 5 +--- esp-hal/src/embassy/executor/mod.rs | 18 +++++++------ esp-hal/src/embassy/executor/thread.rs | 9 ++++++- esp-hal/src/system.rs | 7 +++-- .../embassy_i2c_bmp180_calibration_data.rs | 2 +- examples/src/bin/embassy_multicore.rs | 8 +++--- .../src/bin/embassy_multicore_interrupt.rs | 26 ++++++++++--------- examples/src/bin/embassy_multiprio.rs | 5 ++-- examples/src/bin/embassy_serial.rs | 5 ++-- examples/src/bin/embassy_twai.rs | 5 ++-- examples/src/bin/embassy_usb_serial_jtag.rs | 6 +++-- 11 files changed, 55 insertions(+), 41 deletions(-) diff --git a/esp-hal/src/embassy/executor/interrupt.rs b/esp-hal/src/embassy/executor/interrupt.rs index f27f214a588..b9485fb1b87 100644 --- a/esp-hal/src/embassy/executor/interrupt.rs +++ b/esp-hal/src/embassy/executor/interrupt.rs @@ -10,9 +10,6 @@ use crate::{ system::SoftwareInterrupt, }; -/// The number to offset SW interrupts when passed through the pender context. -pub const SW_OFFSET: u8 = 16; - static mut EXECUTORS: [CallbackContext; 4] = [ CallbackContext::new(), CallbackContext::new(), @@ -123,7 +120,7 @@ impl InterruptExecutor { unsafe { (*self.executor.get()) .as_mut_ptr() - .write(raw::Executor::new((SWI + SW_OFFSET) as *mut ())); + .write(raw::Executor::new(SWI as *mut ())); EXECUTORS[SWI as usize].set((*self.executor.get()).as_mut_ptr()); } diff --git a/esp-hal/src/embassy/executor/mod.rs b/esp-hal/src/embassy/executor/mod.rs index 9277aa8daa5..26a79668974 100644 --- a/esp-hal/src/embassy/executor/mod.rs +++ b/esp-hal/src/embassy/executor/mod.rs @@ -13,14 +13,16 @@ fn __pender(context: *mut ()) { let context = (context as usize).to_le_bytes(); match context[0] { - // 0 is reserved for thread mode executors - 0 => thread::pend_thread_mode(context[1] as usize), // For interrupt executors, the context value is the - // software interrupt number + `SW_OFFSET` - 16 => unsafe { SoftwareInterrupt::<0>::steal().raise() }, - 17 => unsafe { SoftwareInterrupt::<1>::steal().raise() }, - 18 => unsafe { SoftwareInterrupt::<2>::steal().raise() }, - 19 => unsafe { SoftwareInterrupt::<3>::steal().raise() }, - _ => {} + // 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 2c6ae33cdb6..4e885e92aa3 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 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))] @@ -68,7 +70,12 @@ impl Executor { } 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/system.rs b/esp-hal/src/system.rs index 992469ef99d..9d1917d24fe 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -247,14 +247,13 @@ pub struct SoftwareInterruptControl { 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 { 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/src/bin/embassy_i2c_bmp180_calibration_data.rs b/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs index 83a208216f7..e05ac54d7e7 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_multicore.rs b/examples/src/bin/embassy_multicore.rs index 6a2a326e3d6..a1e4521bde4 100644 --- a/examples/src/bin/embassy_multicore.rs +++ b/examples/src/bin/embassy_multicore.rs @@ -27,7 +27,7 @@ use esp_hal::{ timer::TimerGroup, }; use esp_println::println; -use static_cell::make_static; +use static_cell::StaticCell; static mut APP_CORE_STACK: Stack<8192> = Stack::new(); @@ -63,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 444fa0c0a25..28b9374722b 100644 --- a/examples/src/bin/embassy_multicore_interrupt.rs +++ b/examples/src/bin/embassy_multicore_interrupt.rs @@ -27,7 +27,7 @@ use esp_hal::{ timer::TimerGroup, }; use esp_println::println; -use static_cell::make_static; +use static_cell::StaticCell; static mut APP_CORE_STACK: Stack<8192> = Stack::new(); @@ -82,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); + let _guard = cpu_control + .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(); + 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) + // 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 15a2906dd07..02f159b3112 100644 --- a/examples/src/bin/embassy_multiprio.rs +++ b/examples/src/bin/embassy_multiprio.rs @@ -34,7 +34,7 @@ use esp_hal::{ timer::TimerGroup, }; use esp_println::println; -use static_cell::make_static; +use static_cell::StaticCell; /// Periodically print something. #[embassy_executor::task] @@ -82,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_serial.rs b/examples/src/bin/embassy_serial.rs index 5aad5b616ff..bb6f03b39cc 100644 --- a/examples/src/bin/embassy_serial.rs +++ b/examples/src/bin/embassy_serial.rs @@ -22,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; @@ -90,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_twai.rs b/examples/src/bin/embassy_twai.rs index 006a3f5d1d3..3c3e9742191 100644 --- a/examples/src/bin/embassy_twai.rs +++ b/examples/src/bin/embassy_twai.rs @@ -32,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; @@ -132,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_jtag.rs b/examples/src/bin/embassy_usb_serial_jtag.rs index 8ee305eab42..d3a116b1608 100644 --- a/examples/src/bin/embassy_usb_serial_jtag.rs +++ b/examples/src/bin/embassy_usb_serial_jtag.rs @@ -21,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; @@ -75,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();