Skip to main content
Associate
March 25, 2025
Question

Stm32 Hard Fault - PC Address *.map matching

  • March 25, 2025
  • 2 replies
  • 797 views

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

2 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.
Super User
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.