BKPT LabsDOCS/BKPT PROBE TOOLS/BKPT_GDBSERVER BKPT LABS · PROBE TOOLS
BKPT LABS · PROBE TOOLS

bkpt_gdbserver

A GDB remote-serial-protocol server for Cortex-M targets behind an ST-LINK, a J-Link, or the BKPT#1 probe. It is what BKPT Debug and BKPT Studio run for a debug session; it can also be used by hand with any arm-none-eabi-gdb.

bkpt_gdbserver [--probe vacore|stlink|jlink] [--serial S] [--speed KHZ] [--device NAME] [--jlink-dir DIR]
               [--tcp PORT] [--bind 127.0.0.1|0.0.0.0] [--no-reset] [--maskisr off|auto|on]
               [--live-tcp PORT] [--trace-tcp PORT] [--profile-tcp PORT] [--swo-tcp PORT]
               [--flm CHIP.FLM [--ram-base 0xADDR] [--ram-size 0xSIZE]] [--trace-support FILE]
$ bkpt_gdbserver --probe stlink --serial 0033004B3033510735393935 --tcp 2331 --live-tcp 2332 --profile-tcp 2334 --swo-tcp 2335
>> probe stlink 0033004B3033510735393935 (STLINK-V3 fw J17 @ 24000 kHz ap0)
>> GDB server listening on 127.0.0.1:2331  --  (gdb) target remote :2331
>> live-read channel on 127.0.0.1:2332 (r ADDR LEN -> ok HEXBYTES)
>> live-profile channel on 127.0.0.1:2334 (s MILLISECONDS -> ok N sleep=M rate=R PC:COUNT ...; q -> ok pcsr=0|1; h -> ok <hwtrace status json>; w -> ok swo=...)
>> raw SWO channel on 127.0.0.1:2335 (push: probe SWV bytes while 'monitor swo start' runs)
(gdb) target remote :2331
(gdb) load                      # with --flm
(gdb) monitor reset halt
(gdb) break main
(gdb) continue

Options

OPTION MEANING
--probevacore (default, the BKPT#1 FPGA probe over --port /dev/ttyUSBn, --swclk MHZ), stlink, jlink
--serial, --speed, --device, --jlink-dirProbe selection, SWD clock in kHz, SEGGER device name, SEGGER install directory
--tcp PORTThe GDB port (default 2331)
--bind127.0.0.1 (default) or 0.0.0.0 for a gdb on another machine
--no-resetAttach to the running program instead of resetting it at connect
--maskisrInterrupt masking while debugging (DHCSR.C_MASKINTS): off, auto (mask during single-step, default), on (hold across continue); also monitor maskisr live
--flm CHIP.FLMA CMSIS-Pack flash algorithm: required for load and any flash write, on any MCU or vendor. Without it the server is debug-only. --ram-base, --ram-size place the algorithm when the defaults do not fit
--trace-support FILEOverride the bundled vendor trace bring-up catalog (trace-support.json) used by monitor swo start and hwtrace apply
--live-tcp, --trace-tcp, --profile-tcp, --swo-tcpThe side channels, below; each off unless given
--dry-run --arch v7m|v8m|v6m [--caps JSON] --cpu-hz N --swo-hz N --itm-port P --hwtrace JSON|@FILEPrint the hardware-trace register image for those inputs and exit; no probe, no USB. The same image as viewalyzer-cli hwtrace --dry-run, pinned by a shared conformance table

Session behaviour

  • Connecting resets the target and halts at the reset vector (or attaches running with --no-reset); GDB's detach resumes it with the interrupt mask dropped.
  • Breakpoints are hardware (FPB) up to the core's count; watchpoints use the DWT comparators (watch, rwatch, awatch), and a hit reports which comparator matched.
  • Memory reads and writes go through the MEM-AP while the core runs, so a print in a running program works and the live channel exists.
  • The server ends the session by itself when its stdin closes or on SIGTERM/SIGINT: it disarms hardware trace and the fault catch, stops the SWO receiver, releases the probe (an ST-LINK gets DBG_EXIT), and exits. A host that spawns it should close stdin and wait rather than kill it; a process killed mid-transfer leaves an ST-LINK needing bkpt_probe reset-usb or a power cycle.
  • Flash programming (load, restore) needs --flm; the algorithm runs from RAM and the server verifies what it wrote.

monitor commands

(gdb) monitor help
supported monitor commands: reset [halt|run], halt, maskisr [off|auto|on], caps,
  faultcatch [all|off|hard bus mem usage state chk nocp int sf], fault [fresh],
  etm arm|drain out=<path>|disarm, hwtrace apply <json>|status|clear, swo start <swo_hz> <cpu_hz>|stop
COMMAND WHAT IT DOES
reset [halt|run]Reset the core, then halt at the vector (default) or run
haltHalt the core
maskisr off|auto|onThe interrupt mask policy, live
capsThe core's debug capabilities (breakpoints, comparators, trace blocks) as JSON
faultcatch all|off|hard bus mem usage state chk nocp int sfVector catch: halt on the named fault classes before the handler runs (DEMCR.VC_*), so a fault stops at the faulting instruction with the registers intact
fault [fresh]The decoded fault report for the current halt (the bkpt_probe fault report), fresh re-reads the registers
hwtrace apply <json>Program the hardware-trace image (ITM, TPIU, DWT: PC sampling, exception trace, data watches, counters) from a hardware-trace JSON block, at a halt; status re-reads and reports the image; clear disarms everything the server armed
swo start <swo_hz> <cpu_hz>Start the probe's SWO receiver at that rate (rounded to the rate the TPIU's integer prescaler actually produces), bring up the vendor trace pins from the catalog, push the bytes on --swo-tcp; stop ends it
etm arm|drain out=<path>|disarmBKPT#1 only: arm the ETM and the FPGA ring, drain a capture to a file, disarm

monitor runs only while the core is halted (a GDB rule): a host arms hardware trace at the halt after attach, and re-arms comparators at the next halt when rows change while running.

Side channels

All on 127.0.0.1 (or --bind), one client each, line protocols, alive for the length of a GDB session. They exist so an IDE can watch a running program without halting it.

CHANNEL PROTOCOL PURPOSE
--live-tcpr ADDR LENok HEXBYTES (err ...)Live memory reads while the core runs: the BKPT Debug live watch polls variables here at up to hundreds of hertz
--trace-tcpThe same read/write memory protocol, a separate clientRecorder and trace drains (a ViewAlyzer RAM-buffer capture during a debug session) alongside the live watch
--profile-tcps MILLISECONDSok N sleep=M rate=R PC:COUNT ...; qok pcsr=0|1; hok <hwtrace status JSON>; wok swo=on|off hz=N bytes=N dropped=NNon-halting statistical PC samples through DWT_PCSR (sleep = reads that returned 0xFFFFFFFF, the core in WFI/WFE; rate = reads per second achieved), the hardware-trace image and the SWO receiver state, all usable while the core runs
--swo-tcpPush: the raw SWO bytesThe probe's SWV receiver output while monitor swo start runs; viewalyzer-cli capture --transport swo-tcp --swo-tcp-port N decodes it (recorder stream, ITM console, PC samples, exception trace, data watches)

A client that cannot keep up is dropped rather than allowed to stall the GDB loop; the SWO channel keeps a 64 KB pending buffer.

Hardware trace, end to end

With an ST-LINK or J-Link and the target's SWO pin wired:

(gdb) monitor swo start 10000000 170000000
swo: receiver on at 10000000 Hz (cpu 170000000 Hz), bytes on the --swo-tcp channel
(gdb) monitor hwtrace apply {"dwt":{"enable":true,"exception-trace":true,"pc-sample-cyc":16384,"watch":[{"addr":"0x200000E4","size":4,"function":"data-w","name":"sig_noise"}]}}
hwtrace: applied
(gdb) continue
$ viewalyzer-cli capture --transport swo-tcp --swo-tcp-port 2335 --cpu-clock-hz 170000000 --swo-freq-hz 10000000 --itm-port 1 \
      --hardware-trace '{"dwt":{"enable":true,"exception-trace":true,"pc-sample-cyc":16384}}' --elf firmware.elf --output session.vadb --stream

monitor hwtrace status prints the applied image with the registers read back, and the refusals with their reasons when the core lacks a feature (the same verdicts as bkpt_probe detect-trace).

Fault catching

(gdb) monitor faultcatch all
(gdb) continue
Program received signal SIGSEGV, Segmentation fault.     # halted before the handler ran
(gdb) monitor fault
{ "event": "fault", "caught": "vector-catch", "exception": {"number": 6, "name": "UsageFault"}, "root_cause": "INVSTATE", ... }

faultcatch sets the vector-catch bits so the core halts at the faulting instruction with the registers and the stack untouched; fault decodes the state. Both survive across continue; faultcatch off clears them, and detach clears whatever the server armed.

Logging

The server prints its log on stderr (>> lines; !! for probe errors), which the IDE shows in its Output pane. >> slow dispatch 'vCont;c' held the loop N ms (live channel starved) is informational: a long continue held the packet loop, which is normal for a running program.