# # For each named Cortex-M3 vector_catch flag VECTOR ... # bus_err state_err # chk_err nocp_err # mm_err reset # # BUT NYET hard_err, int_err (their test cases don't yet work) ... # # Do the following: # # - Test #1: verify that OpenOCD ignores exceptions by default # + l_VECTOR (loads testcase to RAM) # + fault triggers loop-to-self exception "handler" # + "halt" # + observe fault "handling" -- loop-to-self from load_and_run (below) # # - Test #2: verify that "vector_catch" makes OpenOCD stops ignoring them # + cortex_m3 vector_catch none # + cortex_m3 vector_catch VECTOR # + l_VECTOR (loads testcase to RAM) # + fault triggers vector catch hardware # + observe OpenOCD entering debug state with no assistance # # NOTE "reset" includes the NVIC, so that test case gets its reset vector # from the flash, not from the vector table set up here. Which means that # for that vector_catch option, the Test #1 (above) "observe" step won't # use the SRAM address. # # we can fully automate test #2 proc vector_test {tag} { halt # REVISIT -- annoying, we'd like to scrap vector_catch output cortex_m3 vector_catch none cortex_m3 vector_catch $tag eval "l_$tag" } # # Load and start one vector_catch test case. # # name -- tag for the vector_catch flag being tested # halfwords -- array of instructions (some wide, some narrow) # n_instr -- how many instructions are in $halfwords # proc load_and_run { name halfwords n_instr } { reset halt # Load code at beginning of SRAM. echo "# code to trigger $name vector" set addr 0x20000000 # ocd_array2mem should be faster, though we'd need to # compute the resulting $addr ourselves foreach opcode $halfwords { mwh $addr $opcode incr addr 2 } # create default loop-to-self at $addr ... it serves as # (a) "main loop" on error # (b) handler for all exceptions that get triggered mwh $addr 0xe7fe # disassemble, as sanity check and what's-happening trace cortex_m3 disassemble 0x20000000 [expr 1 + $n_instr ] # Assume that block of code is at most 16 halfwords long. # Create a basic table of loop-to-self exception handlers. mww 0x20000020 $addr 16 # Store its address in VTOR mww 0xe000ed08 0x20000020 # Use SHCSR to ensure nothing escalates to a HardFault mww 0xe000ed24 0x00070000 # now start, trigering the $name vector catch logic resume 0x20000000 } #proc l_hard_err {} { # IMPLEMENT ME # FORCED -- escalate something to HardFault #} #proc l_int_err {} { # IMPLEMENT ME # STKERR -- exception stack BusFault #} # BusFault, escalates to HardFault proc l_bus_err {} { # PRECISERR -- assume less than 512 MBytes of SRAM load_and_run bus_err { 0xf06f 0x4040 0x7800 } 2 } # UsageFault, escalates to HardFault proc l_state_err {} { # UNDEFINSTR -- issue architecturally undefined instruction load_and_run state_err { 0xde00 } 1 } # UsageFault, escalates to HardFault proc l_chk_err {} { # UNALIGNED -- LDM through unaligned pointer load_and_run chk_err { 0xf04f 0x0001 0xe890 0x0006 } 2 } # UsageFault, escalates to HardFault proc l_nocp_err {} { # NOCP -- issue cp14 DCC instruction load_and_run nocp_err { 0xee10 0x0e15 } 1 } # MemManage, escalates to HardFault proc l_mm_err {} { # IACCVIOL -- instruction fetch from an XN region load_and_run mm_err { 0xf04f 0x4060 0x4687 } 2 } proc l_reset {} { # issue SYSRESETREQ via AIRCR load_and_run reset { 0xf04f 0x0104 0xf2c0 0x51fa 0xf44f 0x406d 0xf100 0x000c 0xf2ce 0x0000 0x6001 } 6 }