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.