monitor cortex_m vector_catch all
Tuesday, August 11th, 2026
Occasionally you come across a command or technique that is not only amazingly useful but also something you wish you had known about years ago. This has recently happened to me. The command:
monitor cortex_m vector_catch all
Scenario
I am currently working on rebase a code base from a legacy version of NuttX to a more recent version. This involves consuming several years of upstream changes to the NuttX code base as well as bringing in our additions to the NuttX and other code.
This task presents us with a number of challenges as the several years is over 7 years of upstream changes.
The latest piece of code being worked on related to the dynamic loading of shared libraries. This involved using adopting the latest way of doing this as it had changed, not just the method but simple things like file locations, build scripts and so on. With these changes completed it was time to deploy the code to a board and run the unit tests.
This is where the problems started. The board would just reset part way through the test with no diagnostics. Time to break out the ST-Link (this code is running on a STM32F7) and find out what is happening.
The most obvious thing to do here is to breakpoint __assert and see what this tells us. This becomes a little difficult as this is a protected build and we lose some key backtrace information. There are ways to obtain the actual traceback but this can be difficult.
The Solution: monitor cortex_m vector_catch all
This command passes the vector_catch all command over to OpenOCD (in this caase). OpenOCD then configures the Cortex M series microcontroller to halt execution of the processor before the vector handler is executed. The all parameter informs OpenOCD to halt on all exceptions. Executing the command results in the following output:
hard_err: catch
int_err: catch
bus_err: catch
state_err: catch
chk_err: catch
nocp_err: catch
mm_err: catch
reset: catch
Presumably we could target specific vectors with command such as monitor cortex_m vector_catch mm. An experiment for another day.
Running the application on the board and then triggering the unit test resulted in the following output from the debugger:
121 .type exception_common, function
122 #endif
123 exception_common:
124 .cfi_sections .debug_frame
125 .cfi_startproc
126 mrs r0, ipsr /* R0=exception number */
127 mrs r12, control /* R12=control */
128
129 /* Complete the context save */
130
─── Stack ───
[0] from 0x08163d62 in exception_common+0 at armv7-m/arm_exception.S:126
[1] from 0xffffffe9
[2] from 0x0008a4a0
[3] from 0x080e263c in tensorflow_tests_hello_world+108 at tests/tensorflow_tests.c:213
[4] from 0x080e2544 in hcom_developer_tests_userspace_dispatcher+22 at tests/developer_tests.c:392
[5] from 0x080e2544 in hcom_developer_tests_developer+196 at tests/developer_tests.c:471
—- Rest of stack removed —-
Exactly the output desired, the debugger has halted with the original stack intact and we can see the error is happening on line 213 of the tensorflow_tests.c file.
Conclusion
This is a command I wish I had known about many years ago as it would have saved a fair amount of time tracing back through the call stacks to locate the exact location of an exception, memory access error etc.