Hardfault in __libc_init_array with STM32L072
- January 8, 2021
- 5 replies
- 10545 views
Hi,
I'm working on a STM32L072 project, with an environment composed of arm-none-eabi-gcc compiler version 10-2020-q4, make and Eclipse IDE.
I'm having trouble with a hardfault occuring in libc_init_array function call in startup file. Using disassembly in debug mode, I can see that the instruction that causes the issue is "blx r3" which jumps at address 0x0. At this point, the r3 register value is 0x0.
According to ARM documentation, the blx instruction exchange the instruction set. I've then tried to write the libc_init_array function in my project asI thought maybe the external libc_init_array function used was not compiled with the right instruction set.
Though this does not fix my problem, I am able to see that the jump at 0x0 address is due to callback call using an array of callback named "__init_array_start" that is initialized with 0x0, in the libc_init_array function.
I'm now stuck at this point and don't really know where to look next.
I've looked into the linker file and the map file, I've tried to modify compiler and linker options but without success so far.
Also, the compiler optimization flag is set to -O1. Setting it to -Os prevents from entering the libc_init_array harfault at startup but brings up more issues later. Moreover, using optimization is only a short term solution.
Do you have any idea on what is causing this harfault ?
Below is compiler command line and the linker file of the project:
GCC arguments:
"C:\tools\tlc\tlc.git\0.0.30\..\..\\compilers\gcc.git\10-2020-q4-update/bin/arm-none-eabi-gcc" -mthumb -mcpu=cortex-m0plus -march=armv6-m -static -specs=nano.specs -specs=nosys.specs -specs=rdimon.specs -Wl,--gc-sections -mslow-flash-data -DDEBUG -g3 -gdwarf-2 -TC:/Projects/bsp/STM32/stm32L072.git/0.6.0/src/STM32L072CBTX_FLASH.ld -Wl,-Map,src/out/mapfile.map -o "src/out/application.elf" @./src/out/ObjectFiles.txt -lm
Linker file:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x500; /* required amount of heap */
_Min_Stack_Size = 0x500; /* required amount of stack */
/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
EEPROM (rw) : ORIGIN = 0x8080000, LENGTH = 6K
}
/* Sections */
SECTIONS
{
/* The startup code into "FLASH" Rom type memory */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data into "FLASH" Rom type memory */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data into "FLASH" Rom type memory */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : {
. = ALIGN(4);
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(4);
} >FLASH
.ARM : {
. = ALIGN(4);
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
. = ALIGN(4);
} >FLASH
.preinit_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
} >FLASH
.init_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
} >FLASH
.fini_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >FLASH
/* Used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections into "RAM" Ram type memory */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
*(.RamFunc)
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
SVC_NV_RAM_NB_PAGE = (4); /* set the number of page you want*/
SVC_NV_RAM_PAGE_SIZE = (4096); /* set size of a page, this info is located in the datasheet from the uC*/
SVC_NV_RAM_SIZE = (SVC_NV_RAM_NB_PAGE * SVC_NV_RAM_PAGE_SIZE);
.SVC_NV_RAM_SECTION (ORIGIN(FLASH) + LENGTH(FLASH) - (SVC_NV_RAM_SIZE)) (NOLOAD):
{
/* align data to a page */
. = ALIGN(SVC_NV_RAM_PAGE_SIZE);
*(.SVC_NV_RAM_SECTION)
} >FLASH
/* Uninitialized data section into "RAM" Ram type memory */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
.ARM.attributes 0 : { *(.ARM.attributes) }
}You will also find attached the mapfile.
Thanks for your help.