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.
Page last edited March 08, 2024
Text editor powered by tinymce.