BKPT LabsDOCS/BKPT PROBE TOOLS/BKPT_PROBE BKPT LABS · PROBE TOOLS
BKPT LABS · PROBE TOOLS

bkpt_probe

One operation per invocation, one JSON object on stdout, exit 0. A failure still prints JSON: {"ran":false,"error":"..."} when the probe could not be opened, {"ran":true,"ok":false,"error":"...","addr":"0x..."} when the target refused an access. Every verb except list opens the probe, attaches over SWD without resetting the target, does its work, and releases the probe (an ST-LINK gets its DBG_EXIT, so the next opener finds it clean).

bkpt_probe <list|info|read-mem|write-mem|detect-trace|fault|reset-usb> [--probe stlink|jlink|auto] [--serial S] [--speed KHZ] [--jlink-dir DIR] [--device NAME]

list

Every probe on USB, no target access.

$ bkpt_probe list
{"ran":true,"probes":[{"kind":"stlink","serial":"0033004B3033510735393935","version":"STLINK-V3","vid":"0x0483","pid":"0x374e"}]}

info

Opens the probe, attaches, reads the DP IDCODE.

$ bkpt_probe info --probe stlink --serial 0033004B3033510735393935
{"ran":true,"present":true,"kind":"stlink","serial":"0033004B3033510735393935","version":"STLINK-V3 fw J17 @ 24000 kHz ap0","swo_max_hz":24000000,"idcode":"0x2ba01477","link":true}

version names the firmware and the SWD clock actually applied; swo_max_hz is the probe's SWO receiver ceiling (0 when it has none), the number the BKPT Debug extension bounds the SWO clock with; idcode is the debug port's ID (0x2ba01477 on every Cortex-M4). "present":true,"link":false means the probe answered but the target did not (unpowered, no SWD wiring, held in reset).

read-mem, write-mem

$ bkpt_probe read-mem --probe stlink --serial 0033004B3033510735393935 --addr 0xE000ED00 --len 4
{"ran":true,"ok":true,"addr":"0xe000ed00","len":4,"data":"41c20f41"}

$ bkpt_probe read-mem --probe stlink --addr 0xE000ED00,0xE000ED28 --len 4
{"ran":true,"ok":true,"reads":[{"addr":"0xe000ed00","len":4,"data":"41c20f41"},{"addr":"0xe000ed28","len":4,"data":"00000000"}]}

$ bkpt_probe write-mem --probe stlink --addr 0x20000100 --data 78563412
{"ran":true,"ok":true,"writes":[{"addr":"0x20000100","ok":true}]}

data is the raw little-endian bytes as hex (41c20f41 is CPUID 0x410FC241). A comma-separated --addr list (up to 64) reads or writes each in one probe session; --len applies to each read; --data takes one hex-byte string per address, whole words. Both stop at the first failure, whose entry carries "ok":false and the error, and the envelope then ends with "ok":false. Memory access goes over the MEM-AP while the core runs; nothing is halted.

detect-trace

The CoreSight ROM-table walk plus the trace-capability verdicts: what this core has and whether each hardware-trace feature can be used.

$ bkpt_probe detect-trace --probe stlink --serial 0033004B3033510735393935
{"ran":true,"present":true,
 "probe":{"kind":"stlink","version":"STLINK-V3 fw J17 @ 24000 kHz ap0","swo_max_hz":24000000},
 "idcode":"0x2ba01477","verdict":"pins","etm":true,"etmV4":false,
 "sink":{"present":false,"kind":"none","base":null},"debugLocked":false,"rombase":"0xe00ff000","coreAp":0,
 "components":[{"base":"0xe000e000","part":"0x00c","name":"SCS-M4","class":14},{"base":"0xe0001000","part":"0x002","name":"DWT","class":14},
               {"base":"0xe0002000","part":"0x003","name":"FPB","class":14},{"base":"0xe0000000","part":"0x001","name":"ITM","class":14},
               {"base":"0xe0040000","part":"0x9a1","name":"TPIU-M4","class":9,"coresight":true,"devtype":"0x11","devid":"0x00000ca1"},
               {"base":"0xe0041000","part":"0x925","name":"ETM-M4","class":9,"coresight":true,"devtype":"0x13"}],
 "dwt":{"present":true,"numcomp":4,"notrcpkt":false,"nocyccnt":false,"noprfcnt":false,"noexttrig":false,"ctrl":"0x40000001","func_id":[0,0,0,0]},
 "itm":{"present":true,"ports":32},
 "tpiu":{"present":true,"protocols":["nrz"]},
 "verdicts":{"pc-sampling-onchip":"ok","exception-trace":"ok","data-trace":"ok","event-counters":"ok","itm-console":"ok","pc-sampling-poll":"ok"}}
FIELD MEANING
verdictHow ETM trace could leave the chip: pins (a TPIU with a parallel trace port, the BKPT#1 case), etb (an on-chip buffer), unknown
etm, etmV4An ETM is present, and whether it is ETMv4
sinkAn on-chip trace sink (ETB/ETF) when there is one
debugLockedThe ROM walk came back empty on a present target: debug access is disabled by option bytes or RDP
components[]Every ROM-table entry with its base, part number, name and class
dwtDWT_CTRL decoded: comparator count (numcomp), and the no* bits that say what the vendor left out (notrcpkt = no trace packets, so no PC sampling or exception trace over SWO; nocyccnt; noprfcnt = no event counters)
itm, tpiuPresence, stimulus port count, trace protocols
verdictsOne per hardware-trace feature: ok or the reason it cannot be used on this core. The BKPT Debug extension's Target scan is this call

--peek 0xADDR[,0xADDR...] adds 32-bit reads in the same session (the extension peeks DWT_CTRL this way). With a J-Link always pass --device (the SEGGER name, STM32G474RE): a generic attach makes the walk unreliable, and the tool says so instead of returning a verdict it cannot trust.

fault

Snapshots and decodes the Cortex-M fault state: halts a running core for the capture, reads the fault registers and the exception frame, and resumes it (--keep-halted leaves it stopped).

$ bkpt_probe fault --probe stlink --serial 0033004B3033510735393935
{"ran":true,"was_running":true,"left_halted":false,
 "report":{"event":"fault","caught":"halted",
           "arch":{"profile":"armv7-m","core":"Cortex-M4","cpuid":"0x410FC241","fpu":true,"security":false,"mpu_regions":8},
           "exception":{"number":0,"name":"Thread"},"root_cause":"Thread","escalated":false,"faults":[],
           "fault_address":{"valid":false},"precision":"n/a","exc_return":{"valid":false},"frame":{"trust":"none"},
           "regs":{"r0":"0xD149043B", ..., "sp":"0x2001FF88","lr":"0x080005A1","pc":"0x08001406","xpsr":"0x81000000","msp":"0x2001FF88","psp":"0x00000000","control":"0x00","faultmask":"0x00","basepri":"0x00"}, ...}}

On a healthy core (above) exception.number is 0 and faults is empty. On a faulted one the report names the active exception, the root cause (HardFault escalated from a UsageFault INVSTATE, a BusFault PRECISERR with a valid fault_address, and so on), the decoded CFSR/HFSR/MMFAR/BFAR bits, the EXC_RETURN, and the stacked frame with how far it can be trusted. This is the same report the BKPT Debug Fault Analyzer shows, and bkpt_gdbserver's monitor fault.

reset-usb

For an ST-LINK that answers nothing (a session killed mid-transfer used to leave one streaming SWO): a libusb port reset, a re-open by serial, and a CPUID read to prove it is back.

$ bkpt_probe reset-usb --probe stlink --serial 0033004B3033510735393935
{"ran":true,"ok":true,"idcode":"0x2ba01477","cpuid":"0x410fc241"}

Unsupported on a J-Link (the SEGGER library owns the device). When even this fails, the probe needs a power cycle.

Exit codes and errors

The process exits 0 whenever it ran; read ran, ok and error in the JSON. Probe-open failures name the cause: no matching probe on USB, probe present but claimed by another process (a debugger session or another tool holds it), GET_CURRENT_MODE failed (an ST-LINK left mid-stream, try reset-usb), J-Link library not found (--jlink-dir).