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
//! Scheduler.
/// Scheduler.
///
/// # Implementation
/// In addition to the trait the hardware context switch exception must be
/// implemented. The exception must
/// 1. Push the CPU registers to the stack
/// 2. Call `switch_context` from the kernel
/// - in: current task stack pointer in first parameter register (e.g. `r0`)
/// - out: next task stack pointer in return register (e.g. `r0`)
/// 3. Pop CPU register from new stack
///
/// On a ARM Cortex-M4 for example (simplified):
/// ```ignore
/// #[no_mangle]
/// #[unsafe(naked)]
/// extern "C" fn PendSV() {
/// unsafe {
/// asm!(
/// "push {{lr}}",
/// "mrs r0, psp", // get process stack pointer
/// "stmdb r0!, {{r4-r11}}", // push registers to stack A
/// "bl switch_context", // call kernel for context switch
/// "pop {{lr}}",
/// "mov r3, #3",
/// "msr control, r3", // run in unprivileged mode
/// "isb",
/// "ldmia r0!, {{r4-r11}}", // pop registers from stack B
/// "msr psp, r0", // set process stack pointer
/// "bx lr",
/// options(noreturn),
/// )
/// }
/// }
/// ```
///
/// The exception can call `check_stack` to check wheter the there is enough
/// space left to store the registers.
/// - in: stack pointer after stacking
/// - out: 0 - stack would overflow, 1 - enought space left