1/******************************************************************************* 2 * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions. 3 * 4 * SPDX-License-Identifier: MIT 5 * 6 * MPFS HAL Embedded Software 7 * 8 */ 9/******************************************************************************* 10 * 11 * file name : mpfs-envm-lma-scratchpad-vma.ld 12 * Code starts from eNVM and relocates itself to an L2 cache scratchpad mapped in 13 * the Zero Device address range. 14 * 15 * You can find details on the PolarFireSoC Memory map in the mpfs-memory-hierarchy.md 16 * which can be found under the link below: 17 * https://github.com/polarfire-soc/polarfire-soc-documentation 18 * 19 */ 20 21OUTPUT_ARCH( "riscv" ) 22ENTRY(_start) 23 24/*----------------------------------------------------------------------------- 25 26-- MSS hart Reset vector 27 28The MSS reset vector for each hart is stored securely in the MPFS. 29The most common usage will be where the reset vector for each hart will be set 30to the start of the envm at address 0x2022_0100, giving 128K-256B of contiguous 31non-volatile storage. Normally this is where the initial boot-loader will 32reside. (Note: The first 256B page of envm is used for metadata associated with 33secure boot. When not using secure boot (mode 0,1), this area is still reserved 34by convention. It allows easier transition from non-secure to secure boot flow 35during the development process. 36When debugging a bare metal program that is run out of reset from envm, a linker 37script will be used whereby the program will run from LIM instead of envm. 38In this case, the reset vector in the linker script is normally set to the 39start of LIM, 0x0800_0000. 40This means you are not continually programming the envm each time you load a 41program and there is no limitation with break points when debugging. 42See the mpfs-lim.ld example linker script when runing from LIM. 43 44------------------------------------------------------------------------------*/ 45 46MEMORY 47{ 48 /* In this example, our reset vector is set to point to the */ 49 /* start at page 1 of the envm */ 50 envm (rx) : ORIGIN = 0x20220100, LENGTH = 128k - 0x100 51 dtim (rwx) : ORIGIN = 0x01000000, LENGTH = 7k 52 e51_itim (rwx) : ORIGIN = 0x01800000, LENGTH = 28k 53 u54_1_itim (rwx) : ORIGIN = 0x01808000, LENGTH = 28k 54 u54_2_itim (rwx) : ORIGIN = 0x01810000, LENGTH = 28k 55 u54_3_itim (rwx) : ORIGIN = 0x01818000, LENGTH = 28k 56 u54_4_itim (rwx) : ORIGIN = 0x01820000, LENGTH = 28k 57 l2lim (rwx) : ORIGIN = 0x08000000, LENGTH = 256k 58 scratchpad(rwx) : ORIGIN = 0x0A000000, LENGTH = 256k 59 /* This 1k of DTIM is used to run code when switching the envm clock */ 60 switch_code (rx) : ORIGIN = 0x01001c00, LENGTH = 1k 61 /* DDR sections example */ 62 ddr_cached_32bit (rwx) : ORIGIN = 0x80000000, LENGTH = 768M 63 ddr_non_cached_32bit (rwx) : ORIGIN = 0xC0000000, LENGTH = 256M 64 ddr_wcb_32bit (rwx) : ORIGIN = 0xD0000000, LENGTH = 256M 65 ddr_cached_38bit (rwx) : ORIGIN = 0x1000000000, LENGTH = 1024M 66 ddr_non_cached_38bit (rwx) : ORIGIN = 0x1400000000, LENGTH = 0k 67 ddr_wcb_38bit (rwx) : ORIGIN = 0x1800000000, LENGTH = 0k 68} 69 70HEAP_SIZE = 8k; /* needs to be calculated for your application if using */ 71 72/* 73 * There is common area for shared variables, accessed from a pointer in a harts HLS 74 */ 75SIZE_OF_COMMON_HART_MEM = 4k; 76 77/* 78 * The stack size needs to be calculated for your 79 * application. It must be Must be aligned 80 * Also Thread local storage (AKA hart local storage) is allocated for each hart 81 * as part of the stack 82 * So the memory map will look like once apportion in startup code: 83 * stack hart0 Actual Stack size = (STACK_SIZE_PER_HART - HLS_DEBUG_AREA_SIZE) 84 * TLS hart 0 85 * stack hart1 86 * TLS hart 1 87 * etc 88 * note: HLS_DEBUG_AREA_SIZE is defined in mss_sw_config.h 89 */ 90 91/* 92 * STACK_SIZE_xxx_STARTUP 93 * Stack size for each hart's startup code. 94 * Before copying itself to the scratchpad memory area and executing the code from there, the 95 * startup code is executing from LIM. The scratchpad area is not configured yet. This per-hart 96 * startup stack area is located in LIM and used during this phase of the startup code. 97 * STACK_SIZE_xxx_APPLICATION 98 * After the startup code executing from LIM configures the scratchpad memory, it configures 99 * the each hart's SP with this stack area for the respective hart's application function, 100 * (namely e51(), u54_1(), u54_2(), u54_3(), u54_4() ) to use it. 101 * This per-hart application stack area is located in scratchpad and used by application when 102 * it is executing from scratchpad. 103 * 104 */ 105STACK_SIZE_E51_STARTUP = 4k; 106STACK_SIZE_U54_1_STARTUP = 4k; 107STACK_SIZE_U54_2_STARTUP = 4k; 108STACK_SIZE_U54_3_STARTUP = 4k; 109STACK_SIZE_U54_4_STARTUP = 4k; 110 111STACK_SIZE_E51_APPLICATION = 8k; 112STACK_SIZE_U54_1_APPLICATION = 8k; 113STACK_SIZE_U54_2_APPLICATION = 8k; 114STACK_SIZE_U54_3_APPLICATION = 8k; 115STACK_SIZE_U54_4_APPLICATION = 8k; 116 117 118SECTIONS 119{ 120 PROVIDE(__envm_start = ORIGIN(envm)); 121 PROVIDE(__envm_end = ORIGIN(envm) + LENGTH(envm)); 122 PROVIDE(__l2lim_start = ORIGIN(l2lim)); 123 PROVIDE(__l2lim_end = ORIGIN(l2lim) + LENGTH(l2lim)); 124 PROVIDE(__ddr_cached_32bit_start = ORIGIN(ddr_cached_32bit)); 125 PROVIDE(__ddr_cached_32bit_end = ORIGIN(ddr_cached_32bit) + LENGTH(ddr_cached_32bit)); 126 PROVIDE(__ddr_non_cached_32bit_start = ORIGIN(ddr_non_cached_32bit)); 127 PROVIDE(__ddr_non_cached_32bit_end = ORIGIN(ddr_non_cached_32bit) + LENGTH(ddr_non_cached_32bit)); 128 PROVIDE(__ddr_wcb_32bit_start = ORIGIN(ddr_wcb_32bit)); 129 PROVIDE(__ddr_wcb_32bit_end = ORIGIN(ddr_wcb_32bit) + LENGTH(ddr_wcb_32bit)); 130 PROVIDE(__ddr_cached_38bit_start = ORIGIN(ddr_cached_38bit)); 131 PROVIDE(__ddr_cached_38bit_end = ORIGIN(ddr_cached_38bit) + LENGTH(ddr_cached_38bit)); 132 PROVIDE(__ddr_non_cached_38bit_start = ORIGIN(ddr_non_cached_38bit)); 133 PROVIDE(__ddr_non_cached_38bit_end = ORIGIN(ddr_non_cached_38bit) + LENGTH(ddr_non_cached_38bit)); 134 PROVIDE(__ddr_wcb_38bit_start = ORIGIN(ddr_wcb_38bit)); 135 PROVIDE(__ddr_wcb_38bit_end = ORIGIN(ddr_wcb_38bit) + LENGTH(ddr_wcb_38bit)); 136 PROVIDE(__dtim_start = ORIGIN(dtim)); 137 PROVIDE(__dtim_end = ORIGIN(dtim) + LENGTH(dtim)); 138 PROVIDE(__e51itim_start = ORIGIN(e51_itim)); 139 PROVIDE(__e51itim_end = ORIGIN(e51_itim) + LENGTH(e51_itim)); 140 PROVIDE(__u54_1_itim_start = ORIGIN(u54_1_itim)); 141 PROVIDE(__u54_1_itim_end = ORIGIN(u54_1_itim) + LENGTH(u54_1_itim)); 142 PROVIDE(__u54_2_itim_start = ORIGIN(u54_2_itim)); 143 PROVIDE(__u54_2_itim_end = ORIGIN(u54_2_itim) + LENGTH(u54_2_itim)); 144 PROVIDE(__u54_3_itim_start = ORIGIN(u54_3_itim)); 145 PROVIDE(__u54_3_itim_end = ORIGIN(u54_3_itim) + LENGTH(u54_3_itim)); 146 PROVIDE(__u54_4_itim_start = ORIGIN(u54_4_itim)); 147 PROVIDE(__u54_4_itim_end = ORIGIN(u54_4_itim) + LENGTH(u54_4_itim)); 148 149 . = __envm_start; 150 .text_init : ALIGN(0x10) 151 { 152 *(.text.init) 153 *system_startup.o (.text .text* .rodata .rodata* .srodata*) 154 *mtrap.o (.text .text* .rodata .rodata* .srodata*) 155 *mss_h2f.o (.text .text* .rodata .rodata* .srodata*) 156 *mss_l2_cache.o (.text .text* .rodata .rodata* .srodata*) 157 . = ALIGN(0x10); 158 } >envm 159 160 .text : ALIGN(0x10) 161 { 162 __text_load = LOADADDR(.text); 163 . = ALIGN(0x10); 164 __text_start = .; 165 /* placed at the start of used scratchpad, used as check to verify enough available in code */ 166 __l2_scratchpad_vma_start = .; 167 168 *(.text .text.* .gnu.linkonce.t.*) 169 *(.plt) 170 . = ALIGN(0x10); 171 172 KEEP (*crtbegin.o(.ctors)) 173 KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 174 KEEP (*(SORT(.ctors.*))) 175 KEEP (*crtend.o(.ctors)) 176 KEEP (*crtbegin.o(.dtors)) 177 KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 178 KEEP (*(SORT(.dtors.*))) 179 KEEP (*crtend.o(.dtors)) 180 181 *(.rodata .rodata.* .gnu.linkonce.r.*) 182 *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) 183 *(.gcc_except_table) 184 *(.eh_frame_hdr) 185 *(.eh_frame) 186 187 KEEP (*(.init)) 188 KEEP (*(.fini)) 189 190 PROVIDE_HIDDEN (__preinit_array_start = .); 191 KEEP (*(.preinit_array)) 192 PROVIDE_HIDDEN (__preinit_array_end = .); 193 PROVIDE_HIDDEN (__init_array_start = .); 194 KEEP (*(SORT(.init_array.*))) 195 KEEP (*(.init_array)) 196 PROVIDE_HIDDEN (__init_array_end = .); 197 PROVIDE_HIDDEN (__fini_array_start = .); 198 KEEP (*(.fini_array)) 199 KEEP (*(SORT(.fini_array.*))) 200 PROVIDE_HIDDEN (__fini_array_end = .); 201 202 *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) 203 *(.srodata*) 204 205 . = ALIGN(0x10); 206 __text_end = .; 207 } >scratchpad AT> envm 208 209 /* short/global data section */ 210 .sdata : ALIGN(0x10) 211 { 212 __sdata_load = LOADADDR(.sdata); 213 __sdata_start = .; 214 /* offset used with gp(gloabl pointer) are +/- 12 bits, so set point to middle of expected sdata range */ 215 /* If sdata more than 4K, linker used direct addressing. Perhaps we should add check/warning to linker script if sdata is > 4k */ 216 __global_pointer$ = . + 0x800; 217 *(.sdata .sdata.* .gnu.linkonce.s.*) 218 . = ALIGN(0x10); 219 __sdata_end = .; 220 } >scratchpad AT> envm 221 222 /* data section */ 223 .data : ALIGN(0x10) 224 { 225 __data_load = LOADADDR(.data); 226 __data_start = .; 227 *(.got.plt) *(.got) 228 *(.shdata) 229 *(.data .data.* .gnu.linkonce.d.*) 230 . = ALIGN(0x10); 231 __data_end = .; 232 } > scratchpad AT> envm 233 234 /* sbss section */ 235 .sbss : ALIGN(0x10) 236 { 237 __sbss_start = .; 238 *(.sbss .sbss.* .gnu.linkonce.sb.*) 239 *(.scommon) 240 . = ALIGN(0x10); 241 __sbss_end = .; 242 } > scratchpad 243 244 /* sbss section */ 245 .bss : ALIGN(0x10) 246 { 247 __bss_start = .; 248 *(.shbss) 249 *(.bss .bss.* .gnu.linkonce.b.*) 250 *(COMMON) 251 . = ALIGN(0x10); 252 __bss_end = .; 253 } > scratchpad 254 255 /* End of uninitialized data segment */ 256 _end = .; 257 258 .heap : ALIGN(0x10) 259 { 260 __heap_start = .; 261 . += HEAP_SIZE; 262 __heap_end = .; 263 . = ALIGN(0x10); 264 _heap_end = __heap_end; 265 __l2_scratchpad_vma_end = .; 266 } > scratchpad 267 268 269 /* must be on 4k boundary- corresponds to page size */ 270 .stack_e51 : /* ALIGN(0x1000) */ 271 { 272 PROVIDE(__stack_bottom_h0$ = .); 273 . += STACK_SIZE_E51_STARTUP; 274 PROVIDE(__stack_top_h0$ = .); 275 } > l2lim 276 277 /* must be on 4k boundary- corresponds to page size */ 278 .stack_u54_1 : /* ALIGN(0x1000) */ 279 { 280 PROVIDE(__stack_bottom_h1$ = .); 281 . += STACK_SIZE_U54_1_STARTUP; 282 PROVIDE(__stack_top_h1$ = .); 283 } > l2lim 284 285 /* must be on 4k boundary- corresponds to page size */ 286 .stack_u54_2 : /* ALIGN(0x1000) */ 287 { 288 PROVIDE(__stack_bottom_h2$ = .); 289 . += STACK_SIZE_U54_2_STARTUP; 290 PROVIDE(__stack_top_h2$ = .); 291 } > l2lim 292 293 /* */ 294 .stack_u54_3 : /* ALIGN(0x1000) */ 295 { 296 PROVIDE(__stack_bottom_h3$ = .); 297 . += STACK_SIZE_U54_3_STARTUP; 298 PROVIDE(__stack_top_h3$ = .); 299 } > l2lim 300 301 /* */ 302 .stack_u54_4 : /* ALIGN(0x1000) */ 303 { 304 PROVIDE(__stack_bottom_h4$ = .); 305 . += STACK_SIZE_U54_4_STARTUP; 306 PROVIDE(__stack_top_h4$ = .); 307 } > l2lim 308 /* application stacks defined below here */ 309 310 /* must be on 4k boundary- corresponds to page size */ 311 .app_stack_e51 : /* ALIGN(0x1000) */ 312 { 313 PROVIDE(__app_stack_bottom_h0 = .); 314 . += STACK_SIZE_E51_APPLICATION; 315 PROVIDE(__app_stack_top_h0 = .); 316 } > scratchpad 317 318 /* must be on 4k boundary- corresponds to page size */ 319 .app_stack_u54_1 : /* ALIGN(0x1000) */ 320 { 321 PROVIDE(__app_stack_bottom_h1$ = .); 322 . += STACK_SIZE_U54_1_APPLICATION; 323 PROVIDE(__app_stack_top_h1 = .); 324 } > scratchpad 325 326 /* */ 327 .app_stack_u54_2 : /* ALIGN(0x1000) */ 328 { 329 PROVIDE(__app_stack_bottom_h2 = .); 330 . += STACK_SIZE_U54_2_APPLICATION; 331 PROVIDE(__app_stack_top_h2 = .); 332 } > scratchpad 333 334 /* */ 335 .app_stack_u54_3 : /* ALIGN(0x1000) */ 336 { 337 PROVIDE(__app_stack_bottom_h3 = .); 338 . += STACK_SIZE_U54_3_APPLICATION; 339 PROVIDE(__app_stack_top_h3 = .); 340 } > scratchpad 341 342 /* */ 343 .app_stack_u54_4 : /* ALIGN(0x1000) */ 344 { 345 PROVIDE(__app_stack_bottom_h4 = .); 346 . += STACK_SIZE_U54_4_APPLICATION; 347 PROVIDE(__app_stack_top_h4 = .); 348 } > scratchpad 349 350 /* 351 * memory shared accross harts. 352 * The boot Hart Local Storage holds a pointer to this area for each hart if 353 * when enabled by setting MPFS_HAL_SHARED_MEM_ENABLED define in the 354 * mss_sw_config.h 355 */ 356 .app_hart_common : /* ALIGN(0x1000) */ 357 { 358 PROVIDE(__app_hart_common_start = .); 359 . += SIZE_OF_COMMON_HART_MEM; 360 PROVIDE(__app_hart_common_end = .); 361 /* place at the end of used scratchpad, used as check to verify enough available in code */ 362 __l2_scratchpad_vma_end = .; 363 } > scratchpad 364 365 /* 366 * The .ram_code section will contain the code That is run from RAM. 367 * We are using this code to switch the clocks including envm clock. 368 * This can not be done when running from envm 369 * This will need to be copied to ram, before any of this code is run. 370 */ 371 .ram_code : 372 { 373 . = ALIGN (4); 374 __sc_load = LOADADDR (.ram_code); 375 __sc_start = .; 376 *(.ram_codetext) /* .ram_codetext sections (code) */ 377 *(.ram_codetext*) /* .ram_codetext* sections (code) */ 378 *(.ram_coderodata) /* read-only data (constants) */ 379 *(.ram_coderodata*) 380 . = ALIGN (4); 381 __sc_end = .; 382 /* place __start_of_free_lim$ after last allocation of l2lim */ 383 PROVIDE(__start_of_free_lim$ = .); 384 } >switch_code AT> envm /* On the MPFS for startup code use, >switch_code AT>envm */ 385} 386 387 388