Before we can get into the nitty gritty of debugging we need to first get everything running.

GDB Server

First, we'll get the link between our debug hardware and our computer running. Its called the GDB Server.

OpenOCD + Arduino Zero

First, we need to get OpenOCD going to bridge from our computer to the hardware debugger. Its easy with the Arduino Zero.

Connect a USB cable from your computer to the DEBUG USB connector on the Arduino Zero. Now, make sure you have the Arduino Zero config file for OpenOCD available here.

Now run OpenOCD in a terminal. It will stay running while we debug.

openocd -f arduino_zero.cfg

You should see that it found the Arduino Zero with output similar to this:

Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 02.01.0157
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 500 kHz
Info : SWD IDCODE 0x0bc11477
Info : at91samd21g18.cpu: hardware has 4 breakpoints, 2 watchpoints

JLink + Metro M0 Express

Unlike the Arduino Zero, the Metro M0 Express doesn't have a builtin debug -> USB adapter. To do this conversion you'll need a debugger. Segger's JLinks are the gold standard for debuggers and support many many microcontrollers. (EDU versions are much cheaper for non-commercial use.) To connect the normal sized JLink debugger you'll need an adapter from a JTAG cable to a SWD cable along with a SWD cable.

The SEGGER J-Link BASE is identical to the cheaper J-Link EDU model except for the terms of...
$399.95
In Stock
This adapter board is designed for adapting a 'classic' 2x10 (0.1"/2.54mm pitch) JTAG cable to a slimmer 2x5 (0.05"/1.27mm pitch) SWD Cable.  It's helpful...
$4.95
In Stock
These little cables are handy when programming or debugging a tiny board that uses 10-pin 1.27mm (0.05") pitch SWD programming connectors. We see these connectors often on ARM...
$2.95
In Stock

Now connect the JLink to the Metro express through the adapter board and SWD cable. Once connected, run the JLink GDB server in a terminal.

JLinkGDBServer -if SWD -device ATSAMD21G18

Most boards will be the ATSAMD21G18 except the Trinket M0 and Gemma M0 which are ATSAMD21E18 (meaning they are physically smaller).

After connecting you should see something like:

SEGGER J-Link GDB Server V6.12e Command Line Version

JLinkARM.dll V6.12e (DLL compiled Jan  6 2017 17:21:41)

-----GDB Server start settings-----
GDBInit file:                  none
GDB Server Listening port:     2331
SWO raw output listening port: 2332
Terminal I/O port:             2333
Accept remote connection:      yes
Generate logfile:              off
Verify download:               off
Init regs on start:            off
Silent mode:                   off
Single run mode:               off
Target connection timeout:     0 ms
------J-Link related settings------
J-Link Host interface:         USB
J-Link script:                 none
J-Link settings file:          none
------Target related settings------
Target device:                 ATSAMD21G18
Target interface:              SWD
Target interface speed:        1000kHz
Target endian:                 little

Connecting to J-Link...
J-Link is connected.
Firmware: J-Link V10 compiled Dec 23 2016 12:00:00
Hardware: V10.10
S/N: 50103114
Feature(s): GDB
Checking target voltage...
Target voltage: 3.29 V
Listening on TCP/IP port 2331
Connecting to target...Connected to target

GDB

GDB is similarly straightforward. The most important thing is that your current directory is near your binary. With Adafruit's CircuitPython I like to be in the atmel-samd directory where our binary is build-arduino_zero/firmware.elf. (If you are following along with CircuitPython you can compile it with make BOARD=arduino_zero DEBUG=1.)

arm-none-eabi-gdb-py build-arduino_zero/firmware.elf

Now you should see some version information and a prompt that start with (gdb). All examples that start with (gdb) should be run in gdb and you do not need to type (gdb) in.

OpenOCD

Now we need to tell GDB to debug through OpenOCD rather than on this computer.

(gdb) target extended-remote :3333

JLink

Now to need to tell GDB to debug through JLink rather than on this computer.

(gdb) target extended-remote :2331

Loading, Resetting and Running

Loading, resetting and running the currently running program on the microcontroller is critical to the debugging process. To load a new version of the program after you've compiled outside of gdb do:

(gdb) load
Loading section .text, size 0x2bb84 lma 0x0
Loading section .data, size 0x5a4 lma 0x2bb84
Start address 0x0, load size 180520
Transfer rate: 5 KB/sec, 13886 bytes/write.

OpenOCD

To reset the microcontroller to the start of the new program you need to ask OpenOCD via monitor to reset to the initialization state.

(gdb) monitor reset init
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x00018dd0 msp: 0x20008000

JLink

To reset the microcontroller to the start of the new program you need to ask JLink via monitor to reset to the initialization state.

(gdb) monitor reset
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x00018dd0 msp: 0x20008000

Running

Finally, to make the program run type continue or c and hit enter. The prompt won't return until your program finishes, hits a breakpoint or you type ctrl-c.

This guide was first published on Oct 12, 2016. It was last updated on Oct 12, 2016.

This page (Setup) was last updated on Apr 20, 2021.

Text editor powered by tinymce.