Skip to main content
Associate
March 25, 2025
Question

Stm32 Hard Fault - PC Address *.map matching

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

This topic has been closed for replies.

6 replies

Associate II
March 25, 2025

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.

 

Pavel A.
March 25, 2025

> Do you use puts() in your code?

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

Associate II
March 25, 2025

@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.

MvA54Author
Associate
March 25, 2025
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?
Associate II
March 25, 2025

@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

 

MvA54Author
Associate
March 27, 2025

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.