1.3.3.2 SPI Bootloader Linker Configurations for Cortex-M Based MCUs
Linker configurations for SPI Bootloader
-
Bootloader library uses a custom linker script which is generated through MCC
-
The values populated in the linker script are based on the Bootloader component MCC configurations
-
Bootloader is configured to run from RAM to allow updating the bootloader firmware as well
Note: The below sections provides overview of changes done to bootloader linker scripts when compared to default linker script. The <bootloader_start> address and <bootloader_length> may vary based on the specific device used.
#define ROM_START <bootloader_start> /* Bootloader size is calculated with below criteria with optimization level -O2 * bootloader size = Minimum Flash Erase Size Or actual bootloader ELF size (Rounded of to nearest erase boundary) whichever is greater. */ #define ROM_SIZE <bootloader_length> /* Bootloader Trigger pattern needs to be stored in starting <trigger_len> Bytes * of Ram by the application if it wants to run bootloader at startup without any * external trigger. * Example: * ram[0] = 0x5048434D; * ram[1] = 0x5048434D; * .... * ram[n] = 0x5048434D; */ #define RAM_START (<ram_start> + <trigger_len>) #define RAM_SIZE (<ram_length> - trigger_len) MEMORY { rom (rx) : ORIGIN = ROM_START, LENGTH = ROM_SIZE ram (rwx) : ORIGIN = RAM_START, LENGTH = RAM_SIZE }
Refer the below linker script changes if the RAM pattern based bootloader trigger is disabled in MCC:
SECTIONS
{
/*
* Configure to place the vector table in Flash but to be run from RAM
*/
.vectors :
{
_sfixed = .; /* RAM address where the vector table from flash will be copied. This will be used by C startup code to copy vector table into RAM*/
KEEP(*(.vectors .vectors.*))
} > ram AT > rom
_vectors_loadaddr = LOADADDR(.vectors); /* Start address of vector table in flash. This will be used by C startup code to copy vector table into RAM */
.text : /* The startup code is linked to run from the ROM (flash) memory */
{
. = ALIGN(4);
....
....
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
....
....
. = ALIGN(4);
_etext = .; /* Starting address in flash from where the bootloader code will be copied into RAM by the C startup code */
/* Locate text/rodata in special data section to be copied to RAM
in startup sequence. */
.data :
{
. = ALIGN(4);
__data_start__ = .;
_sdata = .; /* Starting address in RAM where the bootloader code will be copied by the C startup code*/
*(.dinit)
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
. = ALIGN(4);
__data_end__ = .;
_edata = .; /* End address in RAM after the bootloader code is copied */
} > ram AT > rom
....
}
Refer the below linker script changes if the RAM pattern based bootloader trigger is enabled in MCC:
SECTIONS
{
/*
* Configure to place the vector table in Flash but to be run from RAM.
* When RAM pattern based trigger is enabled, first few bytes in RAM are reserved for the pattern. As a result, an offset of 1024 bytes is addded from the * start location of RAM to satisfy the alignment needs of vector table in Cortex M based MCUs. For example, if the RAM start address is 0x2000000 and the * trigger length is set to 16 bytes, then the RAM_START macro will be set to 0x2000016, and the vector table will be copied from RAM_START - <trigger_len> * + 0x400 which evaluates to 0x2000016 - 16 + 0x400 = 0x2000400.
*/
.vectors RAM_START - <trigger_len> + 0x400:
{
_sfixed = .; /* RAM address where the vector table from flash will be copied. This will be used by C startup code to copy vector table into RAM*/
KEEP(*(.vectors .vectors.*))
} > ram AT > rom
_vectors_loadaddr = LOADADDR(.vectors); /* Start address of vector table in flash. This will be used by C startup code to copy vector table into RAM */
.text : /* The startup code is linked to run from the ROM (flash) memory */
{
. = ALIGN(4);
....
....
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
....
....
. = ALIGN(4);
_etext = .; /* Starting address in flash from where the bootloader code will be copied into RAM by the C startup code */
/* Locate text/rodata in special data section to be copied to RAM
in startup sequence. */
.data :
{
. = ALIGN(4);
__data_start__ = .;
_sdata = .; /* Starting address in RAM where the bootloader code will be copied by the C startup code*/
*(.dinit)
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
. = ALIGN(4);
__data_end__ = .;
_edata = .; /* End address in RAM after the bootloader code is copied */
} > ram AT > rom
....
}
Custom startup file for UART, I2C and CAN Bootloaders
-
To reduce the size of the binary these bootloaders make use of custom startup file which is generated by MCC
-
The startup code copies .vector section from Flash to RAM and relocates the vector table to RAM by updating the VTOR register
-
The startup file also copies the entire bootloader code placed in .data section above from Flash to RAM as it is built to run from RAM
/* Declaration of Reset handler (may be custom) */ /* Initialize segments */ extern uint32_t _sfixed; extern void _ram_end_(void); extern int main(void); /** * \brief This is the code that gets called on processor reset. * To initialize the device, and call the main() routine. */ /* Linker-defined symbols for data initialization. */ extern uint32_t _sdata, _edata, _etext; extern uint32_t _sbss, _ebss; extern uint32_t _vectors_loadaddr; void __attribute__((noinline, section(".romfunc.Reset_Handler"))) Reset_Handler(void) { uint32_t *pSrc, *pDst; uint32_t i; pSrc = (uint32_t *) &_vectors_loadaddr; /* flash address */ pDst = (uint32_t *) &_sfixed; /* Copy .vectors section from flash to RAM */ for (i = 0; i < sizeof(H3DeviceVectors)/4; i++) { *pDst++ = *pSrc++; } pSrc = (uint32_t *) &_etext; /* flash functions start after .text */ pDst = (uint32_t *) &_sdata; /* boundaries of .data area to init */ /* Init .data */ while (pDst < &_edata) *pDst++ = *pSrc++; /* Init .bss */ pDst = &_sbss; while (pDst < &_ebss) *pDst++ = 0; #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) /* Set the vector-table base address in RAM */ pSrc = (uint32_t *) & _sfixed; SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk); #endif /* #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) */ /* Branch to application's main function */ main(); #if (defined(__DEBUG) || defined(__DEBUG_D)) && defined(__XC32) __builtin_software_breakpoint(); #endif }
MPLAB X Setting for SPI Bootloader
-
Below MPLAB X option is enabled by MCC for these bootloaders to remove the XC32 crt0 startup code
-
By disabling this crt0 startup code the size is further reduced as it removes the default initialization code by XC32
