diff options
| -rw-r--r-- | embassy/src/executor/arch/cortex_m.rs | 20 | ||||
| -rw-r--r-- | examples/nrf/src/bin/multiprio.rs | 10 | ||||
| -rw-r--r-- | examples/stm32f3/src/bin/multiprio.rs | 10 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/multiprio.rs | 10 |
4 files changed, 22 insertions, 28 deletions
diff --git a/embassy/src/executor/arch/cortex_m.rs b/embassy/src/executor/arch/cortex_m.rs index d23a595ff..87c9c3c87 100644 --- a/embassy/src/executor/arch/cortex_m.rs +++ b/embassy/src/executor/arch/cortex_m.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | use core::marker::PhantomData; | 1 | use core::marker::PhantomData; |
| 2 | use core::ptr; | 2 | use core::ptr; |
| 3 | 3 | ||
| 4 | use super::{raw, Spawner}; | 4 | use super::{raw, SendSpawner, Spawner}; |
| 5 | use crate::interrupt::{Interrupt, InterruptExt}; | 5 | use crate::interrupt::{Interrupt, InterruptExt}; |
| 6 | 6 | ||
| 7 | /// Thread mode executor, using WFE/SEV. | 7 | /// Thread mode executor, using WFE/SEV. |
| @@ -107,13 +107,13 @@ impl<I: Interrupt> InterruptExecutor<I> { | |||
| 107 | 107 | ||
| 108 | /// Start the executor. | 108 | /// Start the executor. |
| 109 | /// | 109 | /// |
| 110 | /// The `init` closure is called from interrupt mode, with a [`Spawner`] that spawns tasks on | 110 | /// This initializes the executor, configures and enables the interrupt, and returns. |
| 111 | /// this executor. Use it to spawn the initial task(s). After `init` returns, | 111 | /// The executor keeps running in the background through the interrupt. |
| 112 | /// the interrupt is configured so that the executor starts running the tasks. | ||
| 113 | /// Once the executor is started, `start` returns. | ||
| 114 | /// | 112 | /// |
| 115 | /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`), | 113 | /// This returns a [`SendSpawner`] you can use to spawn tasks on it. A [`SendSpawner`] |
| 116 | /// for example by passing it as an argument to the initial tasks. | 114 | /// is returned instead of a [`Spawner`] because the executor effectively runs in a |
| 115 | /// different "thread" (the interrupt), so spawning tasks on it is effectively | ||
| 116 | /// sending them. | ||
| 117 | /// | 117 | /// |
| 118 | /// This function requires `&'static mut self`. This means you have to store the | 118 | /// This function requires `&'static mut self`. This means you have to store the |
| 119 | /// Executor instance in a place where it'll live forever and grants you mutable | 119 | /// Executor instance in a place where it'll live forever and grants you mutable |
| @@ -122,16 +122,16 @@ impl<I: Interrupt> InterruptExecutor<I> { | |||
| 122 | /// - a [Forever](crate::util::Forever) (safe) | 122 | /// - a [Forever](crate::util::Forever) (safe) |
| 123 | /// - a `static mut` (unsafe) | 123 | /// - a `static mut` (unsafe) |
| 124 | /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) | 124 | /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) |
| 125 | pub fn start(&'static mut self, init: impl FnOnce(Spawner) + Send) { | 125 | pub fn start(&'static mut self) -> SendSpawner { |
| 126 | self.irq.disable(); | 126 | self.irq.disable(); |
| 127 | 127 | ||
| 128 | init(self.inner.spawner()); | ||
| 129 | |||
| 130 | self.irq.set_handler(|ctx| unsafe { | 128 | self.irq.set_handler(|ctx| unsafe { |
| 131 | let executor = &*(ctx as *const raw::Executor); | 129 | let executor = &*(ctx as *const raw::Executor); |
| 132 | executor.poll(); | 130 | executor.poll(); |
| 133 | }); | 131 | }); |
| 134 | self.irq.set_handler_context(&self.inner as *const _ as _); | 132 | self.irq.set_handler_context(&self.inner as *const _ as _); |
| 135 | self.irq.enable(); | 133 | self.irq.enable(); |
| 134 | |||
| 135 | self.inner.spawner().make_send() | ||
| 136 | } | 136 | } |
| 137 | } | 137 | } |
diff --git a/examples/nrf/src/bin/multiprio.rs b/examples/nrf/src/bin/multiprio.rs index e69f87d85..54f6606a9 100644 --- a/examples/nrf/src/bin/multiprio.rs +++ b/examples/nrf/src/bin/multiprio.rs | |||
| @@ -124,17 +124,15 @@ fn main() -> ! { | |||
| 124 | let irq = interrupt::take!(SWI1_EGU1); | 124 | let irq = interrupt::take!(SWI1_EGU1); |
| 125 | irq.set_priority(interrupt::Priority::P6); | 125 | irq.set_priority(interrupt::Priority::P6); |
| 126 | let executor = EXECUTOR_HIGH.put(InterruptExecutor::new(irq)); | 126 | let executor = EXECUTOR_HIGH.put(InterruptExecutor::new(irq)); |
| 127 | executor.start(|spawner| { | 127 | let spawner = executor.start(); |
| 128 | unwrap!(spawner.spawn(run_high())); | 128 | unwrap!(spawner.spawn(run_high())); |
| 129 | }); | ||
| 130 | 129 | ||
| 131 | // Medium-priority executor: SWI0_EGU0, priority level 7 | 130 | // Medium-priority executor: SWI0_EGU0, priority level 7 |
| 132 | let irq = interrupt::take!(SWI0_EGU0); | 131 | let irq = interrupt::take!(SWI0_EGU0); |
| 133 | irq.set_priority(interrupt::Priority::P7); | 132 | irq.set_priority(interrupt::Priority::P7); |
| 134 | let executor = EXECUTOR_MED.put(InterruptExecutor::new(irq)); | 133 | let executor = EXECUTOR_MED.put(InterruptExecutor::new(irq)); |
| 135 | executor.start(|spawner| { | 134 | let spawner = executor.start(); |
| 136 | unwrap!(spawner.spawn(run_med())); | 135 | unwrap!(spawner.spawn(run_med())); |
| 137 | }); | ||
| 138 | 136 | ||
| 139 | // Low priority executor: runs in thread mode, using WFE/SEV | 137 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 140 | let executor = EXECUTOR_LOW.put(Executor::new()); | 138 | let executor = EXECUTOR_LOW.put(Executor::new()); |
diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs index 1c9401549..02380de72 100644 --- a/examples/stm32f3/src/bin/multiprio.rs +++ b/examples/stm32f3/src/bin/multiprio.rs | |||
| @@ -124,17 +124,15 @@ fn main() -> ! { | |||
| 124 | let irq = interrupt::take!(UART4); | 124 | let irq = interrupt::take!(UART4); |
| 125 | irq.set_priority(interrupt::Priority::P6); | 125 | irq.set_priority(interrupt::Priority::P6); |
| 126 | let executor = EXECUTOR_HIGH.put(InterruptExecutor::new(irq)); | 126 | let executor = EXECUTOR_HIGH.put(InterruptExecutor::new(irq)); |
| 127 | executor.start(|spawner| { | 127 | let spawner = executor.start(); |
| 128 | unwrap!(spawner.spawn(run_high())); | 128 | unwrap!(spawner.spawn(run_high())); |
| 129 | }); | ||
| 130 | 129 | ||
| 131 | // Medium-priority executor: SWI0_EGU0, priority level 7 | 130 | // Medium-priority executor: SWI0_EGU0, priority level 7 |
| 132 | let irq = interrupt::take!(UART5); | 131 | let irq = interrupt::take!(UART5); |
| 133 | irq.set_priority(interrupt::Priority::P7); | 132 | irq.set_priority(interrupt::Priority::P7); |
| 134 | let executor = EXECUTOR_MED.put(InterruptExecutor::new(irq)); | 133 | let executor = EXECUTOR_MED.put(InterruptExecutor::new(irq)); |
| 135 | executor.start(|spawner| { | 134 | let spawner = executor.start(); |
| 136 | unwrap!(spawner.spawn(run_med())); | 135 | unwrap!(spawner.spawn(run_med())); |
| 137 | }); | ||
| 138 | 136 | ||
| 139 | // Low priority executor: runs in thread mode, using WFE/SEV | 137 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 140 | let executor = EXECUTOR_LOW.put(Executor::new()); | 138 | let executor = EXECUTOR_LOW.put(Executor::new()); |
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs index 1c9401549..02380de72 100644 --- a/examples/stm32f4/src/bin/multiprio.rs +++ b/examples/stm32f4/src/bin/multiprio.rs | |||
| @@ -124,17 +124,15 @@ fn main() -> ! { | |||
| 124 | let irq = interrupt::take!(UART4); | 124 | let irq = interrupt::take!(UART4); |
| 125 | irq.set_priority(interrupt::Priority::P6); | 125 | irq.set_priority(interrupt::Priority::P6); |
| 126 | let executor = EXECUTOR_HIGH.put(InterruptExecutor::new(irq)); | 126 | let executor = EXECUTOR_HIGH.put(InterruptExecutor::new(irq)); |
| 127 | executor.start(|spawner| { | 127 | let spawner = executor.start(); |
| 128 | unwrap!(spawner.spawn(run_high())); | 128 | unwrap!(spawner.spawn(run_high())); |
| 129 | }); | ||
| 130 | 129 | ||
| 131 | // Medium-priority executor: SWI0_EGU0, priority level 7 | 130 | // Medium-priority executor: SWI0_EGU0, priority level 7 |
| 132 | let irq = interrupt::take!(UART5); | 131 | let irq = interrupt::take!(UART5); |
| 133 | irq.set_priority(interrupt::Priority::P7); | 132 | irq.set_priority(interrupt::Priority::P7); |
| 134 | let executor = EXECUTOR_MED.put(InterruptExecutor::new(irq)); | 133 | let executor = EXECUTOR_MED.put(InterruptExecutor::new(irq)); |
| 135 | executor.start(|spawner| { | 134 | let spawner = executor.start(); |
| 136 | unwrap!(spawner.spawn(run_med())); | 135 | unwrap!(spawner.spawn(run_med())); |
| 137 | }); | ||
| 138 | 136 | ||
| 139 | // Low priority executor: runs in thread mode, using WFE/SEV | 137 | // Low priority executor: runs in thread mode, using WFE/SEV |
| 140 | let executor = EXECUTOR_LOW.put(Executor::new()); | 138 | let executor = EXECUTOR_LOW.put(Executor::new()); |
