2021-04-24 05:42 PM
I am writing a bootloader for an STM32L071CB target. In certain cases this code results in a HardFault, but in other cases it works. I know that this alone indicates that it's probably something to do with the state of the rest of my program, but I can't figure out what that is -- specifically, what is the `signal handler` that is called just before the HardFault?
Here is the code causing the problem (`flash_ptr` and `data_ptr` are `uint32_t*` types):
HAL_FLASH_Unlock();
for (i = 0; i < len / sizeof(uint32_t); i++)
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,
(uint32_t)(flash_ptr + i),
*(data_ptr + i));
}
HAL_FLASH_Lock();
As soon as `HAL_FLASH_Program` is entered, I get a HardFault. Specifically, when I step into the function, I get this:
WWDG_IRQHandler ()
at startup_stm32l071xx.S:140
140 b Infinite_Loop
If I write a `HardFault_Handler` then it enters that, so I feel like it's aliasing to WWDG_IRQHandler (WWDG is disabled in my application). So, I have no idea what signal is calling this. Here is the backtrace from GDB when I enter the `HardFault_Handler`:
(gdb) bt
#0 HardFault_Handler () at src/main.c:130
Reading 64 bytes @ address 0x20004C80
Read 4 bytes @ address 0x0800869E (Data = 0x200258F2)
Reading 64 bytes @ address 0x20004CC0
Read 4 bytes @ address 0x08000FDC (Data = 0xD0012800)
Reading 8 bytes @ address 0x2000023E
#1 <signal handler called>
#2 prod_bootload_data (addr=<optimized out>, len=96,
dataptr=dataptr@entry=0x2000023e <_this+10> "")
at src/platform/prod_bootload.c:98
Reading 64 bytes @ address 0x20004D40
Read 4 bytes @ address 0x080012F0 (Data = 0x24002100)
....
Examining those frames is unhelpful:
(gdb) info frame 0
Stack frame at 0x20004c98:
pc = 0x80048a8 in HardFault_Handler (src/main.c:130); saved pc = 0xfffffff9
called by frame at 0x20004cb8
source language c.
Arglist at 0x20004c98, args:
Locals at 0x20004c98, Previous frame's sp is 0x20004c98
(gdb) info frame 1
Stack frame at 0x20004cb8:
pc = 0xfffffff9; saved pc = 0x800869e
called by frame at 0x20004cd0, caller of frame at 0x20004c98
Arglist at unknown address.
Locals at unknown address, Previous frame's sp is 0x20004cb8
Saved registers:
r0 at 0x20004c98, r1 at 0x20004c9c, r2 at 0x20004ca0, r3 at 0x20004ca4,
r12 at 0x20004ca8, lr at 0x20004cac, pc at 0x20004cb0, xpsr at 0x20004cb4
I've tried disabling interrupts, but it makes no difference, so I doubt it is any of the peripherals from my application. I checked the addresses in the program and they look good. All my functions are located in Flash.
Any ideas? Grateful for any tips or ideas.
Solved! Go to Solution.
2021-04-24 06:27 PM
Double check words are erased and addresses properly aligned.
Print out diagnostics
Look at the code (disassembly) that is actually faulting, ie the read, or the write
Look at the content of the saved registers, here showing addresses of those registers on the stack frame. Better yet get your Hard Fault Handler to print actionable data
2021-04-24 06:27 PM
Double check words are erased and addresses properly aligned.
Print out diagnostics
Look at the code (disassembly) that is actually faulting, ie the read, or the write
Look at the content of the saved registers, here showing addresses of those registers on the stack frame. Better yet get your Hard Fault Handler to print actionable data
2021-04-25 03:47 PM
@Community member Thanks so much for these pointers. Turns out the HardFault was being generated because the data that I was passing into HAL_FLASH_Write to be written was not word-aligned!
I have yet to set aside time to understand exactly what lower-level instruction caused this, but I plan to disassemble HAL_FLASH_Write to figure out what the instructions are and if any assume that the inputs need to be word-aligned. I suspect it may be `STR` but we'll see.
I also plan to instrument my HardFault handler for the future as you suggested, perhaps by following this guide: https://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html. Let me know if you were thinking about another approach.
Thanks again!