This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How can I distinguish the reason for hardfault?

  • Using SDK 7.2 and S110 7.1

  • IDE : IAR 7.1

  • Board : PCA10001 (Revision 2 MCU)

Hi, regardless of the example, when I add some codes of my own,

there are some cases when the firmware falls into HardFault_Handler

(or other Handlers such as BusFault_Handler).

Handler

Comparing to the situation such as SDK function returns error code,

it is easy for developers to tell what code is the problem.

Whereas when the code falls into HardFault_Handler,

is there a way to identify what cased this problem?

Added : 23, July, 2015

Memory check

One more thing, do I have to consider the endian?

Since nRF51822-QFAA is based on little-endian,

is [0X2000 32D0] = 0x0001 0000 or 0x0100 0000?

If it's 0x0001 0000 (code instruction at 0x0001 0018), then this means the SoftDevice has caused a HardFault?

In my case, as mentioned above, I use SoftDevice S110 7.1 and SDK 7.2.

Dis

This is the Dissembly window.

(If showing the instructions of the SoftDevice is illegal, please notice me and I will edit this part.)

Also, this is a part of the .map file.

  Section            Kind        Address    Size  Object
  -------            ----        -------    ----  ------
"A1":                                       0xc0
  .intvec            ro code  0x00016000    0xc0  iar_startup_nrf51.o [1]
                            - 0x000160c0    0xc0
 
"P1":                                     0x7c00
 
  .text              ro code  0x000160c0   0xf14  device_manager_peripheral.o [1]
  .text              ro code  0x00016fd4    0x28  memcmp.o [4]
  .text              ro code  0x00016ffc    0x64  ABImemset.o [4]
  .text              ro code  0x00017060    0x5c  ABImemcpy.o [4]
  .text              ro code  0x000170bc   0x8cc  pstorage.o [1]
  .text              ro code  0x00017988    0xe0  I32DivModFast.o [4]
  .text              ro code  0x00017a68     0x2  IntDivZer.o [4]
  .text              ro code  0x00017a6a    0x2a  zero_init3.o [4]

Added again : 23, July, 2015

Handler / Command

@RK : At 0x00019b5a, it was LDR command.

-Regards

  • One way to do it is like this.

    Check this infocenter.arm.com/.../index.jsp

    You can see that on Cortex-M0, on Exception entry (like Hardfault) the address of instruction that caused the exception is pushed onto stack at SP+0X18. You can check the symbol table, .map file, and find out which function caused it.

  • Using the picture where it shows the registers,

    then at Memory 0x20032E8, there's the instruction that caused the exception?

    I haven't tried it but won't there be similar instructions?

    For instance, if the instruction was "MOV" at 0x20032E8,

    how could I found that instruction's location?

  • No, you have to look what inside the memory location of where SP is pointing to. That is check the memory contents of 0X200032D0, to the contents add 0X18 (add to the contents of memory location pointed by SP) You just added 0X200032D0+0X18 <-- This is wrong you must do [0X200032D0 + 0X18], then you will get the instruction address that caused the hardfault. you can check where this instruction lies my checking the .map file generated in _build folder

  • Doing it as an answer even though it's not because the comments are restricted to about 2 lines!

    01 00 00 00 in little endian is neither of the above, it's 0x00000001. Anyway that's not where you came from.

    SP is 0x200032D0, so the return PC at exception time is stacked at that +0x18 = 0x200032E8 which has contents 0x00019b5a.

    The link register is 0xFFFFFFF1 which means return to handler, which means you hardfaulted inside an interrupt handler .. but which one.

    The word after the PC is at 0x200032EC and is 0x01000021, that's the PSP. Bit 24 is set telling you you came from Thumb mode, well we knew that. The lower 5 bits are 0x21 which is 33 which is the number of the interrupt being processed. Interrupts start at '1' for the reset handler, the first user interrupt is 16 so this is user interrupt ( 33 - 16 ) = 17. Interrupt 17 is RTC1.

    So it looks like there was something which caused a hardfault inside some code called by the RTC1 interrupt handler (ie I guess a timer) the instruction causing the fault was at 0x00019b5a.

    I'll hazard a wild guess that instruction turns out to be SVC .. see if I'm right.

Related