4
4
// lint here.
5
5
#![ allow( clippy:: missing_inline_in_public_items) ]
6
6
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
+ }
8
27
9
28
/// A stack you can use as your Process Stack (PSP)
10
29
///
11
30
/// The const-param N is the size **in 32-bit words**
12
31
#[ repr( align( 8 ) , C ) ]
13
32
pub struct Stack < const N : usize > {
14
33
space : UnsafeCell < [ u32 ; N ] > ,
34
+ taken : AtomicBool ,
15
35
}
16
36
17
37
impl < const N : usize > Stack < N > {
@@ -22,17 +42,27 @@ impl<const N: usize> Stack<N> {
22
42
/// ```rust
23
43
/// # use cortex_m::psp::Stack;
24
44
/// static PSP_STACK: Stack::<4096> = Stack::new();
45
+ /// fn example() {
46
+ /// let handle = PSP_STACK.take_handle();
47
+ /// // ...
48
+ /// }
25
49
/// ```
26
50
pub const fn new ( ) -> Stack < N > {
27
51
Stack {
28
52
space : UnsafeCell :: new ( [ 0 ; N ] ) ,
53
+ taken : AtomicBool :: new ( false ) ,
29
54
}
30
55
}
31
56
32
57
/// 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
+
34
64
let start = self . space . get ( ) as * mut u32 ;
35
- unsafe { start . add ( N ) }
65
+ StackHandle ( start , N )
36
66
}
37
67
}
38
68
@@ -44,9 +74,18 @@ impl<const N: usize> core::default::Default for Stack<N> {
44
74
}
45
75
}
46
76
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
48
88
#[ 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) }
52
91
}
0 commit comments