1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! Thread-mode executor, idling in `wfe` and woken by `sev`.
//!
//! `embassy-executor`'s scheduler is portable; what it needs per platform
//! is two things — a `__pender` that makes an idle core look at the run
//! queue again, and an idle instruction to spend the time in between.
//! This module supplies both, identically for AArch32 and AArch64.
//!
//! # Why not `embassy-executor`'s own backend
//!
//! `embassy-executor` has a `platform-cortex-ar` feature whose executor is
//! `sev` to pend and `wfe` to idle — exactly the sequence below, which is
//! good evidence this is the blessed approach for the architecture rather
//! than an invention here. It is AArch32 only, though (it depends on
//! `aarch32-cpu`), and there is no AArch64 backend, which would leave the
//! 64-bit build on `platform-spin`: a busy-loop that never idles the CPU
//! at all.
//!
//! Two executors with two different idle behaviors, in a crate whose point
//! is that both word sizes behave the same, is a worse trade than the
//! sixty lines here. `embassy_executor::raw` is public precisely so that a
//! HAL can do this.
//!
//! # Using it
//!
//! The executor has to outlive `run`, which is why it takes
//! `&'static mut self`. `static_cell` is the usual way to get one safely;
//! a `fn kmain() -> !` that never returns can also transmute a local's
//! lifetime, which is what `#[embassy_executor::main]` expands to.
//!
//! That attribute works here, in the form
//! `#[embassy_executor::main(executor = "rpi_hal_embassy::Executor")]` —
//! with no `platform-*` feature selected it resolves to the macro's
//! architecture-agnostic variant, which takes the executor path as an
//! argument. It also emits a plain `fn main`, though, and `rpi-hal`'s boot
//! code calls `kmain`, so it needs an `entry` attribute macro that
//! `rpi-hal` does not currently provide. Until then, call
//! [`Executor::run`](crate::executor::Executor::run) from `kmain`
//! directly — which is all the macro does anyway.
use PhantomData;
use ;
/// Wakes a core that may be sitting in `wfe`.
///
/// `embassy-executor` calls this after putting a task on the run queue.
/// The context pointer distinguishes executors when there is more than
/// one; with a single thread-mode executor there is nothing to
/// distinguish, so it is ignored.
/// Thread-mode executor: runs tasks on the main context, and idles the
/// core in `wfe` when none are ready.
///
/// `wfe` parks the core until an event or an interrupt arrives, so an
/// idle program draws no more power than a `wfi` loop — unlike a spinning
/// executor. Interrupts wake it regardless of the event register, which
/// is what lets the timer interrupt drive `embassy-time` deadlines.
///
/// There is no lost-wake-up race between polling and sleeping. `sev` sets
/// a sticky per-core event register, so a wake-up that lands in the window
/// after the last `poll` and before the `wfe` makes that `wfe` return
/// immediately rather than sleeping through it.
// `Default` is not offered alongside `new`: an `Executor` is only usable
// through `&'static mut`, so a value produced by `Default::default()` in
// an expression position could never be run, and offering it would suggest
// otherwise.