GDB debugging¶
Live debugging, flashing, and tracing on Cortex-M targets over ARM GDB.
This comes from the Cortex M Debugger plugin. Install it from the Marketplace, or from a session:
See Plugins.
What it covers¶
| Cores | Cortex-M0, M0+, M3, M4, M7, M23, M33, and beyond |
| Vendors | STM32, NXP, Nordic, Microchip SAM, TI, Silicon Labs, and others |
| Probes and servers | ST-LINK, J-Link, CMSIS-DAP, OpenOCD, pyOCD, vendor tools |
| Host | Windows, macOS, Linux |
| Protocol | ARM GDB with the GDB MI interface |
Nothing is hardcoded to a chip, board, probe, or OS. Commands either detect their target from the environment or read it from your target profile.
Set up a target profile¶
Fill this in once per project. It holds the parameters every other operation treats as inputs: core type, memory map, GDB port, clock speed, pinout, and which probe backend you use.
Set up a target profile for this board. It is an STM32G4 on ST-LINK.
Read the memory map from the linker script.
Without a profile the agent has to ask for a port or a flash base address every time, or guess at one.
Toolchain resolution¶
Before anything runs, the plugin resolves arm-none-eabi-gdb and your backend tools for the current OS. It checks PATH, then per-OS install locations, and caches the result for 24 hours.
It never hardcodes an absolute path, because install locations differ by OS, IDE version, and user.
Attach and inspect¶
Set a breakpoint at main.c:142, continue, and when it hits show me r0
through r3 and the call stack.
Available once attached: breakpoints and watchpoints, step, next, step-instruction, finish, and reads of registers, memory, locals, globals, stack frames, threads, and disassembly.
Register reads are batched rather than looped one per round trip, which is what makes an interactive session usable.
Diagnose a fault¶
The plugin reads the six contiguous SCB fault registers in a single batched read and decodes CFSR, HFSR, BFAR, and MMFAR, covering HardFault, BusFault, MemManage, stack overflow, and TrustZone secure faults.
Flash and iterate¶
For tight edit-build-test loops there is a strategy ladder rather than a full flash every time: SRAM execute, GDB load, differential update, dual-bank live update, hash-skip when nothing changed, and an auto-watcher that reflashes on rebuild. The agent picks the cheapest strategy that is still correct for what changed.
This flash cycle is too slow. Use the fastest strategy that is still
correct for a change confined to one .c file.
Trace¶
SWO and ITM give printf-style output without stopping the target.
SWO pin, baud, and CPU frequency come from the target profile.
Advanced¶
DWT profiling, conditional and hardware breakpoints with ignore counts, a variable logger, core-dump capture on crash, a peripheral monitor, and an interactive debug REPL.
Register-level peripheral inspection covers GPIO, USART, SPI, I2C, Timer, RCC, NVIC, MPU, and DWT.
Core differences that bite¶
Check the core before assuming a debug feature exists. M0 and M0+ have no DWT comparators, so hardware watchpoints are unavailable, no fault status registers, so faults escalate straight to HardFault_Handler with no further classification, and no ITM or SWO, so trace does not apply.
The plugin confirms the core at runtime from CPUID at 0xE000ED00 rather than inferring it from the part number.
Server safety¶
Starting or stopping a GDB server is deliberately not automatic. It needs your explicit confirmation, and the plugin tracks which server process it started.
It will not kill a server it did not launch. On a shared bench that is the difference between restarting your own session and killing a colleague's.
Checking whether a server is already listening is a read-only TCP probe and runs without confirmation.
Sessions are reused¶
The plugin will not restart GDB or reconnect a live session unless that session is proven dead. A debug session holds state that is expensive to rebuild, so continuity is the default.
Troubleshoot¶
- Connection refused, or an attach that times out. Check whether a server is already listening before assuming the port in your profile is wrong.
- Command not found, or GDB not recognised. Resolve the toolchain rather than hardcoding a path.
- A watchpoint silently does nothing. The core has no DWT comparators. Confirm the core first.
- Fault registers read as garbage. Same cause. M0 and M0+ have none.
- The build blocks debugging. Compile and link flags, linker script symbols, and project structure are covered. If a
CMakeLists.txtexists, build through it rather than callingarm-none-eabi-gccdirectly.
Next¶
- Serial monitor for output that does not need a debugger.
- Plugins for installing and scoping plugins.