Can We Debug Yet?

So, let's debug! I'm going to explain the different tools and approaches that work for me, using the latest issue I've been debugging as an example: High Frequency Pulse In. I mention "work for me" because you may work differently; feel free to explore different approaches.

To start off, I wrote two CircuitPython scripts: one for PWM output from a Feather M0 Express, and the other for PulseIn detection on an ItsyBitsy M0 Express (board being debugged). This is what my screen will look like through most of the process:

Ladies and Gentlemen, START YOUR [DEBUG] ENGINES!!!

To get the target board running, click the "Start Debugging" icon or press the F5 key.

You will only be able to view information while the board is "paused" (exception: any information output from a Breakpoint will be displayed in "real-time" in the Output window).

If you know the information you're interested in, or want to set a breakpoint based on a memory location, you can use the "Start Debugging and Break" icon or press Alt+F5, set your breakpoint(s), and then "Start Debugging".

Debug Ribbon Icons

  1. Start Debugging (F5): programs the board, and starts running the board.

  2. Start Debugging and Break (Alt+F5): programs the board, starts running the board, but immediately pauses execution.

  3. Attach to Target: establishes connection to the target board, does not program the board, and does not start running the board.

  4. Stop Debugging (Ctrl+Shift+F5): stops any paused or running board.

  5. Break All (Ctrl+F5): pauses a running board at the current memory address.

When you click either Start option, a window will pop up and show progress of each of the 4 steps AS7 takes: Compare, Erase, Program, and Verify. Then the board will start running and/or pause depending on your selection.

You will notice that the board's USB drive ejects and re-connects to Windows. Any connected terminal for REPL will need to be re-connected. If you chose "Start and Break", this will not happen since the board immediately stops and doesn't run the bootloader. 

Also, while the board is paused, REPL activities will obviously not work. However, once the board is running again, the terminal will flush and send any commands that were entered while paused (at least PuTTY does).

Pro Tip: Avoid adding/changing files to/on the board during debugging. When you stop the board (or the board hangs), it is NOT properly ejected from Windows and may corrupt the board's filesystem if changes have occurred.

Getting back to the issue I was debugging, I ran the scripts until the board lockup that was described in the GitHub issue occurred. The first place I started to investigate, was a look at the Call Stack. So, I clicked the "Break All" icon (or Ctrl+F5). Then, opened up the Call Stack window:

As you can see, the callstack (aka backtrace, stacktrace) shows that we're currently in the pulsein_interrupt_handler() function.

Since the High Frequency PulseIn issue was resulting in a "board lockup", it seemed logical that we were getting stuck in a loop somewhere. I decided to set a breakpoint on this function and watch the output a few times.

Now that we have a clue, it's time to get into the weeds...

This guide was first published on May 24, 2018. It was last updated on May 24, 2018. This page (Can We Debug Yet?) was last updated on Sep 11, 2019.