cancel
Showing results for 
Search instead for 
Did you mean: 

How to manually set the values of SP,LR register of a stm f103c8t6 in systemworkbench?

SSRIN.1
Associate III

I am following this tutorial to debug a hard fault <timestamp 20:00>. I found that it is a bus fault and tried to access the BFAR register to see the address access that triggered the exception. But the address<0x1826852602> it was pointing didn't make sense and was outside the memory map as shown in pg 53 . So I tried reversing the state to before triggering hard fault as described in above tutorial link. Unfortunately I was only able to change PC register. The SP and LR is not changing. I tried in both GDB as well as register monitor. I want to know the specific instruction that is trying to access this address. Unfortunately backtrace gdb command is not showing that instruction because SP and LR registers are not updated to previous state.

As I mentioned before since, I was able to change PC register to previous state. I tried to find the instruction associated with this address. it correctly points to the function that was executed just before hard fault was triggered. But not the actual instruction.

Please Advice on how to proceed forward.

EDIT1:

I think I made a mistake in gdp commands.

I again tried reading register, now it looks like a hex value of address. However I get different address at each successive attempt to run eg. [0x6ce38efa , 0xef9f9296, 0x8e726e0a ...]. This is still outside the memory map no ?

I used this GDB command.

p/x *((uint32_t *)0xE000ED38) //hex read fro BFAR register.

2 REPLIES 2

LR tends to reflect the last subroutine it came from, it might change infrequently, but can help contextualize the failure, and where to be looking/instrumenting. Subroutines that call other subroutines will push it onto the track, and you can perhaps fish it out from there and generate a rough call-tree. The LR will tend to have different characteristics than ASCII characters, general bytes, or RAM pointers.

If think SWB has been deprecated for a while, and I'm not a GDB adherent (I worked with SID and DDT)

I'm not sure having an address outside the entire functional address space of the MCU is of any use at all.

I dump as much state as possible in my Hard Fault Handler so I can pinpoint the faulting instruction,and the conditions that would have caused it to fault. I also use it to field diagnose issues, a tight while(1) loop is going to tell the customer nothing, and the support technicians will be equally uninformed, so a complete waste of time and resources all round. At the very least it can differentiate one failure from another, or establish common or repeat patterns of failure.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
alister
Lead

The fault occurred before the bus fault. Perhaps do some of these...

  • Check stacks for overflow. If your stacks aren't initialised some fixed value, add that. If the target executes for some time before failing, stop it before it fails and check by change of the pattern for stacks with too little headroom for interrupts, or recursion (if you have any). You could do this after failing too. But you mightn't know what damage is done to RAM after the first failure. If you inspect after failure and find one task stack has overrun and increasing that stops the failing, you might guess it is the cause if it often uses more stack than previously and is continuously reliable now.
  • Enable generating a listing file in your build settings, build the listing, then check if that LR is consistent with that and, if so, closely inspect the function it's returning for bugs, e.g. overrun of a local variable, calling an uninitialised function pointer, etc.
  • Instrument the code, e.g. assign values to variables or add entries to ring-buffers, for the purpose of post-analysing to isolate where and/or when in the code the fault occurs, then, if necessary, add some code somewhere close to that, to perform tests to trap the fault and/or a breakpoint or conditional breakpoint there that it will fail close to where/when the fault is about to occur and then step to the line that fails... If the fault is easily repeatable, you could do several of these to "triangulate" the where/when.