cancel
Showing results for 
Search instead for 
Did you mean: 

How to parse raw stack data in hex (STM32F4)?

GFree.2
Associate II

Hello,

I'd like to ask is there any information about parsing raw stack data?

I always save data from PSP stack when a HardFault happens. Here is an example:

20020200: 00000000 0A461285 00000F7F 00000000 00000000 0812CA7D 0812CA9A 20020210

20020220: <hex> <hex> <hex> <hex> <hex> <hex> <hex> <hex>

etc

As far as I understand it may be helpful to recover the end of the list of functions in the order they were called before a HF happened. Is there any resources about recording information on stack for STM32F4?

9 REPLIES 9
KnarfB
Principal III

What you are looking for is stack unwinding. This can be done with a little help of the gcc compiler. See https://github.com/red-rocket-computing/backtrace

Generally speaking you'd need a lot of debug data from the compiler/linker to make a much headway. The stack frame, register usage is not as orthogonal as say DOS x86 code.

ODD addresses in the 0x08000000 range are typically LR pushes to return targets, ie 0x0812CA7D is where in came from. This is usually the easiest way to pull out points of interest if you can't determine why the Hard Fault arrived where it did. Generally far easier to check-point the code with sanity checks and flow telemetry if this is a recurrent fault on the debugger.

For field analysis you're often better to use a pencil and a .MAP file, and a dump of the immediate stack, and instructions, along with the registers.

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

> Is there any resources about recording information on stack for STM32F4?

0693W000006F2gXQAS.png In your case, PC is 0812CA9A , i.e. the faulting instruction will be at that address or a few addresses before that address (in case of imprecise fault).

JW

Ok and is there any way to recognize ASM instruction codes in a stack frame?

Stack is in RAM, but code (instructions) are in Flash, usually. Stack contains data like local variables, saved register values, and exception/return addresses which point to code.

Read PM0214 Programming manual cited by Jan below or a good book on that topic (Joseph Yiu). Try stepping though sample code and watch what happend and how the stack is used.

There aren't any instructions on the stack. The stack mostly contains data, with sporadic return addresses, if pushed, and perhaps pointers.

You can pull the faulting PC from the fault stack, and dump the 16-bit works around that.

https://community.st.com/s/question/0D50X0000Az372YSQQ/stm32l412-hardfault-while-using-minimal-cubeide-example

Stack dump variant looking like this currently

void hard_fault_handler_c(unsigned int * hardfault_args, unsigned int r4, unsigned int r5, unsigned int r6)
{
  printf("\n[Hard Fault]\n"); // After Joseph Yiu
 
  printf("r0 = %08X, r1 = %08X, r2 = %08X, r3 = %08X\n",
    hardfault_args[0], hardfault_args[1], hardfault_args[2], hardfault_args[3]);
  printf("r4 = %08X, r5 = %08X, r6 = %08X, sp = %08X\n",
    r4, r5, r6, (unsigned int)&hardfault_args[8]);
  printf("r12= %08X, lr = %08X, pc = %08X, psr= %08X\n",
    hardfault_args[4], hardfault_args[5], hardfault_args[6], hardfault_args[7]);
 
  if (__CORTEX_M >= 3)
    printf("bfar=%08X, cfsr=%08X, hfsr=%08X, dfsr=%08X, afsr=%08X\n",
      *((volatile unsigned int *)(0xE000ED38)),
      *((volatile unsigned int *)(0xE000ED28)),
      *((volatile unsigned int *)(0xE000ED2C)),
      *((volatile unsigned int *)(0xE000ED30)),
      *((volatile unsigned int *)(0xE000ED3C)) );
 
  extern void *__initial_sp;
  { // Stack Dump
    int i = 0;
    uint32_t *p = (uint32_t *)&hardfault_args[8];
    uint32_t *q = (uint32_t *)&__initial_sp;
    while((p < q) && (i < 32))
    {
      if ((i++ & 7) == 0) putchar('\n');
      printf(" %08X", *p++);
    }
    putchar('\n');
  }
 
  { // Instruction Dump
    int i = 8;
    uint16_t *p = (uint16_t *)((hardfault_args[6] & ~1) - (i*2)); // PC, 8 opcodes earlier
    while(i--)
      printf(" %04X", *p++);
    printf("[%04X]", *p++);
    i = 3;
    while(i--)
      printf("%04X ", *p++);
    putchar('\n');
  }
 
  while(1)
  {
  }
} // sourcer32@gmail.com

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

Thank you so much for your help

Thank you!

Thank you