Skip to content

Commit d405099

Browse files
committed
Extend the test suite to check more of our assembly code
1 parent ecf51f0 commit d405099

1 file changed

Lines changed: 88 additions & 11 deletions

File tree

testsuite/src/main.rs

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1719
const STACK_SIZE_WORDS: usize = 1024;
1820

1921
static STACK: cortex_m::psp::Stack<STACK_SIZE_WORDS> = cortex_m::psp::Stack::new();
2022

2123
#[cortex_m_rt::exception]
2224
fn 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]
2747
mod 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

Comments
 (0)