Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Analyzing Cortex-M Hardfaults

> I have a build of PX4 (NuttX 6.29 with some patches) with new lpc43xx chip files on 4337 chip running from FLASH (master vanilla NuttX has no such problem). This gives me a hardfault below if I stress NSH console (UART2) with some big output.
>
> I read some threads but can't get a clue how to analyze the dump and where to look first:
>
> 1bXXX and 1aXXX addresses are FLASH. 100XXX addresses are RAM

Code Block
  Assertion failed at file:armv7-m/up_hardfault.c line: 184 task: hpwork
  sp:     10001eb4
  IRQ stack:
    base: 10001f00
    size: 000003fc
  10001ea0: 1b02d961 1b03f07e 10001eb4 10005ed8 1a0312ab 1b03f600 000000b8 1b02d961
  10001ec0: 00000010 10001f40 00000003 00000000 1a03721d 1a037209 1b02d93b 00000000
  10001ee0: 1a0371f5 00000000 00000000 00000000 00000000 00000000 1a0314a5 10005d7c
  sp:     10005e50
  User stack:
    base: 10005ed8
    size: 00000f9c
  10005e40: 00000000 00000000 00000000 1b02d587 10004900 00000000 005b8d7f 00000000
  10005e60: 1a030f2e 00000000 00000000 00001388 00000000 00000005 10001994 00000000
  10005e80: 00000000 00000000 00000000 1b02c359 00000000 00000000 00000000 004c4b40
  10005ea0: 000002ff 00000000 00000000 1a030f2f 00000000 00000000 00000000 00000000
  10005ec0: 00000000 1a030f41 00000000 1b02c2a5 00000000 00000000 ffffffff 00bdeb39
  R0: ffffffff 00000000 00000016 00000000 00000000 00000000 00000000 00000000
  R8: 100036d8 00000000 00000000 004c4b40 10001370 10005e50 1b02b20b 1b02d596
  xPSR: 41000000 BASEPRI: 00000000 CONTROL: 00000000
  EXC_RETURN: ffffffe9

Analyzing the Register Dump

First, in the register dump:

...

Sometimes, however, R14 is not the caller of the offending function. If the offending functions calls some other function then R14 will be overwritten. But no problem, it will also then have pushed the return address on the stack where we can find it by analyzing the stack dump.

Analyzing the Stack Dump =

The Task Stack

To go further back in the time, you have to analyze the stack. It is a push down stack so older events are at higher stack addresses; the most recent things that happened wil be at lower stack addresses.

...

That will give the full backtrace up to the point of the failure.

The Interrupt Stack

Note that in some cases there are two stacks listed. The interrupt stack will be present if (1) the interrupt stack is enabled, and (2) you are in an interrupt handler at the time that the failure occurred:

...

The interrupt stack is sometimes interesting, for example when the interrupt was caused by logic operating at the interrupt level. In this case, it is probably not so interesting since fault was probably caused by normal task code and the interrupt stack probably just shows the normal operation of the interrupt handling logic.

Full Stack Analysis

What I have proposed here is just skimming through the stack, finding and interpreting interesting addresses. Sometimes you need more information and you need to analyze the stack in more detail. That is also possible because every word on the stack is there because of an explicit push instruction in the code (usually a push instruction on Cortex-M or an stmdb instruction in other ARM architectures). This is painstaking work but can also be done to provide a more detailed answer to "what happened?"

Recovering State at the Time of the Hardfault

Here is another tip from Mike Smith:

...