1/* 2 * Copyright 2020 The Pigweed Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17/* This relatively simplified linker script will work with many ARMv7-M cores 18 * that have on-board memory-mapped RAM and FLASH. For more complex projects and 19 * devices, it's possible this linker script will not be sufficient as-is. 20 * 21 * This linker script is likely not suitable for a project with a bootloader. 22 */ 23 24/* Provide useful error messages when required configurations are not set. */ 25#ifndef PW_BOOT_VECTOR_TABLE_BEGIN 26#error "PW_BOOT_VECTOR_TABLE_BEGIN is not defined, and is required to use pw_boot_armv7m" 27#endif // PW_BOOT_VECTOR_TABLE_BEGIN 28 29#ifndef PW_BOOT_VECTOR_TABLE_SIZE 30#error "PW_BOOT_VECTOR_TABLE_SIZE is not defined, and is required to use pw_boot_armv7m" 31#endif // PW_BOOT_VECTOR_TABLE_SIZE 32 33#ifndef PW_BOOT_FLASH_BEGIN 34#error "PW_BOOT_FLASH_BEGIN is not defined, and is required to use pw_boot_armv7m" 35#endif // PW_BOOT_FLASH_BEGIN 36 37#ifndef PW_BOOT_FLASH_SIZE 38#error "PW_BOOT_FLASH_SIZE is not defined, and is required to use pw_boot_armv7m" 39#endif // PW_BOOT_FLASH_SIZE 40 41#ifndef PW_BOOT_RAM_BEGIN 42#error "PW_BOOT_RAM_BEGIN is not defined, and is required to use pw_boot_armv7m" 43#endif // PW_BOOT_RAM_BEGIN 44 45#ifndef PW_BOOT_RAM_SIZE 46#error "PW_BOOT_RAM_SIZE is not defined, and is required to use pw_boot_armv7m" 47#endif // PW_BOOT_RAM_SIZE 48 49#ifndef PW_BOOT_HEAP_SIZE 50#error "PW_BOOT_HEAP_SIZE is not defined, and is required to use pw_boot_armv7m" 51#endif // PW_BOOT_HEAP_SIZE 52 53#ifndef PW_BOOT_MIN_STACK_SIZE 54#error "PW_BOOT_MIN_STACK_SIZE is not defined, and is required to use pw_boot_armv7m" 55#endif // PW_BOOT_MIN_STACK_SIZE 56 57 58/* Note: This technically doesn't set the firmware's entry point. Setting the 59 * firmware entry point is done by setting vector_table[1] 60 * (Reset_Handler). However, this DOES tell the compiler how to optimize 61 * when --gc-sections is enabled. 62 */ 63ENTRY(pw_boot_Entry) 64 65MEMORY 66{ 67 /* TODO(pwbug/57): Make it possible for projects to freely customize 68 * memory regions. 69 */ 70 71 /* Vector Table (typically in flash) */ 72 VECTOR_TABLE(rx) : \ 73 ORIGIN = PW_BOOT_VECTOR_TABLE_BEGIN, \ 74 LENGTH = PW_BOOT_VECTOR_TABLE_SIZE 75 /* Internal Flash */ 76 FLASH(rx) : \ 77 ORIGIN = PW_BOOT_FLASH_BEGIN, \ 78 LENGTH = PW_BOOT_FLASH_SIZE 79 /* Internal SRAM */ 80 RAM(rwx) : \ 81 ORIGIN = PW_BOOT_RAM_BEGIN, \ 82 LENGTH = PW_BOOT_RAM_SIZE 83} 84 85SECTIONS 86{ 87 /* This is the link-time vector table. If used, the VTOR (Vector Table Offset 88 * Register) MUST point to this memory location in order to be used. This can 89 * be done by ensuring this section exists at the default location of the VTOR 90 * so it's used on reset, or by explicitly setting the VTOR in a bootloader 91 * manually to point to &pw_boot_vector_table_addr before interrupts are enabled. 92 */ 93 .vector_table : ALIGN(512) 94 { 95 pw_boot_vector_table_addr = .; 96 KEEP(*(.vector_table)) 97 } >VECTOR_TABLE 98 99 /* Main executable code. */ 100 .code : ALIGN(8) 101 { 102 . = ALIGN(8); 103 /* Application code. */ 104 *(.text) 105 *(.text*) 106 KEEP(*(.init)) 107 KEEP(*(.fini)) 108 109 . = ALIGN(8); 110 /* Constants.*/ 111 *(.rodata) 112 *(.rodata*) 113 114 /* .preinit_array, .init_array, .fini_array are used by libc. 115 * Each section is a list of function pointers that are called pre-main and 116 * post-exit for object initialization and tear-down. 117 * Since the region isn't explicitly referenced, specify KEEP to prevent 118 * link-time garbage collection. SORT is used for sections that have strict 119 * init/de-init ordering requirements. */ 120 . = ALIGN(8); 121 PROVIDE_HIDDEN(__preinit_array_start = .); 122 KEEP(*(.preinit_array*)) 123 PROVIDE_HIDDEN(__preinit_array_end = .); 124 125 PROVIDE_HIDDEN(__init_array_start = .); 126 KEEP(*(SORT(.init_array.*))) 127 KEEP(*(.init_array*)) 128 PROVIDE_HIDDEN(__init_array_end = .); 129 130 PROVIDE_HIDDEN(__fini_array_start = .); 131 KEEP(*(SORT(.fini_array.*))) 132 KEEP(*(.fini_array*)) 133 PROVIDE_HIDDEN(__fini_array_end = .); 134 } >FLASH 135 136 /* Used by unwind-arm/ */ 137 .ARM : ALIGN(8) { 138 __exidx_start = .; 139 *(.ARM.exidx*) 140 __exidx_end = .; 141 } >FLASH 142 143 /* Explicitly initialized global and static data. (.data)*/ 144 .static_init_ram : ALIGN(8) 145 { 146 *(.data) 147 *(.data*) 148 . = ALIGN(8); 149 } >RAM AT> FLASH 150 151 /* Zero initialized global/static data. (.bss) 152 * This section is zero initialized in pw_boot_Entry(). */ 153 .zero_init_ram : ALIGN(8) 154 { 155 *(.bss) 156 *(.bss*) 157 *(COMMON) 158 . = ALIGN(8); 159 } >RAM 160 161 .heap : ALIGN(8) 162 { 163 pw_boot_heap_low_addr = .; 164 . = . + PW_BOOT_HEAP_SIZE; 165 . = ALIGN(8); 166 pw_boot_heap_high_addr = .; 167 } >RAM 168 169 /* Link-time check for stack overlaps. */ 170 .stack (NOLOAD) : ALIGN(8) 171 { 172 /* Set the address that the main stack pointer should be initialized to. */ 173 pw_boot_stack_low_addr = .; 174 HIDDEN(_stack_size = ORIGIN(RAM) + LENGTH(RAM) - .); 175 /* Align the stack to a lower address to ensure it isn't out of range. */ 176 HIDDEN(_stack_high = (. + _stack_size) & ~0x7); 177 ASSERT(_stack_high - . >= PW_BOOT_MIN_STACK_SIZE, 178 "Error: Not enough RAM for desired minimum stack size."); 179 . = _stack_high; 180 pw_boot_stack_high_addr = .; 181 } >RAM 182 183 /* Discard unwind info. */ 184 .ARM.extab 0x0 (INFO) : 185 { 186 KEEP(*(.ARM.extab*)) 187 } 188} 189 190/* Symbols used by core_init.c: */ 191/* Start of .static_init_ram in FLASH. */ 192_pw_static_init_flash_start = LOADADDR(.static_init_ram); 193 194/* Region of .static_init_ram in RAM. */ 195_pw_static_init_ram_start = ADDR(.static_init_ram); 196_pw_static_init_ram_end = _pw_static_init_ram_start + SIZEOF(.static_init_ram); 197 198/* Region of .zero_init_ram. */ 199_pw_zero_init_ram_start = ADDR(.zero_init_ram); 200_pw_zero_init_ram_end = _pw_zero_init_ram_start + SIZEOF(.zero_init_ram); 201 202/* arm-none-eabi expects `end` symbol to point to start of heap for sbrk. */ 203PROVIDE(end = _pw_zero_init_ram_end); 204