Hard fault in __libc_init_array
When starting my STM32 makefile project for the first time I encountered a very early hard fault in the startup code. It happened exactly when calling libc function at
The whole startup code came straight from ST so I did not suspect it to be faulty. Here is what I have found out to fix the problem.
I use GNU ARM embedded toolchain so I also did not suspect it to be at fault. At this stage I suspected: startup code, linker script, compilation flags. STM32L151 MCU hit the fault with IBUSERR bit set in CFSR, which means that it was not an ordinary bus fault (wrong memory address being accessed) so it most likely was not the linker script (it also came straight from ST).
A hard fault can also be triggered when the ARM CPU tries to execute invalid instructions (like a wrong jump or trying to treat program data as code). I eventually traced the problem to linker flags. I use
gcc -c to compile
.c files to
.o object files and plain
gcc to link them all into a single executable. The problem happened because
gcc called at compile time did have the correct
-mcpu=cortex-m3 -mthumb flags. The flags make the output binary contain only valid Cortex M3 instructions but
gcc at link time was called with a different set of flags, which did not contain the
-mcpu=cortex-m3 -mthumb flags to
LDFLAGS variable of my boilermake build system the final executable worked fine when executed by the MCU.
It turned out that by default
gcc will link an ARM instructions version of standard library (or probably a version for different Cortex-M than required) and not its Thumb version. Obviously Cortex-M4 code will not work on smaller chips like Cortex-M0+.
Supported versions of the library can be listed by executing
arm-none-eabi-gcc --print-multi-lib and the default settings by
arm-none-eabi-gcc -dumpspecs .