/* Test exception escalation in armv7-m */ #include "armv7m.h" #include "testme.h" static unsigned testseq; #define SEQ() __atomic_add_fetch(&testseq, 1, __ATOMIC_RELAXED) #define CHECK_SEQ(N) testEqI(N, SEQ(), "SEQ " #N) static void hard(void) { int test = SEQ(); switch(test) { case 8: case 11: case 17: testPass("in HardFault"); break; default: testFail("Fail HardFault"); abort(); } } static void svc(void) { int test = SEQ(); switch(test) { case 2: case 14: testPass("in SVC"); break; default: testFail("Fail SVC"); abort(); } } static __attribute__((unused)) void pendsv(void) { int test = SEQ(); switch(test) { case 5: testPass("in PendSV"); break; default: testFail("Fail PendSV"); abort(); } } void main(void) { run_table.hard = hard; run_table.pendsv = pendsv; run_table.svc = svc; testInit(12); out32(SCB(0xd0c), 0x05fa0000 | (PRIGROUP<<8)); CPSIE(if); SEQ(); testDiag("trigger SVC"); SVC(42); testDiag("Back in main"); CHECK_SEQ(3); testDiag("trigger PendSV"); SEQ(); out32((void*)0xe000ed04, 1<<28); testDiag("Back in main"); CHECK_SEQ(6); testDiag("trigger HardFault via SVC escalating to HF due to PRIMASK"); SEQ(); CPSID(i); /* mask prio lower than -1 [0,255] */ SVC(42); testDiag("Back in main"); CHECK_SEQ(9); CPSIE(i); basepri(1); out32(SCB(0xd1c), PRIO(7,0)<<24); /* PRIO SVC */ //out32(SCB(0xd1c), 1<<21); /* PRIO PendSV */ testDiag("trigger HardFault via SVC escalating to HF due to priority"); SEQ(); SVC(42); testDiag("Back in main"); CHECK_SEQ(12); out32(SCB(0xd1c), PRIO(0,0)<<24); /* PRIO SVC */ testDiag("trigger SVC"); SEQ(); SVC(42); testDiag("Back in main"); CHECK_SEQ(15); out32(SCB(0xd1c), PRIO(2,0)<<24); /* PRIO SVC */ basepri(2); testDiag("trigger HardFault via SVC escalating to HF due to BASEPRI"); SEQ(); SVC(42); testDiag("Back in main"); CHECK_SEQ(18); testDiag("Done"); }