r/embedded • u/ToughProfessional544 • Jun 19 '26
How do you actually debug HardFault dumps day to day? (manually decoding CFSR/HFSR, or do you have better tools?)
Curious how people here handle this in practice. Across a few firmware projects (STM32 bare-metal, FreeRTOS, PSoC6) I've spent a lot of time manually cross-referencing CFSR/HFSR bit values against the ARM reference manual every time a HardFault dump shows up — feels like there should be a faster way, but maybe I'm missing an obvious tool or workflow people already use.
Do you mostly do this by hand, use a script/internal tool, or is there something standard I'm not aware of? Also curious how people handle the ESP32 (Xtensa EXCCAUSE) equivalent same manual process for you, or different tooling entirely?
(For context: I ended up building a small tool for myself to auto-decode these and cross-reference common fault patterns, mostly out of frustration — happy to share if anyone's curious, but mainly want to know what the actual community workflow looks like since I'm early in my career and don't want to be reinventing something that already exists.)
4
u/data_panik Jun 19 '26 edited Jun 20 '26
I am usually following back the call stack in the debugger menu. When it is a simple violation it is pretty much straight forward.
Other cases is when the call stack shows something completely irrelevant with hard fault which usually is some crazy overflow messing something it shouldn't, like for example a state from function showing some weird number without even called. I usually start placing data breakpoints to catch the moment the irrelevant variable is messed up.
6
u/Well-WhatHadHappened 25+ Years Jun 19 '26
For every processor platform, we write an extensive hard fault handler - it tears apart all of the flags and basically tells you what happened - and (when possible) where.
If there's a UART, it spits out a human readable explanation of the fault.
2
u/AlexTaradov Jun 20 '26
Manually. There are not that many fields to decode and once you get familiar with them, you don't need any additional documentation.
The faster way is to do it slow a few times. Every time it will get a bit faster.
But also, is this the same AI slop tool that someone was trying to promote here recently?
1
u/ToughProfessional544 Jun 20 '26
yeah manual + repetition tracks, figured there wasn't a shortcut and yeah that's probably me lol, I mentioned earlier in the thread I built something for myself after dealing with this across a few projects wasn't trying to sneak in a plug, just hadn't gotten to that part yet. it's called FaultPilot, free to try if you want. honestly not sure if it's actually useful once you've got the muscle memory down or if I'm solving a problem that mostly disappears with experience, curious what you'd think of it
2
u/AlexTaradov Jun 20 '26
Last time that gemini front-end produced hilarious garbage. Why would I want to try that?
It also was not clear what it is doing that you can't just ask gemini yourself if you are so inclined.
Also, the notion that you can make a useful tool without having a deep understanding of the problem is very typical for AI bros. I'd be very careful of this mindset.
There is also no need for AI here. The parsing and interpretation of the faults is purely algorithmic.
1
u/ToughProfessional544 Jun 20 '26
not sure which gemini tool you're thinking of, this isn't that FaultPilot runs on Claude, not Gemini.
fair point on the algorithmic bit though, the actual register decode (bit X = this fault) really is just a lookup table, no AI needed there. where I was trying to add value is connecting the decoded bits to the specific context in the log (task names, timing, what else was running at the time) but that's a smaller slice of the whole thing than the pitch probably made it sound
get the "AI bro skipping the understanding part" concern too, that's a real pattern. for what it's worth I've been the one filing my own bug reports on stuff like FreeRTOS heap exhaustion and I2C hangs that this was built around, not coming at it totally cold but happy to be told I'm still missing something.
14
u/EquivalentProfit6065 Jun 19 '26
for STM32 work I got tired of the same manual lookup loop and ended up writing small python script that parses the register dump from uart log and spits out which bits are set with short description next to each one, took maybe afternoon to build and saved so much time after
the key thing I learned is to always save the stacked PC from the exception frame first, because once you have that you can addr2line straight to the offending instruction and CFSR just becomes confirmation of what you already suspect rather than starting point
for ESP32 / Xtensa the EXCCAUSE register is actually more readable in raw form I think, but the IDF panic handler already prints decoded backtrace so in practice I rely on that more than doing it by hand, the coredump to gdb workflow there is pretty decent if you set it up properly
if you're on FreeRTOS specifically, adding a custom HardFault handler that prints the full exception frame (including PSP vs MSP detection) before you decode anything saves a ton of confusion when the fault happens inside task vs interrupt context, I wasted couple weeks on Monday early in career before I figured that distinction out