diff options
Diffstat (limited to 'embassy-executor/src/arch/cortex_m.rs')
| -rw-r--r-- | embassy-executor/src/arch/cortex_m.rs | 21 |
1 files changed, 9 insertions, 12 deletions
diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs index fde862f3c..55299c94f 100644 --- a/embassy-executor/src/arch/cortex_m.rs +++ b/embassy-executor/src/arch/cortex_m.rs | |||
| @@ -115,12 +115,12 @@ mod thread { | |||
| 115 | pub use interrupt::*; | 115 | pub use interrupt::*; |
| 116 | #[cfg(feature = "executor-interrupt")] | 116 | #[cfg(feature = "executor-interrupt")] |
| 117 | mod interrupt { | 117 | mod interrupt { |
| 118 | use core::cell::UnsafeCell; | 118 | use core::cell::{Cell, UnsafeCell}; |
| 119 | use core::mem::MaybeUninit; | 119 | use core::mem::MaybeUninit; |
| 120 | 120 | ||
| 121 | use atomic_polyfill::{AtomicBool, Ordering}; | ||
| 122 | use cortex_m::interrupt::InterruptNumber; | 121 | use cortex_m::interrupt::InterruptNumber; |
| 123 | use cortex_m::peripheral::NVIC; | 122 | use cortex_m::peripheral::NVIC; |
| 123 | use critical_section::Mutex; | ||
| 124 | 124 | ||
| 125 | use crate::raw; | 125 | use crate::raw; |
| 126 | 126 | ||
| @@ -146,7 +146,7 @@ mod interrupt { | |||
| 146 | /// It is somewhat more complex to use, it's recommended to use the thread-mode | 146 | /// It is somewhat more complex to use, it's recommended to use the thread-mode |
| 147 | /// [`Executor`] instead, if it works for your use case. | 147 | /// [`Executor`] instead, if it works for your use case. |
| 148 | pub struct InterruptExecutor { | 148 | pub struct InterruptExecutor { |
| 149 | started: AtomicBool, | 149 | started: Mutex<Cell<bool>>, |
| 150 | executor: UnsafeCell<MaybeUninit<raw::Executor>>, | 150 | executor: UnsafeCell<MaybeUninit<raw::Executor>>, |
| 151 | } | 151 | } |
| 152 | 152 | ||
| @@ -158,7 +158,7 @@ mod interrupt { | |||
| 158 | #[inline] | 158 | #[inline] |
| 159 | pub const fn new() -> Self { | 159 | pub const fn new() -> Self { |
| 160 | Self { | 160 | Self { |
| 161 | started: AtomicBool::new(false), | 161 | started: Mutex::new(Cell::new(false)), |
| 162 | executor: UnsafeCell::new(MaybeUninit::uninit()), | 162 | executor: UnsafeCell::new(MaybeUninit::uninit()), |
| 163 | } | 163 | } |
| 164 | } | 164 | } |
| @@ -167,7 +167,8 @@ mod interrupt { | |||
| 167 | /// | 167 | /// |
| 168 | /// # Safety | 168 | /// # Safety |
| 169 | /// | 169 | /// |
| 170 | /// You MUST call this from the interrupt handler, and from nowhere else. | 170 | /// - You MUST call this from the interrupt handler, and from nowhere else. |
| 171 | /// - You must not call this before calling `start()`. | ||
| 171 | pub unsafe fn on_interrupt(&'static self) { | 172 | pub unsafe fn on_interrupt(&'static self) { |
| 172 | let executor = unsafe { (&*self.executor.get()).assume_init_ref() }; | 173 | let executor = unsafe { (&*self.executor.get()).assume_init_ref() }; |
| 173 | executor.poll(); | 174 | executor.poll(); |
| @@ -196,11 +197,7 @@ mod interrupt { | |||
| 196 | /// do it after. | 197 | /// do it after. |
| 197 | /// | 198 | /// |
| 198 | pub fn start(&'static self, irq: impl InterruptNumber) -> crate::SendSpawner { | 199 | pub fn start(&'static self, irq: impl InterruptNumber) -> crate::SendSpawner { |
| 199 | if self | 200 | if critical_section::with(|cs| self.started.borrow(cs).replace(true)) { |
| 200 | .started | ||
| 201 | .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) | ||
| 202 | .is_err() | ||
| 203 | { | ||
| 204 | panic!("InterruptExecutor::start() called multiple times on the same executor."); | 201 | panic!("InterruptExecutor::start() called multiple times on the same executor."); |
| 205 | } | 202 | } |
| 206 | 203 | ||
| @@ -222,10 +219,10 @@ mod interrupt { | |||
| 222 | /// This returns a [`SendSpawner`] you can use to spawn tasks on this | 219 | /// This returns a [`SendSpawner`] you can use to spawn tasks on this |
| 223 | /// executor. | 220 | /// executor. |
| 224 | /// | 221 | /// |
| 225 | /// This MUST only be called on an executor that has already been spawned. | 222 | /// This MUST only be called on an executor that has already been started. |
| 226 | /// The function will panic otherwise. | 223 | /// The function will panic otherwise. |
| 227 | pub fn spawner(&'static self) -> crate::SendSpawner { | 224 | pub fn spawner(&'static self) -> crate::SendSpawner { |
| 228 | if !self.started.load(Ordering::Acquire) { | 225 | if !critical_section::with(|cs| self.started.borrow(cs).get()) { |
| 229 | panic!("InterruptExecutor::spawner() called on uninitialized executor."); | 226 | panic!("InterruptExecutor::spawner() called on uninitialized executor."); |
| 230 | } | 227 | } |
| 231 | let executor = unsafe { (&*self.executor.get()).assume_init_ref() }; | 228 | let executor = unsafe { (&*self.executor.get()).assume_init_ref() }; |
