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.
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.
Text editor powered by tinymce.