Merge 05303d1e37 into 040c0fd353
This commit is contained in:
commit
c7f35c3602
@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed an issue with using thread-mode executors on both cores (#2924)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
## 0.5.0 - 2024-11-20
|
## 0.5.0 - 2024-11-20
|
||||||
|
|||||||
@ -3,9 +3,9 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use embassy_executor::{raw, Spawner};
|
use embassy_executor::{raw, Spawner};
|
||||||
use esp_hal::Cpu;
|
|
||||||
#[cfg(multi_core)]
|
#[cfg(multi_core)]
|
||||||
use esp_hal::{interrupt::software::SoftwareInterrupt, macros::handler};
|
use esp_hal::interrupt::software::SoftwareInterrupt;
|
||||||
|
use esp_hal::{interrupt::Priority, Cpu};
|
||||||
#[cfg(low_power_wait)]
|
#[cfg(low_power_wait)]
|
||||||
use portable_atomic::{AtomicBool, Ordering};
|
use portable_atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
@ -16,16 +16,6 @@ pub(crate) const THREAD_MODE_CONTEXT: usize = 16;
|
|||||||
static SIGNAL_WORK_THREAD_MODE: [AtomicBool; Cpu::COUNT] =
|
static SIGNAL_WORK_THREAD_MODE: [AtomicBool; Cpu::COUNT] =
|
||||||
[const { AtomicBool::new(false) }; Cpu::COUNT];
|
[const { AtomicBool::new(false) }; Cpu::COUNT];
|
||||||
|
|
||||||
#[cfg(all(multi_core, low_power_wait))]
|
|
||||||
#[handler]
|
|
||||||
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`.
|
|
||||||
unsafe { SoftwareInterrupt::<3>::steal().reset() };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn pend_thread_mode(_core: usize) {
|
pub(crate) fn pend_thread_mode(_core: usize) {
|
||||||
#[cfg(low_power_wait)]
|
#[cfg(low_power_wait)]
|
||||||
{
|
{
|
||||||
@ -68,11 +58,6 @@ impl Executor {
|
|||||||
This will use software-interrupt 3 which isn't available for anything else to wake the other core(s)."#
|
This will use software-interrupt 3 which isn't available for anything else to wake the other core(s)."#
|
||||||
)]
|
)]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
#[cfg(all(multi_core, low_power_wait))]
|
|
||||||
unsafe {
|
|
||||||
SoftwareInterrupt::<3>::steal().set_interrupt_handler(software3_interrupt);
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inner: raw::Executor::new((THREAD_MODE_CONTEXT + Cpu::current() as usize) as *mut ()),
|
inner: raw::Executor::new((THREAD_MODE_CONTEXT + Cpu::current() as usize) as *mut ()),
|
||||||
not_send: PhantomData,
|
not_send: PhantomData,
|
||||||
@ -100,6 +85,11 @@ This will use software-interrupt 3 which isn't available for anything else to wa
|
|||||||
///
|
///
|
||||||
/// This function never returns.
|
/// This function never returns.
|
||||||
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
||||||
|
unwrap!(esp_hal::interrupt::enable(
|
||||||
|
esp_hal::peripherals::Interrupt::FROM_CPU_INTR3,
|
||||||
|
Priority::min(),
|
||||||
|
));
|
||||||
|
|
||||||
init(self.inner.spawner());
|
init(self.inner.spawner());
|
||||||
|
|
||||||
#[cfg(low_power_wait)]
|
#[cfg(low_power_wait)]
|
||||||
|
|||||||
@ -158,5 +158,24 @@ impl_array!(4);
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn init(time_driver: impl TimerCollection) {
|
pub fn init(time_driver: impl TimerCollection) {
|
||||||
|
#[cfg(all(feature = "executors", multi_core, low_power_wait))]
|
||||||
|
unsafe {
|
||||||
|
use esp_hal::interrupt::software::SoftwareInterrupt;
|
||||||
|
|
||||||
|
#[esp_hal::macros::ram]
|
||||||
|
extern "C" 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`.
|
||||||
|
unsafe { SoftwareInterrupt::<3>::steal().reset() };
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_hal::interrupt::bind_interrupt(
|
||||||
|
esp_hal::peripherals::Interrupt::FROM_CPU_INTR3,
|
||||||
|
software3_interrupt,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
EmbassyTimer::init(time_driver.timers())
|
EmbassyTimer::init(time_driver.timers())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,8 @@ use esp_hal::{
|
|||||||
},
|
},
|
||||||
timer::AnyTimer,
|
timer::AnyTimer,
|
||||||
};
|
};
|
||||||
|
#[cfg(multi_core)]
|
||||||
|
use esp_hal_embassy::Executor;
|
||||||
use esp_hal_embassy::InterruptExecutor;
|
use esp_hal_embassy::InterruptExecutor;
|
||||||
use hil_test as _;
|
use hil_test as _;
|
||||||
|
|
||||||
@ -31,10 +33,11 @@ macro_rules! mk_static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn interrupt_driven_task(
|
async fn responder_task(
|
||||||
signal: &'static Signal<CriticalSectionRawMutex, ()>,
|
signal: &'static Signal<CriticalSectionRawMutex, ()>,
|
||||||
response: &'static Signal<CriticalSectionRawMutex, ()>,
|
response: &'static Signal<CriticalSectionRawMutex, ()>,
|
||||||
) {
|
) {
|
||||||
|
response.signal(());
|
||||||
loop {
|
loop {
|
||||||
signal.wait().await;
|
signal.wait().await;
|
||||||
response.signal(());
|
response.signal(());
|
||||||
@ -99,10 +102,9 @@ mod test {
|
|||||||
|
|
||||||
let spawner = interrupt_executor.start(Priority::Priority3);
|
let spawner = interrupt_executor.start(Priority::Priority3);
|
||||||
|
|
||||||
spawner
|
spawner.spawn(responder_task(signal, response)).unwrap();
|
||||||
.spawn(interrupt_driven_task(signal, response))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
|
response.wait().await;
|
||||||
for _ in 0..3 {
|
for _ in 0..3 {
|
||||||
signal.signal(());
|
signal.signal(());
|
||||||
response.wait().await;
|
response.wait().await;
|
||||||
@ -123,20 +125,44 @@ mod test {
|
|||||||
|
|
||||||
let spawner = interrupt_executor.start(Priority::Priority3);
|
let spawner = interrupt_executor.start(Priority::Priority3);
|
||||||
|
|
||||||
spawner
|
spawner.spawn(responder_task(signal, response)).unwrap();
|
||||||
.spawn(interrupt_driven_task(signal, response))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(static_mut_refs)]
|
|
||||||
let _guard = ctx
|
let _guard = ctx
|
||||||
.cpu_control
|
.cpu_control
|
||||||
.start_app_core(app_core_stack, cpu1_fnctn)
|
.start_app_core(app_core_stack, cpu1_fnctn)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
response.wait().await;
|
||||||
|
for _ in 0..3 {
|
||||||
|
signal.signal(());
|
||||||
|
response.wait().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(multi_core)]
|
||||||
|
async fn run_thread_executor_test_on_core_1(mut ctx: Context) {
|
||||||
|
let app_core_stack = mk_static!(Stack<8192>, Stack::new());
|
||||||
|
let signal = mk_static!(Signal<CriticalSectionRawMutex, ()>, Signal::new());
|
||||||
|
let response = mk_static!(Signal<CriticalSectionRawMutex, ()>, Signal::new());
|
||||||
|
|
||||||
|
let cpu1_fnctn = || {
|
||||||
|
let executor = mk_static!(Executor, Executor::new());
|
||||||
|
executor.run(|spawner| {
|
||||||
|
spawner.spawn(responder_task(signal, response)).ok();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let _guard = ctx
|
||||||
|
.cpu_control
|
||||||
|
.start_app_core(app_core_stack, cpu1_fnctn)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
response.wait().await;
|
||||||
for _ in 0..3 {
|
for _ in 0..3 {
|
||||||
signal.signal(());
|
signal.signal(());
|
||||||
response.wait().await;
|
response.wait().await;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user