Debugging#

On-chip debug. A probe on one end, a gdb-server in the middle, gdb on the other end, and the chip stopped under inspection. The operator gains full visibility (registers, memory, peripherals, stack traces) without printf statements that change the timing of the bug. The stack is JTAG or SWD on the wire, OpenOCD or J-Link as the daemon, and gdb (or a gdb front-end) as the user interface.

The stack#

Layer

Component

Wire protocol

JTAG (4-wire) or SWD (2-wire ARM).

Probe

ST-Link, J-Link, BlackMagic Probe, CMSIS-DAP, J-Link Edu; see Programmers.

Server

OpenOCD, JLinkGDBServer, BlackMagic firmware, pyOCD.

Client

arm-none-eabi-gdb, VS Code Cortex-Debug, CLion, Ozone.

Side channels#

Print-style debug output without the cost of an extra UART pin.

Mechanism

Note

Semihosting

printf is intercepted by the debugger and routed to the host stdout. Cheap to enable; slow (each call halts the CPU for the duration).

ITM / SWO

Cortex-M only. A small FIFO on-chip; the CPU writes a byte, SWO trace pin clocks it out to the probe at line rate. Non-intrusive.

RTT (SEGGER)

Ring buffers in RAM polled by the probe; the fastest trace channel available, no extra pin needed beyond SWD. defmt (Rust) uses RTT.

Live watch (Cortex-M)

Probe reads target RAM while the CPU runs; configuration in the IDE.

gdb basics#

Command

Effect

target extended-remote :3333

Attach to an OpenOCD gdb server on the default port.

monitor reset halt

Reset the target and halt at the reset vector.

load

Program the ELF into flash via the probe.

break main

Break at the named symbol.

continue, c

Resume execution.

stepi, si

Single-step at the instruction level.

info registers, i r

Dump CPU registers.

info threads

Show RTOS threads (with proper OpenOCD config).

x/16wx 0x20000000

Examine 16 words of memory at the address.

backtrace, bt

Walk the call stack.

watch *(uint32_t *)0x20001000

Stop when the location’s value changes.

set $sp = 0x20020000

Patch a register; useful for recovering from a fault.

References#