aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/arch/cortex_m.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-executor/src/arch/cortex_m.rs')
-rw-r--r--embassy-executor/src/arch/cortex_m.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs
new file mode 100644
index 000000000..d6e758dfb
--- /dev/null
+++ b/embassy-executor/src/arch/cortex_m.rs
@@ -0,0 +1,59 @@
1use core::arch::asm;
2use core::marker::PhantomData;
3use core::ptr;
4
5use super::{raw, Spawner};
6
7/// Thread mode executor, using WFE/SEV.
8///
9/// This is the simplest and most common kind of executor. It runs on
10/// thread mode (at the lowest priority level), and uses the `WFE` ARM instruction
11/// to sleep when it has no more work to do. When a task is woken, a `SEV` instruction
12/// is executed, to make the `WFE` exit from sleep and poll the task.
13///
14/// This executor allows for ultra low power consumption for chips where `WFE`
15/// triggers low-power sleep without extra steps. If your chip requires extra steps,
16/// you may use [`raw::Executor`] directly to program custom behavior.
17pub struct Executor {
18 inner: raw::Executor,
19 not_send: PhantomData<*mut ()>,
20}
21
22impl Executor {
23 /// Create a new Executor.
24 pub fn new() -> Self {
25 Self {
26 inner: raw::Executor::new(|_| unsafe { asm!("sev") }, ptr::null_mut()),
27 not_send: PhantomData,
28 }
29 }
30
31 /// Run the executor.
32 ///
33 /// The `init` closure is called with a [`Spawner`] that spawns tasks on
34 /// this executor. Use it to spawn the initial task(s). After `init` returns,
35 /// the executor starts running the tasks.
36 ///
37 /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
38 /// for example by passing it as an argument to the initial tasks.
39 ///
40 /// This function requires `&'static mut self`. This means you have to store the
41 /// Executor instance in a place where it'll live forever and grants you mutable
42 /// access. There's a few ways to do this:
43 ///
44 /// - a [Forever](crate::util::Forever) (safe)
45 /// - a `static mut` (unsafe)
46 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
47 ///
48 /// This function never returns.
49 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
50 init(self.inner.spawner());
51
52 loop {
53 unsafe {
54 self.inner.poll();
55 asm!("wfe");
56 };
57 }
58 }
59}