blob: 6cde6a2c354277390d485676fef9c3c97db53732 [file]
/***************************************************************************//**
* GCC Linker script for Silicon Labs devices
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
MEMORY
{
FLASH (rx) : ORIGIN = 0x1008000, LENGTH = 0x389000
RAM (rwx) : ORIGIN = 0x20000100, LENGTH = 0x7ff00
RAM_ALIAS (x) : ORIGIN = 0x800100, LENGTH = 0x7ff00
BOOTLOADER_RESET_REGION (rwx) : ORIGIN = 0x20000000, LENGTH = 0x100
/* Dummy region is used for the dummy segment, which in turn never gets data
* loaded, but is only used to calculate the size of objects placed in it. */
DUMMY (!ax) : ORIGIN = 0xffc77000, LENGTH = 0x389000
}
__flash_size__ = 0x391000;
__flash_page_size__ = 0x1000;
__mspu_region_size__ = 0x8000;
/*******************************************************************************
* Due to an issue in GNU LD, which results in wrongly applying the writeable
* flag to a text section (thereby triggering an error since the memory block is
* declared rx), we need to define our segments manually.
*
* Typical Silicon Labs program layout:
*
* ----- START OF APPLICATION FLASH -----
* R X - TrustZone Secure-to-Nonsecure trampoline app.
* R - Vector table
* R X - RAM functions (copied to RAM at startup)
* R - Read-only data
* R X - Code
* R X - Secure Gateways (Trustzone S only)
* R X - extab
* R X - exidx
* R - startup copy table
* R - startup zeroization table
* RW - Initialised RAM data (copied to RAM at startup)
* - [unallocated space]
* - NVM (defined using linker symbols only, not an ELF section)
* ----- END OF APPLICATION FLASH -----
*
* ----- START OF APPLICATION RAM -----
* RW - Bootloader reset reason (if present)
* RW - stack
* RW - stack sealing
* RW - BSS (zero-init RAM)
* RW - uninitialised RAM
* R X - RAM functions
* RW - Initialised RAM
* RW - Heap (automatically expanded to end of RAM)
* ----- END OF APPLICATION RAM -----
*
* ----- START OF DUMMY REGION -----
* RW - NVM sections (not loadable, only collected such that the linker can
* calculate the size of the symbols placed inside it, to subtract that
* size from the end of the available flash space)
* ----- END OF DUMMY REGION -----
*
* For the purpose of defining segments, we need a new segment whenever the
* data loaded changes type. That means e.g. we need three segments for all RAM
* content: the initial RW segment, the RX segment, and the final RW segment.
******************************************************************************/
PHDRS
{
text_s PT_LOAD FLAGS(5); /* Executable S code (if present) */
vectors PT_LOAD FLAGS(4); /* Flash content before RAM functions is R */
readonly PT_LOAD FLAGS(4); /* Readonly content after RAM functions */
text PT_LOAD FLAGS(5); /* Executable flash content after readonly */
tables PT_LOAD FLAGS(4); /* Tables supporting startup copying are R */
empty PT_LOAD FLAGS(4); /* Empty area is R */
ram_pre_code PT_LOAD FLAGS(6); /* All RAM content before RAMfuncs is RW */
ram_code PT_LOAD FLAGS(5); /* RAMfuncs need to be RX */
ram_data PT_LOAD FLAGS(6); /* Relocatable RAM data needs own segment */
ram_post_data PT_LOAD FLAGS(6); /* All RAM content after data is RW */
btl_data PT_LOAD FLAGS(6); /* Bootloader data is in a separate region */
dummy_seg PT_NULL FLAGS(6); /* Dummy segment for dummy sections */
}
ENTRY(Reset_Handler)
SECTIONS
{
.secure_app :
{
__Secure_Vectors = .;
KEEP(*(.secure_vectors))
KEEP(*(.secure_config_data))
__Secure_Reset_Handler = .;
KEEP(*(.secure_reset_handler))
KEEP(*(.secure_fault_handler))
. = ALIGN(__mspu_region_size__);
} > FLASH :text_s
.vectors :
{
linker_vectors_begin = .;
KEEP(*(.vectors))
linker_vectors_end = .;
__Vectors_End = .;
__Vectors_Size = __Vectors_End - __Vectors;
} > FLASH :vectors
text_ram :
{
. = ALIGN(32);
__vma_ramfuncs_start__ = .;
/* text_application_ram */
*(text_application_ram)
. = ALIGN(4);
/* text_<component>_ram */
__text_system_ram_start__ = .;
*(text_system_*timecritical*)
. = ALIGN(4);
__text_system_ram_end__ = .;
__text_aes_ccm_ram_start__ = .;
*(text_aes_ccm_*security*)
*(text_aes_ccm_*timecritical*)
. = ALIGN(4);
__text_aes_ccm_ram_end__ = .;
__text_aes_common_ram_start__ = .;
*(text_aes_common_*security*)
*(text_aes_common_*timecritical*)
. = ALIGN(4);
__text_aes_common_ram_end__ = .;
__text_clock_manager_ram_start__ = .;
*(text_clock_manager_*timecritical*)
. = ALIGN(4);
__text_clock_manager_ram_end__ = .;
__text_device_peripheral_ram_start__ = .;
*(text_device_peripheral_*timecritical*)
. = ALIGN(4);
__text_device_peripheral_ram_end__ = .;
__text_dma_channel_ram_start__ = .;
*(text_dma_channel_*timecritical*)
. = ALIGN(4);
__text_dma_channel_ram_end__ = .;
__text_dma_manager_ram_start__ = .;
*(text_dma_manager_*timecritical*)
. = ALIGN(4);
__text_dma_manager_ram_end__ = .;
__text_dmadrv_ram_start__ = .;
*(text_dmadrv_*timecritical*)
. = ALIGN(4);
__text_dmadrv_ram_end__ = .;
__text_gpio_ram_start__ = .;
*(text_gpio_*timecritical*)
. = ALIGN(4);
__text_gpio_ram_end__ = .;
__text_hal_common_ram_start__ = .;
*(text_hal_common_*timecritical*)
. = ALIGN(4);
__text_hal_common_ram_end__ = .;
__text_hal_gpio_ram_start__ = .;
*(text_hal_gpio_*timecritical*)
. = ALIGN(4);
__text_hal_gpio_ram_end__ = .;
__text_hal_ldma_ram_start__ = .;
*(text_hal_ldma_*timecritical*)
. = ALIGN(4);
__text_hal_ldma_ram_end__ = .;
__text_hal_sysrtc_ram_start__ = .;
*(text_hal_sysrtc_*timecritical*)
. = ALIGN(4);
__text_hal_sysrtc_ram_end__ = .;
__text_interrupt_manager_ram_start__ = .;
*(text_interrupt_manager_*timecritical*)
. = ALIGN(4);
__text_interrupt_manager_ram_end__ = .;
__text_memlcd_ram_start__ = .;
*(text_memlcd_*timecritical*)
. = ALIGN(4);
__text_memlcd_ram_end__ = .;
__text_memory_manager_ram_start__ = .;
*(text_memory_manager_*timecritical*)
. = ALIGN(4);
__text_memory_manager_ram_end__ = .;
__text_ot_platform_abstraction_ram_start__ = .;
*(text_ot_platform_abstraction_*timecritical*)
. = ALIGN(4);
__text_ot_platform_abstraction_ram_end__ = .;
__text_power_manager_ram_start__ = .;
*(text_power_manager_*timecritical*)
. = ALIGN(4);
__text_power_manager_ram_end__ = .;
__text_rail_lib_ram_start__ = .;
*(text_rail_lib_*timecritical*)
. = ALIGN(4);
__text_rail_lib_ram_end__ = .;
__text_se_manager_ram_start__ = .;
*(text_se_manager_*timecritical*)
. = ALIGN(4);
__text_se_manager_ram_end__ = .;
__text_core_ram_start__ = .;
*(text_core_*timecritical*)
. = ALIGN(4);
__text_core_ram_end__ = .;
__text_sleeptimer_ram_start__ = .;
*(text_sleeptimer_*timecritical*)
. = ALIGN(4);
__text_sleeptimer_ram_end__ = .;
__text_sli_crypto_ram_start__ = .;
*(text_sli_crypto_*timecritical*)
. = ALIGN(4);
__text_sli_crypto_ram_end__ = .;
__text_psec_osal_ram_start__ = .;
*(text_psec_osal_*timecritical*)
. = ALIGN(4);
__text_psec_osal_ram_end__ = .;
__text_sxsymcrypt_ram_start__ = .;
*(text_sxsymcrypt_*timecritical*)
. = ALIGN(4);
__text_sxsymcrypt_ram_end__ = .;
__text_uartdrv_ram_start__ = .;
*(text_uartdrv_*timecritical*)
. = ALIGN(4);
__text_uartdrv_ram_end__ = .;
*libgcc.a:_*.*(.text*)
*libgcc.a:_*.*(.rodata*)
*memset.*(.text*)
*memset.*(.rodata*)
*/link_raw_api.*(.text*)
*/link_raw_api.*(.rodata*)
*/sub_mac.*(.text*)
*/sub_mac.*(.rodata*)
*/factory_diags.*(.text*)
*/factory_diags.*(.rodata*)
*/link_metrics.*(.text*)
*/link_metrics.*(.rodata*)
*/mac.*(.text*)
*/mac.*(.rodata*)
*(text_freertos_kernel_*timecritical*)
. = ALIGN(32);
__vma_ramfuncs_end__ = .;
} > RAM_ALIAS AT > FLASH :ram_code
__lma_ramfuncs_start__ = LOADADDR(text_ram);
__lma_ramfuncs_end__ = LOADADDR(text_ram) + SIZEOF(text_ram);
.rodata :
{
} > FLASH :readonly
.text :
{
linker_code_begin = .;
*(SORT_BY_ALIGNMENT(.text*))
*(SORT_BY_ALIGNMENT(text_*))
. = ALIGN(32);
linker_code_end = .;
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
*(.eh_frame*)
} > FLASH :text
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH :text
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH :text
__exidx_end = .;
.copy.table :
{
. = ALIGN(4);
__copy_table_start__ = .;
LONG (__etext)
LONG (__data_start__)
LONG ((__data_end__ - __data_start__) / 4)
/* Add each additional data section here */
/*
LONG (__etext2)
LONG (__data2_start__)
LONG ((__data2_end__ - __data2_start__) / 4)
*/
__copy_table_end__ = .;
} > FLASH :tables
.zero.table :
{
. = ALIGN(4);
__zero_table_start__ = .;
/* Add each additional bss section here */
/*
LONG (__bss2_start__)
LONG ((__bss2_end__ - __bss2_start__) / 4)
*/
__zero_table_end__ = .;
} > FLASH :tables
.bootloader_reset_section (NOLOAD):
{
__ResetReasonStart__ = .;
KEEP(*(.bootloader_reset_section))
} > BOOTLOADER_RESET_REGION :btl_data
text_ram_vma (NOLOAD):
{
/* Offset the location counter to account for RAM code that was placed in
the aliased RAM region.
*/
. += (__vma_ramfuncs_end__ - __vma_ramfuncs_start__);
} > RAM :ram_pre_code
.stack (NOLOAD):
{
. = ALIGN(8);
__stack_limit = .;
__StackLimit = .;
KEEP(*(.stack*))
. = ALIGN(4);
__stack = .;
__StackTop = .;
} > RAM :ram_pre_code
.noinit (NOLOAD):
{
__noinit_start__ = .;
*(.noinit*);
__noinit_end__ = .;
} > RAM :ram_pre_code
vector_table_ram (NOLOAD):
{
linker_vectors_ram_begin = .;
KEEP(*(.vector_table_ram))
linker_vectors_ram_end = .;
} > RAM :ram_pre_code
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
*(SORT_BY_ALIGNMENT(.bss*))
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM :ram_pre_code
.data :
{
*(vtable)
*(SORT_BY_ALIGNMENT(.data*))
. = ALIGN(4);
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
/* Shareable data sections here */
__start_shareable = .;
*(.rail_shareable)
/* Add each additional shareable sections here */
__stop_shareable = .;
. = ALIGN(4);
*(SEGGER_RTT)
. = ALIGN(4);
/* All data end */
} > RAM AT > FLASH :ram_data
/* Values to support copying initialised values at startup */
__etext = LOADADDR(.data);
__data_start__ = ADDR(.data);
__data_end__ = ADDR(.data) + SIZEOF(.data);
ASSERT((__etext % 4) == 0, "Data section needs to be word-aligned in LMA")
ASSERT((__data_start__ % 4) == 0, "Data section needs to be word-aligned in VMA")
ASSERT((__data_end__ % 4) == 0, "Data section needs to be word-multiple sized")
.code_flash_end : {
code_flash_end = .;
} > FLASH :empty
/* Calculate heap size based on RAM limits. */
heap_limit = ORIGIN(RAM) + LENGTH(RAM); /* End of RAM */
heap_size = heap_limit - __HeapBase;
.memory_manager_heap (NOLOAD):
{
. = ALIGN(8);
__HeapBase = .;
. += heap_size;
__end__ = .;
_end = __end__;
KEEP(*(.memory_manager_heap*))
__HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
} > RAM :ram_post_data
__ram_end__ = 0x20000100 + 0x7ff00;
__main_flash_end__ = 0x1008000 + 0x389000;
/* This is where we handle flash storage blocks. We use dummy sections for finding the configured
* block sizes and then "place" them at the end of flash when the size is known. */
.internal_storage (NOLOAD) : {
KEEP(*(.internal_storage*))
} > DUMMY :dummy_seg
.nvm (NOLOAD) : {
KEEP(*(.simee*))
} > DUMMY :dummy_seg
__ramfuncs_start__ = ORIGIN(RAM) + (__vma_ramfuncs_start__ - ORIGIN(RAM_ALIAS));
__ramfuncs_end__ = ORIGIN(RAM) + (__vma_ramfuncs_end__ - ORIGIN(RAM_ALIAS));
/* Static secure tokens reserve flash memory at the end of the flash */
linker_static_secure_tokens_end = __main_flash_end__;
linker_static_secure_tokens_begin = linker_static_secure_tokens_end - 0x2000;
linker_nvm_end = linker_static_secure_tokens_begin;
linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm);
linker_storage_end = linker_nvm_begin;
__nvm3Base = linker_nvm_begin;
linker_storage_begin = linker_storage_end - SIZEOF(.internal_storage);
ASSERT((linker_storage_begin >= (__etext + SIZEOF(.data))), "FLASH memory overflowed !")
HIDDEN(app_flash_end = 0x1008000 + 0x389000);
ASSERT( (linker_nvm_begin + SIZEOF(.nvm)) <= linker_static_secure_tokens_begin, "NVM3 is excessing the flash size !")
ASSERT( (linker_static_secure_tokens_begin + 0x2000) <= app_flash_end, "Static secure storage is exceeding the flash size !")
ASSERT( code_flash_end - 0x1008000 <= 0x1f0000, "Code size exceeds code region 1 capacity. Flash partitions can be reconfigured: https://docs.silabs.com/gecko-platform/latest/flash-partitions-series3/")
}