aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy/src/executor/arch/cortex_m.rs20
-rw-r--r--examples/nrf/src/bin/multiprio.rs10
-rw-r--r--examples/stm32f3/src/bin/multiprio.rs10
-rw-r--r--examples/stm32f4/src/bin/multiprio.rs10
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 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2use core::ptr; 2use core::ptr;
3 3
4use super::{raw, Spawner}; 4use super::{raw, SendSpawner, Spawner};
5use crate::interrupt::{Interrupt, InterruptExt}; 5use 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());