Intro

I am using Teensy 4 in one of my projects where I've seemingly hit a wall with debugging. Using printf statements messes up with the timings in the code, and I have no way of inspecting the state of the system at the time when things go wrong. There's no way of pausing the code, changing few variables and resuming the execution. I have tried this approach with some other boards that shipped with on-board debugger, and ended up wondering what would it take to get this to work on Teensy.

I have also tried a software solution to debugging, TeensyDebug, which essentially runs and GDB server directly on Teensy, together with your code. While this does a good job for most of the time, it seems to crash when my program dies, which is when I need it the most.

The only thing I believe could help is having a JTAG debugger to inspect the running code and be able to halt the MCU when a fault occurs.

Debugger?

This brings me to the second problem: I don't have a JTAG debugger. 

The ones I used in the past came as a part of eval kits (Texas Instruments Tiva series) and they will not work with other boards. So I need to get something else. A work colleague of mine recently showed me the blackmagic project, which is an open source debug probe, awesome! As an added bonus, they support tiva's debugger as a platform, so in theory I could reprogram on the eval kits I already have and have a general purpose debugger. Fantastic!

Getting the project to compile and run was a breeze. Now onto teensy.

Teensy 4?

Although I'd like this to work on Teensy 4, I would like to give it a try on Teensy 3 first. Reason for that is that I only have two Teensy 4 boards (one in use), but a lot more Teensy 3.2 boards I can spare, and the process sounds like it might be destructive - at least in the research phase.

Luckily, there's some good discussions around the internet on hacking in a debugger into teensy, that essentially outline the procedure or add extra bits of useful info:

Teensy 3 originally not supported by blackmagic

When starting this project, one of the hurdles was that MK20DX256, chip used in Teensy 3 was not originally supported by the blackmagic debug probe. However, I have since sent a pull request with support for it and it now works with the probe.

Wiring up Teensy 3.2

Teensy 3.2 features a bootloader chip (MKL02). That chip is what allows loading the firmware into Teensy chip using the Teensy loader PC program. It also ensure that no matter how bad you mess up your program, your board will always be programmable. Bootloader chip has access to the main chip (MK20DX256) via SWO interface. Since the board doesn't expose the pins in a convenient header, the only way is to tap into the connection between the bootloader and main chip.

Wiring it is a bit of a process and requires some thin wires and a steady hand. I ended up attaching all of the wires I could onto the via as they are easier to solder, and those that I couldn't directly onto the chip. Final result looks like this:

Pinout is as follows:

JTAG /SWOSignalMK20DX PinLocation Hint
TCK/SWCLKPTA022 (accessible from top of the 2 soldered vias)
TDIPTA123 (accessible from bottom of the 2 soldered vias)
TDO/tSWOPTA224 (8 from the top of the left side of the chip; accessible on chip only)
TMS/SWDIOPTA325 (9 from the top of the left side of the chip; accessible on chip only)
RSTRESET_b34 (exposed via 'R' test pad on the back side)

From what I understood online, both JTAG and SWO interface are usable on Teensy 3.2, so the choice of interface is mostly up to the probe hooked up to it.

In this configuration, bootloader chip will still meddle with the JTAG interface. Luckily. one of the links above reveals that the reset pin of the bootloader is exposed via a test pad at the back of the board, right next to pin 1:

Red circle shows the location of bootloader reset pin, it needs to be pulled to GND for the chip to be inactive and not interfere with JTAG interface. This pad maps to pin 14 on the MKL02, named PTA0 in datasheet. MK20DX256 (main chip) RST pin from the pinout table is shown here as well, in blue circle.

PlatformIO

Since I'm using platformIO for development, I would like to incorporate this debugging support within its ecosystem. PlatformIO already supports 'blackmagic' as debug option in their settings, however, it seems that it doesn't work in combination with Teensy 3.2 (I assume since it was not officially supported). It returns an error on my computer.

But it supports 'custom' debug tool where one can specify all GDB commands needed to get going, and that's what can be used here. A bit of fiddling got me to the following settings:

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:teensy31]
platform = teensy
board = teensy31
framework = arduino
debug_port = COM8
debug_tool = custom
debug_load_mode = always
platform_packages = platformio/toolchain-gccarmnoneeabi@1.90301.200702
debug_init_break = tbreak setup

debug_init_cmds = 
  define pio_reset_run_target
      quit
  end

  target ext $DEBUG_PORT
  mon jtag scan
  attach 1
  $LOAD_CMDS
  $INIT_BREAK

(notice a change in default compiler; This is to avoid using a GDB debugger with an issue described in one of the project logs below). In short, avoid GDB older than version 8.

From there on, I could hit F5 (or select one of platformIO's debug options) and be greeted with a friendly debug screen where I could run my code, pause it, step over/into, inspect registers, watch variables, get stack trace, edit variables when paused, inspect registers, set breakpoints/watchpoints - all the good goodies used when debugging.