bern_arch/scheduler.rs
1//! Scheduler.
2
3/// Scheduler.
4///
5/// # Implementation
6/// In addition to the trait the hardware context switch exception must be
7/// implemented. The exception must
8/// 1. Push the CPU registers to the stack
9/// 2. Call `switch_context` from the kernel
10/// - in: current task stack pointer in first parameter register (e.g. `r0`)
11/// - out: next task stack pointer in return register (e.g. `r0`)
12/// 3. Pop CPU register from new stack
13///
14/// On a ARM Cortex-M4 for example (simplified):
15/// ```ignore
16/// #[no_mangle]
17/// #[unsafe(naked)]
18/// extern "C" fn PendSV() {
19/// unsafe {
20/// asm!(
21/// "push {{lr}}",
22/// "mrs r0, psp", // get process stack pointer
23/// "stmdb r0!, {{r4-r11}}", // push registers to stack A
24/// "bl switch_context", // call kernel for context switch
25/// "pop {{lr}}",
26/// "mov r3, #3",
27/// "msr control, r3", // run in unprivileged mode
28/// "isb",
29/// "ldmia r0!, {{r4-r11}}", // pop registers from stack B
30/// "msr psp, r0", // set process stack pointer
31/// "bx lr",
32/// options(noreturn),
33/// )
34/// }
35/// }
36/// ```
37///
38/// The exception can call `check_stack` to check wheter the there is enough
39/// space left to store the registers.
40/// - in: stack pointer after stacking
41/// - out: 0 - stack would overflow, 1 - enought space left
42pub trait IScheduler {
43 /// Init the stack of task.
44 ///
45 /// # Safety
46 /// The stack must be large enough for the initial stack frame.
47 unsafe fn init_task_stack(
48 stack_ptr: *mut usize,
49 entry: *const usize,
50 arg: *const usize,
51 exit: *const usize,
52 ) -> *mut usize;
53 /// Start the first task.
54 fn start_first_task(stack_ptr: *const usize) -> ();
55 /// Trigger context switch exception.
56 fn trigger_context_switch();
57}