cancel
Showing results for 
Search instead for 
Did you mean: 

Stm32 Hard Fault - PC Address *.map matching

MvA54
Associate II

Hello,

Hard Fault Handler Code:
To capture the details of the Hard Fault, I’m using the following handler:
void HardFault_Handler(void)
{
    __asm volatile
    (
        "TST lr, #4 \n"
        "ITE EQ \n"
        "MRSEQ r0, MSP \n"
        "MRSNE r0, PSP \n"
        "B hard_fault_handler_c \n"
    );
}

void hard_fault_handler_c(unsigned int *hardfault_args)
{
    unsigned int stacked_r0 = hardfault_args[0];
    unsigned int stacked_r1 = hardfault_args[1];
    unsigned int stacked_r2 = hardfault_args[2];
    unsigned int stacked_r3 = hardfault_args[3];
    unsigned int stacked_r12 = hardfault_args[4];
    unsigned int stacked_lr = hardfault_args[5];
    unsigned int stacked_pc = hardfault_args[6];
    unsigned int stacked_psr = hardfault_args[7];

    printf("\n[HardFault] Hata!\n");
    printf("R0  = 0x%08X\n", stacked_r0);
    printf("R1  = 0x%08X\n", stacked_r1);
    printf("R2  = 0x%08X\n", stacked_r2);
    printf("R3  = 0x%08X\n", stacked_r3);
    printf("R12 = 0x%08X\n", stacked_r12);
    printf("LR  = 0x%08X\n", stacked_lr);
    printf("PC  = 0x%08X\n", stacked_pc);  
    printf("PSR = 0x%08X\n", stacked_psr);

    while (1);
}


I'm getting hard fault in my STM32L4XX project. The output is:

[HardFault]!  
R0  = 0x2000FFE8  
R1  = 0x0000000A  
R2  = 0x00000040  
R3  = 0x00000002  
R12 = 0x00000000  
LR  = 0x00000000  
PC  = 0x0800656F  
PSR = 0x08000EEC  

 

Problem: The PC address 0x0800656F shows where the error occurs. I checked the *.map file but couldn’t figure out which function it corresponds to. Where might I be going wrong? How can I match this address with the *.map file?

The *.map file is inside the zip

6 REPLIES 6
krotti42
Associate III

Hi @MvA54 !

 

I have investigated your attached *.map file.

Seems the hard fault is triggered in the libc (libc_nano.a) function _puts_r():

  .text._puts_r  0x08006520       0xaa C:/ST/STM32CubeIDE_1.14.1/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.13.3.rel1.win32_1.0.0.202411081344/tools/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc_nano.a(libc_a-puts.o)
                0x08006520                _puts_r
 *fill*         0x080065ca        0x2 
 .text.puts     0x080065cc       0x10 C:/ST/STM32CubeIDE_1.14.1/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.13.3.rel1.win32_1.0.0.202411081344/tools/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc_nano.a(libc_a-puts.o)
                0x080065cc                puts

Do you use puts() in your code? Because puts() calls _puts_r() according the newlib sources.

 

Do you use puts() in your code?

GCC compiler converts printf calls  with one argument to puts. So it could be a printf.


@Pavel A. wrote:

Do you use puts() in your code?

GCC compiler converts printf calls  with one argument to puts. So it could be a printf.


Yes that's true. Have forgotten to write that.

MvA54
Associate II
Here, I’m intentionally dividing a uint8_t value by zero inside the APP_Test_Init function, causing a Hard Fault.
When I examine the *.map file, shouldn’t I be able to see the APP_Test_Init function?

@MvA54 wrote:
Here, I’m intentionally dividing a uint8_t value by zero inside the APP_Test_Init function, causing a Hard Fault.
When I examine the *.map file, shouldn’t I be able to see the APP_Test_Init function?

Dividing by zero should "normally" generate an usage fault on the ARMv7-M architecture, not a hard fault.

You can read this in the ARMv7-M TRM:UDIVUDIVUsageFault raised by UDIVUsageFault raised by UDIV

Because when I try to divide by zero in C:

int test(unsigned char a)
{
    return a / 0;
}

GCC use UDIV for the calculation in the resulting object file:

test.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <test>:
   0:   b480            push    {r7}
   2:   b083            sub     sp, #12
   4:   af00            add     r7, sp, #0
   6:   4603            mov     r3, r0
   8:   71fb            strb    r3, [r7, #7]
   a:   79fb            ldrb    r3, [r7, #7]
   c:   2200            movs    r2, #0
   e:   fbb3 f3f2       udiv    r3, r3, r2
  12:   b2db            uxtb    r3, r3
  14:   4618            mov     r0, r3
  16:   370c            adds    r7, #12
  18:   46bd            mov     sp, r7
  1a:   bc80            pop     {r7}
  1c:   4770            bx      lr

 

Hmm, the kit I used for the test is the Nucleo L32KC kit.
I triggered a hard fault using a different method now.

void APP_Test_Init(void)
{
	void (*invalid_func)(void) = (void (*)(void))0xDEADBEEF; // An invalid address
	invalid_func();// This call causes Hard Fault
}

And the log output is as follows:

[HardFault]!
R0  = 0x2000FFE8
R1  = 0x00000000
R2  = 0x00400000
R3  = 0x00000000
R12 = 0xDEADBEEF
LR  = 0x00000000
PC  = 0x08000EE3
PSR = 0xDEADBEEE

I still couldn't analyze it in the *.map file.
I'm attaching the *.map file again.