cancel
Showing results for 
Search instead for 
Did you mean: 

Want to figure out how dig down into stacked LR and SP values on an STM32f429 programmed with Keil tools.

BPort.2
Associate II

Have a device built around an 32f429 which appears to be hard faulting too infrequently to catch on the bench with debugger attached -- but have lab personnel running all day and getting the errors, not infrequently enough.

I can use some BKUP registers (BKUP RAM and RT Clock) to store away some info from the HardFault handler before resetting -- then dump out to a file after reset. I'm getting bits from the fault status registers and the values stacked when fault occurs (including address of a suspect instruction). All I've found about the ABI is the ARM Base ABI which says that SP and LR are callee saved. I'm using Keil tools (ARMCC ?? - not in front of the IDE at the moment) -- but so far I've evoked little hints about anything documented about where those registers are saved. I know the locations of variables will not be known (in general), but the calls preceding the fault should be extractable.

5 REPLIES 5

Read PM0214, chapter Exception model, subchapter Exception entry.

Clive (Tesla DeLorean) wrote about debugging hardfaults here many times, e.g. https://community.st.com/s/question/0D50X0000Az372YSQQ/stm32l412-hardfault-while-using-minimal-cubeide-example

JW

Hi Jan,
Thanks for your reply. I've read the info you point to in PM0214, but my problem isn't what is stacked during exception entry. I'll look more closely at the link you provided to see if there are hints there.
I'm trying to get some more info out from the fault handler non-interactively and without debug info. Since data values can be moved around in the compiled code I can't grab much there, but I'm hoping that some standard is being followed by the compiler for storing LR and SP values (at the start of any non-leaf function perhaps), so that I can trace back from an offending instruction to previous BRX (or whatever) instructions which led to the function containing that instruction.
With the number of instruments running (seeing the problem with sufficient frequency) it may be that I can (and have to) chase the problem iteratively. If I learn to read DWARF (or whatever it takes), knowing the stack of function calls may let me find where some other useful data is at fault time -- and I can adjust the handler to spit that out.
Maybe I'm having bad luck -- but it seems so crazy that I haven't bumped into this info yet in searching (yeah -- I'll resort to looking at disassemled code if I need to, but ...).
Regards,
Brett

PC stacked at the exception entry points to instruction which is one or a few instructions after the instruction which caused the exception. Except in cases where the execution went completely awry (i.e. taking messed up function pointers or return after stack corruption), this together with content of other registers and mixed source/disasm is enough to find out the problematic line/data in the source.

JW

Right. I've got that address -- and so can find the line of code, and the function containing it... say function "ucalledme". ucalledme might turn out to be some utility function, or otherwise be insufficient to be of much use. It seems that there should be an earlier value of LR which contains the address following the BLX instruction which is the call to ucalledme..... and so on.... and a straightforward way of finding that earlier LR value.

What's on stack is entirely up to the compiler.

DWARF contains that information so the debugger can walk back, but I don't think it's trivial nor that it can in any simple way be implemented on the target.

A "poor man's tracer" could be conceived by simply going through the stack (backwards) and consider everything in FLASH range to be a valid return address.

JW