I'm working with an STM32H7 microcontroller and encountered a Hard Fault during the startup sequence while copying data from Flash to RAM (specifically to ITCM and DTCM sections). This issue arises under specific conditions related to the presence (or absence) of data in these memory regions, as well as their ordering in the linker script.
Linker Script Configuration:
My linker script segments are ordered as follows:
SECTIONS
{
.isr_vector :
{
. = ALIGN(8);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(8);
} >FLASH
/* DTCM --------------------------------------------------------------------*/
/* Used by the startup to initialize dtcm */
_siDTCM = LOADADDR(.dtcm_data);
/* Uninitialized dtcm sections into "DTCM" Ram type memory */
.dtcm_data :
{
. = ALIGN(8);
_sdtcm = .; /* Create a symbol marking the start of the DTCM data */
*(.dtcm_data) /* Place the data in the .dtcm section here */
*(.dtcm_data*) /* Place the data* in the .dtcm section here */
. = ALIGN(8);
_edtcm = .; /* Mark the end of the DTCM data */
} >DTCMRAM AT> FLASH
/* ITCM --------------------------------------------------------------------*/
/* Used by the startup to initialize data */
_siITCM = LOADADDR(.itcmram);
/* Text section into "ITCM" Ram type memory */
.itcmram :
{
. = ALIGN(8);
_sitcm = .; /* Create a symbol marking the start of the ITCM data */
*(.itcmFunc) /* Place the itcmFunc in the .itcm section here */
*(.itcmFunc*) /* Place the itcmFunc* in the .itcm section here */
. = ALIGN(8);
_eitcm = .; /* Mark the end of the ITCM data */
} >ITCMRAM AT> FLASH
/* FLASH -------------------------------------------------------------------*/
/* The program code and other data into "FLASH" Rom type memory */
.text :
{
. = ALIGN(8);
*(.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(8);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data into "FLASH" Rom type memory */
.rodata :
{
. = ALIGN(8);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(8);
} >FLASH
...
}
Startup Routine:
The startup code copies initialized data from Flash to ITCM and DTCM. It functions correctly when there's data within these sections. However, it leads to a Hard Fault when these sections are empty:
/* Copy the data segment initializers from flash to ITCM SRAM */
ldr r0, =_sitcm
ldr r1, =_eitcm
ldr r2, =_siITCM
movs r3, #0
movs r4, #0
b LoopCopyItcmInit
CopyItcmInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyItcmInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyItcmInit
/* Copy the data segment initializers from flash to DTCM SRAM */
ldr r0, =_sdtcm
ldr r1, =_edtcm
ldr r2, =_siDTCM
movs r3, #0
movs r4, #0
b LoopCopyDtcmInit
CopyDtcmInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyDtcmInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyDtcmInit
Observations and Question:
The system does not encounter a Hard Fault when the .dtcm_data and .itcmram sections have data. A Hard Fault occurs during the "Copy Data Loop" if .dtcm_data and .itcmram are empty. Rearranging the linker script to place .dtcm_data and .itcmram sections under the .text section resolves the issue, suggesting that the section order might impact the behavior. My questions are:
- Why does the startup code result in a Hard Fault when attempting to copy from empty .dtcm_data and .itcmram sections? How does rearranging these sections to follow the .text section in the linker script prevent the Hard Fault? (Below rearrangement of sections does solve)
.isr_vector : { ... } >FLASH
.text : { ... } >FLASH
.dtcm_data : { *(.dtcm_data) *(.dtcm_data*) } >DTCMRAM AT> FLASH
.itcmram : { *(.itcmram) *(.itcmram*) } >ITCMRAM AT> FLASH
...
- Does the order of sections in a linker script influence the initialization behavior or memory allocation in a way that's significant here?
- Can anyone explain or provide insights into this behavior?