1#![allow(clippy::missing_inline_in_public_items)]
6
7use core::{
8 cell::UnsafeCell,
9 sync::atomic::{AtomicBool, Ordering},
10};
11
12pub struct StackHandle(*mut u32, usize);
14
15impl StackHandle {
16 pub fn top(&mut self) -> *mut u32 {
18 unsafe { self.0.add(self.1) }
20 }
21
22 pub fn bottom(&mut self) -> *mut u32 {
24 self.0
25 }
26}
27
28#[repr(align(8), C)]
32pub struct Stack<const N: usize> {
33 space: UnsafeCell<[u32; N]>,
34 taken: AtomicBool,
35}
36
37impl<const N: usize> Stack<N> {
38 pub const fn new() -> Stack<N> {
51 Stack {
52 space: UnsafeCell::new([0; N]),
53 taken: AtomicBool::new(false),
54 }
55 }
56
57 pub fn take_handle(&self) -> StackHandle {
59 if self.taken.load(Ordering::Acquire) {
60 panic!("Cannot get two handles to one stack!");
61 }
62 self.taken.store(true, Ordering::Release);
63
64 let start = self.space.get() as *mut u32;
65 StackHandle(start, N)
66 }
67}
68
69unsafe impl<const N: usize> Sync for Stack<N> {}
70
71impl<const N: usize> core::default::Default for Stack<N> {
72 fn default() -> Self {
73 Stack::new()
74 }
75}
76
77pub fn switch_to_unprivileged_psp(mut psp_stack: StackHandle, function: extern "C" fn() -> !) -> ! {
83 #[cfg(armv8m_main)]
85 unsafe {
86 crate::register::psplim::write(psp_stack.bottom() as u32);
87 }
88 unsafe {
90 crate::asm::enter_unprivileged_psp(psp_stack.top(), function);
91 }
92}
93
94pub fn switch_to_privileged_psp(mut psp_stack: StackHandle, function: extern "C" fn() -> !) -> ! {
96 #[cfg(armv8m_main)]
98 unsafe {
99 crate::register::psplim::write(psp_stack.bottom() as u32);
100 }
101 unsafe {
103 crate::asm::enter_privileged_psp(psp_stack.top(), function);
104 }
105}