44// lint here.
55#![ allow( clippy:: missing_inline_in_public_items) ]
66
7- use core:: cell:: UnsafeCell ;
7+ use core:: {
8+ cell:: UnsafeCell ,
9+ sync:: atomic:: { AtomicBool , Ordering } ,
10+ } ;
11+
12+ /// Represents access to a [`Stack`]
13+ pub struct StackHandle ( * mut u32 , usize ) ;
14+
15+ impl StackHandle {
16+ /// Get the pointer to the top of the stack
17+ pub const fn top ( & mut self ) -> * mut u32 {
18+ // SAFETY: The stack was this big when we constructed the handle
19+ unsafe { self . 0 . add ( self . 1 ) }
20+ }
21+
22+ /// Get the pointer to the top of the stack
23+ pub const fn bottom ( & mut self ) -> * mut u32 {
24+ self . 0
25+ }
26+ }
827
928/// A stack you can use as your Process Stack (PSP)
1029///
1130/// The const-param N is the size **in 32-bit words**
1231#[ repr( align( 8 ) , C ) ]
1332pub struct Stack < const N : usize > {
1433 space : UnsafeCell < [ u32 ; N ] > ,
34+ taken : AtomicBool ,
1535}
1636
1737impl < const N : usize > Stack < N > {
@@ -22,17 +42,27 @@ impl<const N: usize> Stack<N> {
2242 /// ```rust
2343 /// # use cortex_m::psp::Stack;
2444 /// static PSP_STACK: Stack::<4096> = Stack::new();
45+ /// fn example() {
46+ /// let handle = PSP_STACK.take_handle();
47+ /// // ...
48+ /// }
2549 /// ```
2650 pub const fn new ( ) -> Stack < N > {
2751 Stack {
2852 space : UnsafeCell :: new ( [ 0 ; N ] ) ,
53+ taken : AtomicBool :: new ( false ) ,
2954 }
3055 }
3156
3257 /// Return the top of the stack
33- pub fn get_top ( & self ) -> * mut u32 {
58+ 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+
3464 let start = self . space . get ( ) as * mut u32 ;
35- unsafe { start . add ( N ) }
65+ StackHandle ( start , N )
3666 }
3767}
3868
@@ -44,9 +74,18 @@ impl<const N: usize> core::default::Default for Stack<N> {
4474 }
4575}
4676
47- /// Switch to running on the PSP
77+ /// Switch to unprivileged mode running on the Process Stack Pointer (PSP)
78+ ///
79+ /// In Unprivileged Mode, code can no longer perform privileged operations,
80+ /// such as disabling interrupts.
81+ ///
82+ #[ cfg( cortex_m) ]
83+ pub fn switch_to_unprivileged_psp ( mut psp_stack : StackHandle , function : extern "C" fn ( ) -> !) -> ! {
84+ unsafe { crate :: asm:: enter_unprivileged_psp ( psp_stack. top ( ) , function) }
85+ }
86+
87+ /// Switch to running on the Process Stack Pointer (PSP), but remain in privileged mode
4888#[ cfg( cortex_m) ]
49- pub fn switch_to_psp < const N : usize > ( psp_stack : & Stack < N > , function : extern "C" fn ( ) -> !) -> ! {
50- let stack_top = psp_stack. get_top ( ) ;
51- unsafe { crate :: asm:: enter_unprivileged ( stack_top, function) }
89+ pub fn switch_to_privileged_psp ( mut psp_stack : StackHandle , function : extern "C" fn ( ) -> !) -> ! {
90+ unsafe { crate :: asm:: enter_privileged_psp ( psp_stack. top ( ) , function) }
5291}
0 commit comments