BKPT LabsDOCS/BKPT DEBUG/FAULT ANALYZER BKPT DEBUG · VS CODE
BKPT DEBUG · USER GUIDE

Fault Analyzer

Run the firmware, hit a fault, read what happened. The debugger catches HardFault, BusFault, MemManage, UsageFault and friends at the exception itself, before any handler runs, and explains them: the root cause in one line, every set bit of the fault registers with its meaning, the faulting address when the core says it is valid, and the line of your code that did it. Your firmware needs no fault handler for this; a while (1) in HardFault_Handler is fine, the debugger stops the core before it gets there.

A caught UsageFault: the verdict line, the eight facts, the fault status bits, and the recovered frame with its source line.
A CAUGHT USAGEFAULT: THE VERDICT LINE, THE EIGHT FACTS, THE FAULT STATUS BITS, AND THE RECOVERED FRAME WITH ITS SOURCE LINE

How it catches

The Cortex-M debug block can halt the core the instant a fault vector is taken (a "vector catch"). When a session starts, the debugger arms the classes you chose (bkptDebug.faultCatch, default all; the checkboxes in the tile edit it live) and disarms them when it detaches. A caught fault halts the target with the stack still intact, which is what makes the recovered frame trustworthy, and the tile opens itself once per fault.

The fixture firmware parked before a fault, with the catch classes armed in the tile's header.
THE FIXTURE FIRMWARE PARKED BEFORE A FAULT, WITH THE CATCH CLASSES ARMED IN THE TILE'S HEADER

The classes, in the tile's header: HardFault (escalated faults, vector-table read errors), BusFault (precise and imprecise bus errors, stacking errors), MemManage (MPU violations, execute-never), UsageFault (undefined instruction, invalid state, divide by zero, unaligned access, stack overflow), IRQ errors (exception entry and return integrity) and SecureFault (Armv8-M with the Security Extension). A class the core does not have is greyed out with the reason.

Reading the tile

The summary card answers the fault in one line and eight facts:

FACT WHAT IT COMES FROM
ExceptionThe active exception number and name (#6 UsageFault)
CauseThe status bit that names it (INVSTATE) and the root-cause sentence
Escalated?Whether a configurable fault was taken as a HardFault instead
Caught byVector catch (halted at the exception, frame intact) or At halt (analyzed after the fact)
Recovered PCThe instruction that faulted, resolved to function and line; click to open it
Recovered LRWhere it was called from, resolved the same way
Stacked xPSRThe program status the hardware pushed; its Thumb bit is the tell for an invalid-state fault
Fault addressMMFAR / BFAR, shown only when the core marked it valid, else not valid

Below it: Fault status, the set bits with their meaning, each one clickable; Where it happened, the recovered pc and lr with a trust badge on the frame (good, suspect, none), the stack in use (MSP or PSP) and whether an FPU frame was pushed; Notes the analyzer adds when something needs saying (an imprecise bus error, a frame it could not trust); and two cards with the core registers of the faulting context and the raw architectural state.

Read the registers in this order

Faults do not have a single status word; the answer is spread over five registers, read in a fixed order. The tile does this for you; knowing the order tells you how much to trust each line.

STEP QUESTION REGISTER
1How was it caught? Halted at the fault, or noticed later? A stale report lies about "where".DFSR
2Which exception, and was it escalated?ICSR, HFSR
3What went wrong: bad access, undefined instruction, divide by zero?CFSR
4At what address? Only when the matching VALID bit is set.MMFAR, BFAR
5Where in my code? The stacked frame: pre-fault pc, lr, and the xPSR that proves the mode.the stack

Everything after step 3 is about where, not what.

Every register, every bit

The CFSR decoded bit by bit in the tile's register panel, the bit this capture set highlighted, each field tagged with the architectures that have it.
THE CFSR DECODED BIT BY BIT IN THE TILE'S REGISTER PANEL, THE BIT THIS CAPTURE SET HIGHLIGHTED, EACH FIELD TAGGED WITH THE ARCHITECTURES THAT HAVE IT

Click a status bit, or a register name, and the tile opens that register bit by bit: every field with its meaning, the bits this capture set highlighted, and a tag on each field saying which architecture has it (Armv6-M, Armv7-M, Armv8-M, FPU, Security), because the same tile runs against a Cortex-M0+ with almost none of these registers and a Cortex-M33 with a whole extra secure bank. The registers it decodes:

REGISTER WHAT IT TELLS YOU
ICSRThe exception whose handler is running (VECTACTIVE), and what is pending
SHCSRWhich configurable fault handlers are enabled; a clear ...ENA bit is why a fault escalated to HardFault
DEMCRThe debugger's vector-catch bits (how the target was stopped) and TRCENA
DFSRWhy the core entered debug halt: VCATCH means a live catch
CFSRThe one that matters: MMFSR (MemManage), BFSR (BusFault) and UFSR (UsageFault) stacked in one word, sticky bits
HFSRWhy a HardFault was taken; FORCED says "a configurable fault escalated, read CFSR"
MMFAR / BFARThe faulting data address, valid only with MMARVALID / BFARVALID; an imprecise bus error leaves it invalid by nature
AFSRVendor-defined auxiliary bits, zero on most STM32
FPCCRThe FPU context state (lazy stacking, which handlers are ready), on cores with an FPU
SFSR / SFARSecurity-boundary violations, Armv8-M with the Security Extension
xPSR (stacked)The pushed program status; the Thumb bit must be 1, a 0 is exactly an INVSTATE fault
EXC_RETURNThe magic lr on entry: which stack the frame is on, thread or handler mode, whether FP registers were pushed

Escalation

The same undefined instruction with the UsageFault handler disabled: caught as a HardFault, root cause "escalated UsageFault", the original cause still decoded.
THE SAME UNDEFINED INSTRUCTION WITH THE USAGEFAULT HANDLER DISABLED: CAUGHT AS A HARDFAULT, ROOT CAUSE "ESCALATED USAGEFAULT", THE ORIGINAL CAUSE STILL DECODED

A fault whose handler is disabled in SHCSR (or masked by priority) escalates to HardFault. HFSR.FORCED records that, and the original cause is still in CFSR, so the tile reports the HardFault with its real cause and the Escalated? fact set. Firmware that never enables the configurable fault handlers sees every fault as a HardFault; the tile still tells you which one it was.

What each core has

ARCHITECTURE CORES WHAT THE ANALYZER CAN READ
Armv6-MCortex-M0, M0+, M1HardFault only, no CFSR, HFSR or fault-address registers. The report leans on the recovered pc / lr and the stacked xPSR. Vector catch for HardFault and reset only.
Armv7-MCortex-M3, M4, M7Everything above; the FPU registers on M4F / M7.
Armv8-MCortex-M23, M33, M55, M85Everything, plus stack-limit overflow (STKOF) and, with the Security Extension, SecureFault with its own address register.

The tile knows which it is talking to (the core and profile show in its header) and greys out what the core lacks, with the reason.

Analyze now

Analyze now in the tile's header runs the same analysis on any halted target: a firmware that faulted into its own handler before you attached, a fault you did not catch because its class was off. The report is marked At halt rather than Vector catch: the status registers still say what happened, but the frame and the "where" may be stale if the handler ran. A report goes stale when the target runs again after it.

Known limits

  • Catching needs a session started or attached by BKPT Debug; a fault that happened before that is a job for Analyze now.
  • An imprecise bus error (a buffered write that faulted late) has no exact pc; the tile says so and shows the approximate one.
  • Armv8.1-M and Security-Extension cases are decoded from the architecture manuals but have had less bench time than the Armv6-M / Armv7-M cores.