1/* Based on GCC ARM embedded samples. 2 Defines the following symbols for use by code: 3 __exidx_start 4 __exidx_end 5 __etext 6 __data_start__ 7 __preinit_array_start 8 __preinit_array_end 9 __init_array_start 10 __init_array_end 11 __fini_array_start 12 __fini_array_end 13 __data_end__ 14 __bss_start__ 15 __bss_end__ 16 __end__ 17 end 18 __HeapLimit 19 __StackLimit 20 __StackTop 21 __stack (== StackTop) 22*/ 23 24MEMORY 25{ 26 RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k 27 SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k 28 SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k 29} 30 31ENTRY(_entry_point) 32 33SECTIONS 34{ 35 /* Note unlike RP2040, we start the image with a vector table even for 36 NO_FLASH builds. On Arm, the bootrom expects a VT at the start of the 37 image by default; on RISC-V, the default is to enter the image at its 38 lowest address, so an IMAGEDEF item is required to specify the 39 nondefault entry point. */ 40 41 .text : { 42 __logical_binary_start = .; 43 /* Vectors require 512-byte alignment on v8-M when >48 IRQs are used, 44 so we would waste RAM if the vector table were not at the 45 start. */ 46 KEEP (*(.vectors)) 47 KEEP (*(.binary_info_header)) 48 __binary_info_header_end = .; 49 KEEP (*(.embedded_block)) 50 __embedded_block_end = .; 51 __reset_start = .; 52 KEEP (*(.reset)) 53 __reset_end = .; 54 *(.time_critical*) 55 *(.text*) 56 . = ALIGN(4); 57 *(.init) 58 *(.fini) 59 /* Pull all c'tors into .text */ 60 *crtbegin.o(.ctors) 61 *crtbegin?.o(.ctors) 62 *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) 63 *(SORT(.ctors.*)) 64 *(.ctors) 65 /* Followed by destructors */ 66 *crtbegin.o(.dtors) 67 *crtbegin?.o(.dtors) 68 *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) 69 *(SORT(.dtors.*)) 70 *(.dtors) 71 72 *(.eh_frame*) 73 } > RAM 74 75 .rodata : { 76 . = ALIGN(4); 77 *(.rodata*) 78 *(.srodata*) 79 . = ALIGN(4); 80 *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) 81 . = ALIGN(4); 82 } > RAM 83 84 .ARM.extab : 85 { 86 *(.ARM.extab* .gnu.linkonce.armextab.*) 87 } > RAM 88 89 __exidx_start = .; 90 .ARM.exidx : 91 { 92 *(.ARM.exidx* .gnu.linkonce.armexidx.*) 93 } > RAM 94 __exidx_end = .; 95 96 /* Machine inspectable binary information */ 97 . = ALIGN(4); 98 __binary_info_start = .; 99 .binary_info : 100 { 101 KEEP(*(.binary_info.keep.*)) 102 *(.binary_info.*) 103 } > RAM 104 __binary_info_end = .; 105 . = ALIGN(4); 106 107 .data : { 108 __data_start__ = .; 109 *(vtable) 110 *(.data*) 111 *(.sdata*) 112 113 . = ALIGN(4); 114 *(.after_data.*) 115 . = ALIGN(4); 116 /* preinit data */ 117 PROVIDE_HIDDEN (__mutex_array_start = .); 118 KEEP(*(SORT(.mutex_array.*))) 119 KEEP(*(.mutex_array)) 120 PROVIDE_HIDDEN (__mutex_array_end = .); 121 122 . = ALIGN(4); 123 /* preinit data */ 124 PROVIDE_HIDDEN (__preinit_array_start = .); 125 KEEP(*(SORT(.preinit_array.*))) 126 KEEP(*(.preinit_array)) 127 PROVIDE_HIDDEN (__preinit_array_end = .); 128 129 . = ALIGN(4); 130 /* init data */ 131 PROVIDE_HIDDEN (__init_array_start = .); 132 KEEP(*(SORT(.init_array.*))) 133 KEEP(*(.init_array)) 134 PROVIDE_HIDDEN (__init_array_end = .); 135 136 . = ALIGN(4); 137 /* finit data */ 138 PROVIDE_HIDDEN (__fini_array_start = .); 139 *(SORT(.fini_array.*)) 140 *(.fini_array) 141 PROVIDE_HIDDEN (__fini_array_end = .); 142 143 *(.jcr) 144 . = ALIGN(4); 145 } > RAM 146 147 .tdata : { 148 . = ALIGN(4); 149 *(.tdata .tdata.* .gnu.linkonce.td.*) 150 /* All data end */ 151 __tdata_end = .; 152 } > RAM 153 PROVIDE(__data_end__ = .); 154 155 .uninitialized_data (NOLOAD): { 156 . = ALIGN(4); 157 *(.uninitialized_data*) 158 } > RAM 159 /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ 160 __etext = LOADADDR(.data); 161 162 .tbss (NOLOAD) : { 163 . = ALIGN(4); 164 __bss_start__ = .; 165 __tls_base = .; 166 *(.tbss .tbss.* .gnu.linkonce.tb.*) 167 *(.tcommon) 168 169 __tls_end = .; 170 } > RAM 171 172 .bss (NOLOAD) : { 173 . = ALIGN(4); 174 __tbss_end = .; 175 176 *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) 177 *(COMMON) 178 PROVIDE(__global_pointer$ = . + 2K); 179 *(.sbss*) 180 . = ALIGN(4); 181 __bss_end__ = .; 182 } > RAM 183 184 .heap (NOLOAD): 185 { 186 __end__ = .; 187 end = __end__; 188 KEEP(*(.heap*)) 189 } > RAM 190 /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however 191 to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */ 192 __HeapLimit = ORIGIN(RAM) + LENGTH(RAM); 193 194 /* Start and end symbols must be word-aligned */ 195 .scratch_x : { 196 __scratch_x_start__ = .; 197 *(.scratch_x.*) 198 . = ALIGN(4); 199 __scratch_x_end__ = .; 200 } > SCRATCH_X 201 __scratch_x_source__ = LOADADDR(.scratch_x); 202 203 .scratch_y : { 204 __scratch_y_start__ = .; 205 *(.scratch_y.*) 206 . = ALIGN(4); 207 __scratch_y_end__ = .; 208 } > SCRATCH_Y 209 __scratch_y_source__ = LOADADDR(.scratch_y); 210 211 /* .stack*_dummy section doesn't contains any symbols. It is only 212 * used for linker to calculate size of stack sections, and assign 213 * values to stack symbols later 214 * 215 * stack1 section may be empty/missing if platform_launch_core1 is not used */ 216 217 /* by default we put core 0 stack at the end of scratch Y, so that if core 1 218 * stack is not used then all of SCRATCH_X is free. 219 */ 220 .stack1_dummy (NOLOAD): 221 { 222 *(.stack1*) 223 } > SCRATCH_X 224 .stack_dummy (NOLOAD): 225 { 226 KEEP(*(.stack*)) 227 } > SCRATCH_Y 228 229 /* stack limit is poorly named, but historically is maximum heap ptr */ 230 __StackLimit = ORIGIN(RAM) + LENGTH(RAM); 231 __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); 232 __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); 233 __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); 234 __StackBottom = __StackTop - SIZEOF(.stack_dummy); 235 PROVIDE(__stack = __StackTop); 236 237 /* picolibc and LLVM */ 238 PROVIDE (__heap_start = __end__); 239 PROVIDE (__heap_end = __HeapLimit); 240 PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); 241 PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1)); 242 PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); 243 244 /* llvm-libc */ 245 PROVIDE (_end = __end__); 246 PROVIDE (__llvm_libc_heap_limit = __HeapLimit); 247 248 /* Check if data + heap + stack exceeds RAM limit */ 249 ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") 250 251 ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary") 252 ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary") 253 254 /* todo assert on extra code */ 255} 256 257