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_lim.ld 12 * Used when debugging code. The debugger loads the code to LIM. 13 * 14 * You can find details on the PolarFireSoC Memory map in the mpfs-memory-hierarchy.md 15 * which can be found under the link below: 16 * https://github.com/polarfire-soc/polarfire-soc-documentation 17 * 18 */ 19 20OUTPUT_ARCH( "riscv" ) 21ENTRY(_start) 22 23/*----------------------------------------------------------------------------- 24 25-- MSS hart Reset vector 26 27The MSS reset vector for each hart is stored securely in the MPFS. 28The most common usage will be where the reset vector for each hart will be set 29to the start of the envm at address 0x2022_0100, giving 128K-256B of contiguous 30non-volatile storage. Normally this is where the initial boot-loader will 31reside. (Note: The first 256B page of envm is used for metadata associated with 32secure boot. When not using secure boot (mode 0,1), this area is still reserved 33by convention. It allows easier transition from non-secure to secure boot flow 34during the development process. 35 36------------------------------------------------------------------------------*/ 37 38MEMORY 39{ 40 envm (rx) : ORIGIN = 0x20220100, LENGTH = 128k - 0x100 41 dtim (rwx) : ORIGIN = 0x01000000, LENGTH = 7k 42 switch_code (rx) : ORIGIN = 0x01001c00, LENGTH = 1k 43 e51_itim (rwx) : ORIGIN = 0x01800000, LENGTH = 28k 44 u54_1_itim (rwx) : ORIGIN = 0x01808000, LENGTH = 28k 45 u54_2_itim (rwx) : ORIGIN = 0x01810000, LENGTH = 28k 46 u54_3_itim (rwx) : ORIGIN = 0x01818000, LENGTH = 28k 47 u54_4_itim (rwx) : ORIGIN = 0x01820000, LENGTH = 28k 48 l2lim (rwx) : ORIGIN = 0x08000000, LENGTH = 256k 49 scratchpad(rwx) : ORIGIN = 0x0A000000, LENGTH = 256k 50 /* DDR sections example */ 51 ddr_cached_32bit (rwx) : ORIGIN = 0x80000000, LENGTH = 768M 52 ddr_non_cached_32bit (rwx) : ORIGIN = 0xC0000000, LENGTH = 256M 53 ddr_wcb_32bit (rwx) : ORIGIN = 0xD0000000, LENGTH = 256M 54 ddr_cached_38bit (rwx) : ORIGIN = 0x1000000000, LENGTH = 1024M 55 ddr_non_cached_38bit (rwx) : ORIGIN = 0x1400000000, LENGTH = 0k 56 ddr_wcb_38bit (rwx) : ORIGIN = 0x1800000000, LENGTH = 0k 57} 58 59HEAP_SIZE = 8k; /* needs to be calculated for your application if using */ 60 61/* 62 * There is common area for shared variables, accessed from a pointer in a harts HLS 63 */ 64SIZE_OF_COMMON_HART_MEM = 4k; 65 66/* 67 * The stack size needs to be calculated for your 68 * application. It must be Must be aligned 69 * Also Thread local storage (AKA hart local storage) is allocated for each hart 70 * as part of the stack 71 * So the memory map will look like once apportion in startup code: 72 * stack hart0 Actual Stack size = (STACK_SIZE_PER_HART - HLS_DEBUG_AREA_SIZE) 73 * TLS hart 0 74 * stack hart1 75 * TLS hart 1 76 * etc 77 * note: HLS_DEBUG_AREA_SIZE is defined in mss_sw_config.h 78 */ 79 80/* 81 * Stack size for each hart's application. 82 * These are the stack sizes that will be allocated to each hart before starting 83 * each hart's application function, e51(), u54_1(), u54_2(), u54_3(), u54_4(). 84 */ 85STACK_SIZE_E51_APPLICATION = 8k; 86STACK_SIZE_U54_1_APPLICATION = 8k; 87STACK_SIZE_U54_2_APPLICATION = 8k; 88STACK_SIZE_U54_3_APPLICATION = 8k; 89STACK_SIZE_U54_4_APPLICATION = 8k; 90 91 92SECTIONS 93{ 94 PROVIDE(__envm_start = ORIGIN(envm)); 95 PROVIDE(__envm_end = ORIGIN(envm) + LENGTH(envm)); 96 PROVIDE(__l2lim_start = ORIGIN(l2lim)); 97 PROVIDE(__l2lim_end = ORIGIN(l2lim) + LENGTH(l2lim)); 98 PROVIDE(__ddr_cached_32bit_start = ORIGIN(ddr_cached_32bit)); 99 PROVIDE(__ddr_cached_32bit_end = ORIGIN(ddr_cached_32bit) + LENGTH(ddr_cached_32bit)); 100 PROVIDE(__ddr_non_cached_32bit_start = ORIGIN(ddr_non_cached_32bit)); 101 PROVIDE(__ddr_non_cached_32bit_end = ORIGIN(ddr_non_cached_32bit) + LENGTH(ddr_non_cached_32bit)); 102 PROVIDE(__ddr_wcb_32bit_start = ORIGIN(ddr_wcb_32bit)); 103 PROVIDE(__ddr_wcb_32bit_end = ORIGIN(ddr_wcb_32bit) + LENGTH(ddr_wcb_32bit)); 104 PROVIDE(__ddr_cached_38bit_start = ORIGIN(ddr_cached_38bit)); 105 PROVIDE(__ddr_cached_38bit_end = ORIGIN(ddr_cached_38bit) + LENGTH(ddr_cached_38bit)); 106 PROVIDE(__ddr_non_cached_38bit_start = ORIGIN(ddr_non_cached_38bit)); 107 PROVIDE(__ddr_non_cached_38bit_end = ORIGIN(ddr_non_cached_38bit) + LENGTH(ddr_non_cached_38bit)); 108 PROVIDE(__ddr_wcb_38bit_start = ORIGIN(ddr_wcb_38bit)); 109 PROVIDE(__ddr_wcb_38bit_end = ORIGIN(ddr_wcb_38bit) + LENGTH(ddr_wcb_38bit)); 110 PROVIDE(__dtim_start = ORIGIN(dtim)); 111 PROVIDE(__dtim_end = ORIGIN(dtim) + LENGTH(dtim)); 112 PROVIDE(__e51itim_start = ORIGIN(e51_itim)); 113 PROVIDE(__e51itim_end = ORIGIN(e51_itim) + LENGTH(e51_itim)); 114 PROVIDE(__u54_1_itim_start = ORIGIN(u54_1_itim)); 115 PROVIDE(__u54_1_itim_end = ORIGIN(u54_1_itim) + LENGTH(u54_1_itim)); 116 PROVIDE(__u54_2_itim_start = ORIGIN(u54_2_itim)); 117 PROVIDE(__u54_2_itim_end = ORIGIN(u54_2_itim) + LENGTH(u54_2_itim)); 118 PROVIDE(__u54_3_itim_start = ORIGIN(u54_3_itim)); 119 PROVIDE(__u54_3_itim_end = ORIGIN(u54_3_itim) + LENGTH(u54_3_itim)); 120 PROVIDE(__u54_4_itim_start = ORIGIN(u54_4_itim)); 121 PROVIDE(__u54_4_itim_end = ORIGIN(u54_4_itim) + LENGTH(u54_4_itim)); 122 /* text: text code section */ 123 . = __l2lim_start; 124 .text : ALIGN(0x10) 125 { 126 __text_load = LOADADDR(.text); 127 __text_start = .; 128 *(.text.init) 129 . = ALIGN(0x10); 130 *(.text .text.* .gnu.linkonce.t.*) 131 *(.plt) 132 . = ALIGN(0x10); 133 134 KEEP (*crtbegin.o(.ctors)) 135 KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 136 KEEP (*(SORT(.ctors.*))) 137 KEEP (*crtend.o(.ctors)) 138 KEEP (*crtbegin.o(.dtors)) 139 KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 140 KEEP (*(SORT(.dtors.*))) 141 KEEP (*crtend.o(.dtors)) 142 143 *(.rodata .rodata.* .gnu.linkonce.r.*) 144 *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) 145 *(.gcc_except_table) 146 *(.eh_frame_hdr) 147 *(.eh_frame) 148 149 KEEP (*(.init)) 150 KEEP (*(.fini)) 151 152 PROVIDE_HIDDEN (__preinit_array_start = .); 153 KEEP (*(.preinit_array)) 154 PROVIDE_HIDDEN (__preinit_array_end = .); 155 PROVIDE_HIDDEN (__init_array_start = .); 156 KEEP (*(SORT(.init_array.*))) 157 KEEP (*(.init_array)) 158 PROVIDE_HIDDEN (__init_array_end = .); 159 PROVIDE_HIDDEN (__fini_array_start = .); 160 KEEP (*(.fini_array)) 161 KEEP (*(SORT(.fini_array.*))) 162 PROVIDE_HIDDEN (__fini_array_end = .); 163 164 *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) 165 *(.srodata*) 166 167 . = ALIGN(0x10); 168 __text_end = .; 169 . = ALIGN(0x10); 170 } > l2lim 171 172 .l2_scratchpad : ALIGN(0x10) 173 { 174 . = ALIGN (0x10); 175 __l2_scratchpad_load = LOADADDR(.l2_scratchpad); 176 __l2_scratchpad_start = .; 177 __l2_scratchpad_vma_start = .; 178 *(.l2_scratchpad) 179 . = ALIGN(0x10); 180 __l2_scratchpad_end = .; 181 __l2_scratchpad_vma_end = .; 182 } >scratchpad AT> l2lim 183 184 /* 185 * The .ram_code section will contain the code That is run from RAM. 186 * We are using this code to switch the clocks including eNVM clock. 187 * This can not be done when running from eNVM 188 * This will need to be copied to ram, before any of this code is run. 189 */ 190 .ram_code : 191 { 192 . = ALIGN (4); 193 __sc_load = LOADADDR (.ram_code); 194 __sc_start = .; 195 *(.ram_codetext) /* .ram_codetext sections (code) */ 196 *(.ram_codetext*) /* .ram_codetext* sections (code) */ 197 *(.ram_coderodata) /* read-only data (constants) */ 198 *(.ram_coderodata*) 199 . = ALIGN (4); 200 __sc_end = .; 201 } >switch_code AT> l2lim /* On the MPFS for startup code use, >switch_code AT>eNVM */ 202 203 /* short/global data section */ 204 .sdata : ALIGN(0x10) 205 { 206 __sdata_load = LOADADDR(.sdata); 207 __sdata_start = .; 208 /* offset used with gp(gloabl pointer) are +/- 12 bits, so set point to middle of expected sdata range */ 209 /* If sdata more than 4K, linker used direct addressing. Perhaps we should add check/warning to linker script if sdata is > 4k */ 210 __global_pointer$ = . + 0x800; 211 *(.sdata .sdata.* .gnu.linkonce.s.*) 212 . = ALIGN(0x10); 213 __sdata_end = .; 214 } > l2lim 215 216 /* data section */ 217 .data : ALIGN(0x10) 218 { 219 __data_load = LOADADDR(.data); 220 __data_start = .; 221 *(.got.plt) *(.got) 222 *(.shdata) 223 *(.data .data.* .gnu.linkonce.d.*) 224 . = ALIGN(0x10); 225 __data_end = .; 226 } > l2lim 227 228 /* sbss section */ 229 .sbss : ALIGN(0x10) 230 { 231 __sbss_start = .; 232 *(.sbss .sbss.* .gnu.linkonce.sb.*) 233 *(.scommon) 234 . = ALIGN(0x10); 235 __sbss_end = .; 236 } > l2lim 237 238 /* sbss section */ 239 .bss : ALIGN(0x10) 240 { 241 __bss_start = .; 242 *(.shbss) 243 *(.bss .bss.* .gnu.linkonce.b.*) 244 *(COMMON) 245 . = ALIGN(0x10); 246 __bss_end = .; 247 } > l2lim 248 249 /* End of uninitialized data segment */ 250 _end = .; 251 252 .heap : ALIGN(0x10) 253 { 254 __heap_start = .; 255 . += HEAP_SIZE; 256 __heap_end = .; 257 . = ALIGN(0x10); 258 _heap_end = __heap_end; 259 } > l2lim 260 261 /* must be on 4k boundary- corresponds to page size */ 262 .stack : ALIGN(0x1000) 263 { 264 PROVIDE(__stack_bottom_h0$ = .); 265 PROVIDE(__app_stack_bottom_h0 = .); 266 . += STACK_SIZE_E51_APPLICATION; 267 PROVIDE(__app_stack_top_h0 = .); 268 PROVIDE(__stack_top_h0$ = .); 269 270 PROVIDE(__stack_bottom_h1$ = .); 271 PROVIDE(__app_stack_bottom_h1$ = .); 272 . += STACK_SIZE_U54_1_APPLICATION; 273 PROVIDE(__app_stack_top_h1 = .); 274 PROVIDE(__stack_top_h1$ = .); 275 276 PROVIDE(__stack_bottom_h2$ = .); 277 PROVIDE(__app_stack_bottom_h2 = .); 278 . += STACK_SIZE_U54_2_APPLICATION; 279 PROVIDE(__app_stack_top_h2 = .); 280 PROVIDE(__stack_top_h2$ = .); 281 282 PROVIDE(__stack_bottom_h3$ = .); 283 PROVIDE(__app_stack_bottom_h3 = .); 284 . += STACK_SIZE_U54_3_APPLICATION; 285 PROVIDE(__app_stack_top_h3 = .); 286 PROVIDE(__stack_top_h3$ = .); 287 288 PROVIDE(__stack_bottom_h4$ = .); 289 PROVIDE(__app_stack_bottom_h4 = .); 290 . += STACK_SIZE_U54_4_APPLICATION; 291 PROVIDE(__app_stack_top_h4 = .); 292 PROVIDE(__stack_top_h4$ = .); 293 294 } > l2lim 295 296 /* 297 * memory shared accross harts. 298 * The boot Hart Local Storage holds a pointer to this area for each hart if 299 * when enabled by setting MPFS_HAL_SHARED_MEM_ENABLED define in the 300 * mss_sw_config.h 301 */ 302 .app_hart_common : /* ALIGN(0x1000) */ 303 { 304 PROVIDE(__app_hart_common_start = .); 305 . += SIZE_OF_COMMON_HART_MEM; 306 PROVIDE(__app_hart_common_end = .); 307 } > l2lim 308} 309 310