@@ -12,20 +12,40 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
1212 minitest:: fail ( )
1313}
1414
15- static EXCEPTION_FLAG : AtomicBool = AtomicBool :: new ( false ) ;
15+ static PENDSV_FLAG : AtomicBool = AtomicBool :: new ( false ) ;
16+ static SVCALL_FLAG : AtomicBool = AtomicBool :: new ( false ) ;
17+ static WANT_FAULT : AtomicBool = AtomicBool :: new ( false ) ;
1618
1719const STACK_SIZE_WORDS : usize = 1024 ;
1820
1921static STACK : cortex_m:: psp:: Stack < STACK_SIZE_WORDS > = cortex_m:: psp:: Stack :: new ( ) ;
2022
2123#[ cortex_m_rt:: exception]
2224fn PendSV ( ) {
23- EXCEPTION_FLAG . store ( true , Ordering :: SeqCst ) ;
25+ minitest:: log!( "Hit PendSV!" ) ;
26+ PENDSV_FLAG . store ( true , Ordering :: SeqCst ) ;
27+ }
28+
29+ #[ cortex_m_rt:: exception]
30+ fn SVCall ( ) {
31+ minitest:: log!( "Handling SWI :)" ) ;
32+ SVCALL_FLAG . store ( true , Ordering :: SeqCst ) ;
33+ }
34+
35+ #[ cortex_m_rt:: exception]
36+ unsafe fn HardFault ( frame : & cortex_m_rt:: ExceptionFrame ) -> ! {
37+ minitest:: log!( "{:?}" , frame) ;
38+ if WANT_FAULT . load ( Ordering :: Relaxed ) {
39+ minitest:: log!( "Trapped breakpoint OK!" ) ;
40+ minitest:: exit ( )
41+ } else {
42+ minitest:: fail ( )
43+ }
2444}
2545
2646#[ minitest:: tests]
2747mod tests {
28- use crate :: { EXCEPTION_FLAG , Ordering } ;
48+ use crate :: { Ordering , PENDSV_FLAG } ;
2949 use minitest:: log;
3050
3151 #[ init]
@@ -67,28 +87,28 @@ mod tests {
6787
6888 #[ test]
6989 fn critical_section_nesting ( ) {
70- EXCEPTION_FLAG . store ( false , Ordering :: SeqCst ) ;
90+ PENDSV_FLAG . store ( false , Ordering :: SeqCst ) ;
7191 critical_section:: with ( |_| {
7292 critical_section:: with ( |_| {
7393 cortex_m:: peripheral:: SCB :: set_pendsv ( ) ;
74- assert ! ( !EXCEPTION_FLAG . load( Ordering :: SeqCst ) ) ;
94+ assert ! ( !PENDSV_FLAG . load( Ordering :: SeqCst ) ) ;
7595 } ) ;
76- assert ! ( !EXCEPTION_FLAG . load( Ordering :: SeqCst ) ) ;
96+ assert ! ( !PENDSV_FLAG . load( Ordering :: SeqCst ) ) ;
7797 } ) ;
78- assert ! ( EXCEPTION_FLAG . load( Ordering :: SeqCst ) ) ;
98+ assert ! ( PENDSV_FLAG . load( Ordering :: SeqCst ) ) ;
7999 }
80100
81101 #[ test]
82102 fn interrupt_free_nesting ( ) {
83- EXCEPTION_FLAG . store ( false , Ordering :: SeqCst ) ;
103+ PENDSV_FLAG . store ( false , Ordering :: SeqCst ) ;
84104 cortex_m:: interrupt:: free ( |_| {
85105 cortex_m:: interrupt:: free ( |_| {
86106 cortex_m:: peripheral:: SCB :: set_pendsv ( ) ;
87- assert ! ( !EXCEPTION_FLAG . load( Ordering :: SeqCst ) ) ;
107+ assert ! ( !PENDSV_FLAG . load( Ordering :: SeqCst ) ) ;
88108 } ) ;
89- assert ! ( !EXCEPTION_FLAG . load( Ordering :: SeqCst ) ) ;
109+ assert ! ( !PENDSV_FLAG . load( Ordering :: SeqCst ) ) ;
90110 } ) ;
91- assert ! ( EXCEPTION_FLAG . load( Ordering :: SeqCst ) ) ;
111+ assert ! ( PENDSV_FLAG . load( Ordering :: SeqCst ) ) ;
92112 }
93113
94114 #[ test]
@@ -99,4 +119,61 @@ mod tests {
99119 let delta = unsafe { top. offset_from ( bottom) } ;
100120 assert_eq ! ( delta as usize , super :: STACK_SIZE_WORDS ) ;
101121 }
122+
123+ #[ test]
124+ fn check_asm ( ) {
125+ // Data Memory Barrier - harmless
126+ cortex_m:: asm:: dmb ( ) ;
127+ // Data Sync Barrier - harmless
128+ cortex_m:: asm:: dsb ( ) ;
129+ // Instruction Sync Barrier - harmless
130+ cortex_m:: asm:: isb ( ) ;
131+ // A NOP loop - harmless
132+ cortex_m:: asm:: delay ( 100 ) ;
133+ // A single NOP - harmless
134+ cortex_m:: asm:: nop ( ) ;
135+ // Set the event flag
136+ cortex_m:: asm:: sev ( ) ;
137+ // Wait for Event (will not block - flag is set)
138+ cortex_m:: asm:: wfe ( ) ;
139+ // Pend an interrupt, the wait for it
140+ cortex_m:: peripheral:: SCB :: set_pendsv ( ) ;
141+ cortex_m:: interrupt:: free ( |_| {
142+ cortex_m:: peripheral:: SCB :: set_pendsv ( ) ;
143+ // wfi will turn interrupts back on
144+ cortex_m:: asm:: wfi ( ) ;
145+ } ) ;
146+ // Print to the debug console with a semihosting syscall
147+ let msg = c"This is a test\n " ;
148+ const SYS_WRITE0 : u32 = 0x04 ;
149+ unsafe {
150+ cortex_m:: asm:: semihosting_syscall ( SYS_WRITE0 , msg. as_ptr ( ) as usize as u32 ) ;
151+ }
152+ }
153+
154+ // this test must be last!
155+ #[ test]
156+ fn run_psp ( ) {
157+ static STACK : cortex_m:: psp:: Stack < 4096 > = cortex_m:: psp:: Stack :: new ( ) ;
158+ minitest:: log!( "Switching to PSP..." ) ;
159+ cortex_m:: psp:: switch_to_unprivileged_psp ( STACK . take_handle ( ) , crate :: user_fn) ;
160+ }
161+ }
162+
163+ /// This code runs on the Process Stack Pointer (i.e. "User mode")
164+ extern "C" fn user_fn ( ) -> ! {
165+ // should not be set
166+ assert ! ( !SVCALL_FLAG . load( Ordering :: SeqCst ) ) ;
167+ // this should fire the SVCall handler
168+ unsafe {
169+ core:: arch:: asm!( "swi 0x00" ) ;
170+ }
171+ // check we hit the SVCall handler
172+ assert ! ( SVCALL_FLAG . load( Ordering :: SeqCst ) ) ;
173+ // now test breakpoints, and exit the tests at the same time
174+ // (bkpt will trip the HardFault handler)
175+ crate :: WANT_FAULT . store ( true , Ordering :: Relaxed ) ;
176+ loop {
177+ cortex_m:: asm:: bkpt ( ) ;
178+ }
102179}
0 commit comments