Cornell University ECE4760
Debugging

Pi Pico RP2040/2350

Datasheet Errata

rp2040 data sheet Appendix B

rp2350 data sheet Appendix E

Build Bugs

  1. Cmake configuration.
    Cmake can go wrong in a number of ways while configuring the project, with very limited error messages in the VSCode window.
    You can invoke cmake at the powershell command line by changing directory to your current build directory then issuing the command: 
    cmake "NMake Makefiles" ..
    (
    note the quotation marks and two periods at the end; both are part of the command)
    An example shows that on my system, the absolute path to cmake was necessary. It also shows
    that you can read out which board and cpu the systems thinks you want, and will issue error messages
    that make sense if soemthing goes wrong.
  2. Occasionally the build process will not correctly pick up the board type (e.g. pico, pico2), even though
    you see the correct board type in the pico extension panel in VSCode.

Protothread Bugs

If your program just sits there and does nothing:
-- Did you write each thread to include at least one YIELD (or YIELD_UNTIL, or YIELD_TIME_msec) in the while(1) loop? Remember that the UART input spawned
thread yields betwen eacy typed character. Humans are sooo slow.
-- Did you schedule the threads?
-- Does the board have correct Vdd?

If your program reboots about a few times/sec:
-- Did you exit from any scheduled thread? This blows out the stack.
-- Did you turn on any interrupt source and fail to write an ISR for that source?
-- Did you divide by zero? A divide by zero is an untrapped exception.
-- Did you write to a non-existant memory location, perhaps by using a negative (or very large) array index.
A write to a non-existant memory location is an untrapped exception.

If your thread state variables seem to change on their own:
--- Did you define any automatic local variable?
Local variables in a thread should be static.
-- Are your global arrays big enough the clobber the stack in high memory?
You should be able to use over 400 kbytes.

Runtime Exceptions -- Hardfaults
From the datasheet:
The bootrom implements the NMI and HardFault vectors with an rcp_panic instruction. This instruction
unconditionally stalls the coprocessor port. This prevents the processor from retiring any more instructions until either
a debugger connects to reset the processors, or the processors reset through some other mechanism (such as the
system watchdog timer). The processor quickly reaches a quiescent state that reduces vulnerability to further fault
injection (deliberate or otherwise).
From the Memfault blog:
A hardfault is the catchall term for assorted system failures that can take place such as:
-- accesses to bad memory (bad address or protected)
-- divide-by-zero errors
-- illegal unaligned accesses.
It’s the only handler for faults on the ARMv6-M architecture but for ARMv7-M & ARMv8-M, finer granularity fault handlers can be enabled for specific error classes (i.e MemManage, BusFault, UsageFault).


  1. You can find out more about openOCD here.

Copyright Cornell University April 30, 2025