How to get RP2040 exceptions in the Serial monitor?

I’ve written some dud code and my RP2040 is crashing.

Coming from an ESP32 background, I’m used to getting an exception stack trace in the serial monitor.

Is this possible with Arduino on the RP2040?

If not, whats the easiest way to see whats happening? Do I need additional debugger hardware?

Thanks

[env:pico]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = pico
framework = arduino
board_build.core = earlephilhower
monitor_speed = 9600
upload_protocol = picotool
build_type = debug
build_flags = 
	-DUSE_TINYUSB
	-DPIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS

If your code crashes and ends up in a HardFault handler or in any other ARM Cortex M0+ crash handler, nothing is printed. The function isr_hardfault (in CMSIS complaint terms named Hardfault_Handler()) is just implemented as a function that triggers a breakpoint (bkpt #0), thereby signaling to a possibly connected debug probe that the code has now crashed and halted.

See https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/src/rp2_common/pico_crt0/crt0.S#L29-L170.

The crash /exception output as in ESP32 is a luxury that by default does not exist on the RP2040 and the Arduino-Pico framework. What you’re doing with PIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS is enable the usage of C++ exception constructs, aka try { /* .. */ } catch(std::exception e) { /* ..*/ }. This has nothing to do with printing a crash log.

So the advice that makes the most sense is follow the documentation on how to connect a debug probe to the RP2040. That is surprisingly easy and comfortable: If you have have a second Raspberry Pi Pico or Raspberry Pi Pico 2, you can copy the “DebugProbe” firmware on it as released in

https://github.com/raspberrypi/debugprobe/releases

(e.g. copying debugprobe_on_pico.uf2 to a RP2040’s based Pico’s BOOTSEL USB drive), which will make that Pico act like a CMSIS-DAP debug probe (debug_tool = cmsis-dap in the platformio.ini). Then with just 3 wires (SWDIO, SWCLK, GND) between them, one Pico can debug the other Pico.

That is all again documented.

https://arduino-pico.readthedocs.io/en/latest/platformio.html#debugging

This would then enable you to see how code execution ended up in the crash handler, for example via the call stack:


Another approach is to implement the isr_hardfault() function in a way that does print out information about the crash, by decoding the info from some ARM Cortex core registers and the stack and printing them to the serial. The https://github.com/armink/CmBacktrace project can do that. However, if you use the USB serial with the Pico, that in itself may require USB interrupts to work and send out the data, which definitely won’t trigger if the core has experienced a HardFault interrupt and is stuck in there, so using Serial(USB).println() likely won’t work. It may work however to use the UART based Serial (Serial0) and, of course, connect a separate USB-to-UART converter to connect to that port and read out the data.

Thanks for your mega detailed and helpful response, as usual. 2nd Pi ordered :slight_smile:

Sure! May be a little late, but: A Raspberry Pi Pico with the “Debugprobe” firmware flashed on it will work prefectly fine. Raspberry Pi however also sells that as its own premade debugger tool, in a nice enclosure and with only the connectors for SWD (SWDIO, SWCLK, GND) and UART (TX, RX, GND) sticking out:

https://www.raspberrypi.com/products/debug-probe/

Makes connecting the wires a bit easier. Otherwise of course, equivalent.