2024-05-14 03:27 AM - edited 2024-05-14 05:01 AM
Hi amazing community.
I am developing a custom bootloader for stm32f429 .
I have touched the linker file that i show here
******************************************************************************
**
** @file : LinkerScript.ld
**
** @author : Auto-generated by STM32CubeIDE
**
** @brief : Linker script for STM32F429ZITx Device from STM32F4 series
** 2048Kbytes FLASH
** 64Kbytes CCMRAM
** 192Kbytes RAM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used
**
** Target : STMicroelectronics STM32
**
** Distribution: The file is distributed as is, without any warranty
** of any kind.
**
******************************************************************************
** @attention
**
** Copyright (c) 2023 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
** in the root directory of this software component.
** If no LICENSE file comes with this software, it is provided AS-IS.
**
******************************************************************************
*/
/* 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 = 0x400; /* required amount of heap */
_Min_Stack_Size = 0x800; /* required amount of stack */
_BOOTL_HEADER_OFFSET = 0x00004000; /* spazio riservato a .isr_vector, prima di bootl_header */
/* Memories definition */
MEMORY
{
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K-4
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64k
}
/* Sections */
SECTIONS
{
/* The startup code into "FLASH" Rom type memory */
.isr_vector :
{
. = ALIGN(4);
_bootl_fw_start = .;
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* Bootloader Header */
/* It will start from _BOOTL_HEADER_OFFSET */
/* see: http://www.openstm32.org/forumthread6870 */
/* https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Using_ld_the_GNU_Linker/expressions.html */
.bootl_header :
. = _bootl_fw_start + _BOOTL_HEADER_OFFSET;
KEEP(*(.bootl_header)) /* Bootloader Header */
. = 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) /* .RamFunc sections */
*(.RamFunc*) /* .RamFunc* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
_siccmram = LOADADDR(.ccmram);
/* CCM-RAM section
*
* IMPORTANT NOTE!
* If initialized variables will be placed in this section,
* the startup code needs to be modified to copy the init-values.
*/
.ccmram :
{
. = ALIGN(4);
_sccmram = .; /* create a global symbol at ccmram start */
*(.ccmram)
*(.ccmram*)
. = ALIGN(4);
_eccmram = .; /* create a global symbol at ccmram end */
} >CCMRAM AT> 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
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
The idea it is to have the following memory map
* Per il micro STM32F429 -
* ------------------------------------------
*
|----------------------------------------------------------------------------|---------------------------------------------------------------
| FLASH (2048K) |
|----------------------------------------------------------------------------|
| | 0x08000000 |
| | |
| 16K | Bootloader Section |
| | |
|-------------------------- -|-----------------------------------------------|
| | 0x08004000 | Bootloader 64k
| 16K | |
| | Bootloader Header (.bl_header) |
| | |
| | |
------------------------------------------------------------------------------
| 16k --- |
| |
| |
-------------------------------------------------------------------------------------------------------------------------------------------
| | 0x08010000 |
| | |
| 64k | Application Section |
| | |
| |-----------------------------------------------|
| | |
| | Startup Code (.isr_vector) |
| | |
|--------------------------- |-----------------------------------------------|
| 128k... | 0x08020000 |
| | |
| | Application Header (.app_header) |
| | | app 2048-64k
| |-----------------------------------------------|
| | |
| | Program Code (.text) |
| | |
| |-----------------------------------------------|
| | |
| | Constant Data (.rodata) |
| | |
| |-----------------------------------------------|
| | |
| | ARM Exception Handling (.ARM) |
| | |
|----------------------------------------------------------------------------|------------------------------------------------------------
Now i am working on the bootloader project but when i click on debug after the reset handler i have immediatly the hardware fault problem
Do you see any issues ?
Thans a lot
2024-05-14 11:58 AM
Hardware fault? Do you mean HardFault? Would you like to use the fault analyzer of the CubeIDE debugger and share the results?
2024-05-14 02:22 PM - edited 2024-05-14 02:25 PM
This seems unnecessarily clumsy..
Make TWO scripts, one for the LOADER and one for the APPLICATION. The concept being you can replace one or the other, ie update the Application.
Base the application one at 0x08020000 in the MEMORY definitions.
Each will have it's own Vector Table, and you'll point SCB->VTOR at the one for the current project via SystemInit()
Have your HardFault_Handler() in each provide details on the failure so you can track it down in your code.
Use symbols or pointer to reference other things, you don't need to build them into the structure of the object file for the loader.
2024-05-14 10:23 PM
My five cents:
Do you have a bootloader flashed?
Is this bootloader working? (does it jump at the end to your user code?)
Yes, there is a need for SCB->VTOR, but who will do this? (relocation of vector table), the bootloader or your code?
I am not sure, but I think:
I could imagine this:
Check the SP, PC and LR registers when it crashes: it might give you a clue what went wrong.
2024-05-16 11:36 PM - edited 2024-05-17 02:35 AM
Hi @tjaekel .
Yes the bootloader was missing but now i have imported moreover the starting ram address was wrong .
Moreover i added the following instructions
/*vector table remap*/
static void VetcorTblRemap(void)
{
/*vector table re map*/
SCB->VTOR = (uint32_t)&g_pfnVectors;
__enable_irq();
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
VetcorTblRemap();
/* USER CODE END 1 */
and now the code at least it is working.
But the interrupts are not working anymore and i don't understand why.
This is the updated linker file
/*
******************************************************************************
**
** @file : LinkerScript.ld
**
** @author : Auto-generated by STM32CubeIDE
**
** @brief : Linker script for STM32F429ZITx Device from STM32F4 series
** 2048Kbytes FLASH
** 64Kbytes CCMRAM
** 192Kbytes RAM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used
**
** Target : STMicroelectronics STM32
**
** Distribution: The file is distributed as is, without any warranty
** of any kind.
**
******************************************************************************
** @attention
**
** Copyright (c) 2023 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
** in the root directory of this software component.
** If no LICENSE file comes with this software, it is provided AS-IS.
**
******************************************************************************
*/
/* 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 = 0x400; /* required amount of heap */
_Min_Stack_Size = 0x800; /* required amount of stack */
_BOOTLDR_OFFSET = 0x00000000;
_APP_START_OFFSET = 0x00010000;
_APP_HEADER_OFFSET = 0x00010000;
/* Memories definition */
MEMORY
{
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K-4
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
}
/* Sections */
SECTIONS
{
/* The bootloader code into "FLASH" Rom type memory */
.bootloader_section :
{
. = ALIGN(4);
_bl_fw_start = .;
KEEP(*(.bootloader_section)) /* Bootloader */
. = ALIGN(4);
} > FLASH
/* The startup code into "FLASH" Rom type memory */
.isr_vector :
{
. = _bl_fw_start + _APP_START_OFFSET;
_app_fw_start = .;
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} > FLASH
.app_header :
{
. = _bl_fw_start + _APP_START_OFFSET + _APP_HEADER_OFFSET;
KEEP(*(.app_header)) /* Bootloader Header */
. = 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) /* .RamFunc sections */
*(.RamFunc*) /* .RamFunc* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
_siccmram = LOADADDR(.ccmram);
/* CCM-RAM section
*
* IMPORTANT NOTE!
* If initialized variables will be placed in this section,
* the startup code needs to be modified to copy the init-values.
*/
.ccmram :
{
. = ALIGN(4);
_sccmram = .; /* create a global symbol at ccmram start */
*(.ccmram)
*(.ccmram*)
. = ALIGN(4);
_eccmram = .; /* create a global symbol at ccmram end */
} >CCMRAM AT> 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
.app_trailer :
{
. = ALIGN(16);
_app_trailer = .;
KEEP(*(.app_trailer)) /* Application Trailer */
. = ALIGN(4);
_app_fw_end = .;
} >FLASH
_app_fw_size = _app_fw_end - _app_fw_start;
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
and this is the memory map from cube ide (current situation)
and this is what i want to obtain
*
|----------------------------------------------------------------------------|---------------------------------------------------------------
| FLASH (2048K) |
|----------------------------------------------------------------------------|
| | 0x08000000 |
| | |
| 16K | Bootloader Section |
| | |
|-------------------------- -|-----------------------------------------------|
| | 0x08004000 | Bootloader 64k
| 16K | |
| | Bootloader Header (.bl_header) |
| | |
| | |
------------------------------------------------------------------------------
| 16k --- |
| |
| |
-------------------------------------------------------------------------------------------------------------------------------------------
| | 0x08010000 |
| | |
| 64k | Application Section |
| | |
| |-----------------------------------------------|
| | |
| | Startup Code (.isr_vector) |
| | |
|--------------------------- |-----------------------------------------------|
| 128k... | 0x08020000 |
| | |
| | Application Header (.app_header) |
| | | app 2048-64k
| |-----------------------------------------------|
| | |
| | Program Code (.text) |
| | |
| |-----------------------------------------------|
| | |
| | Constant Data (.rodata) |
| | |
| |-----------------------------------------------|
| | |
| | ARM Exception Handling (.ARM) |
| | |
|----------------------------------------------------------------------------|------------------------------------------------------------
Moreover i don't understand why the e-stack value is that one underlined instead an address inside
ram starting at 0x2000..
really don't understand why any interrupts is not working anymore.
INterrupt vector table is set correctly ?
Can you check ?
Thanks a lot for your help