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-ddr-loaded-by-boot-loader.ld 12 * Use this linker script when the program is fully located in DDR. The 13 * assumption is DDR has already been initialized by another program. 14 * 15 * This linker script can be used with a debugger or when compiled and loaded 16 * by a boot-loader. 17 * The loading program passes two parameters in a0 and a1 18 * a0 - The hartid is passed here 19 * a1 - A pointer to Hart Local Storage (HLS) is passed here 20 * The HLS is a small amount of memory dedicated to each hart. 21 * The HLS also contains a pointer to shared memory. 22 * The shared memory is accessible by all harts if used. It is 23 * allocated by the boot-loader if the MPFS_HAL_SHARED_MEM_ENABLED 24 * is defined in the mss_sw_config.h file project configuration file. 25 * Please see the project mpfs-hal-run-from-ddr-u54-1 located in the Bare Metal 26 * library under examples/mpfs-hal for an example of it use. 27 * 28 * https://github.com/polarfire-soc/polarfire-soc-bare-metal-library 29 * 30 * You can find details on the PolarFireSoC Memory map in the mpfs-memory-hierarchy.md 31 * which can be found under the link below: 32 * https://github.com/polarfire-soc/polarfire-soc-documentation 33 * 34 */ 35 36OUTPUT_ARCH( "riscv" ) 37ENTRY(_start) 38 39/*----------------------------------------------------------------------------- 40 41-- MSS hart Reset vector 42 43The MSS reset vector for each hart is stored securely in the MPFS. 44The most common usage will be where the reset vector for each hart will be set 45to the start of the envm at address 0x2022_0100, giving 128K-256B of contiguous 46non-volatile storage. Normally this is where the initial boot-loader will 47reside. (Note: The first 256B page of envm is used for metadata associated with 48secure boot. When not using secure boot (mode 0,1), this area is still reserved 49by convention. It allows easier transition from non-secure to secure boot flow 50during the development process. 51 52------------------------------------------------------------------------------*/ 53 54MEMORY 55{ 56 /* In this example, our reset vector is set to point to the */ 57 /* start at page 1 of the envm */ 58 envm (rx) : ORIGIN = 0x20220100, LENGTH = 128k - 0x100 59 dtim (rwx) : ORIGIN = 0x01000000, LENGTH = 7k 60 e51_itim (rwx) : ORIGIN = 0x01800000, LENGTH = 28k 61 u54_1_itim (rwx) : ORIGIN = 0x01808000, LENGTH = 28k 62 u54_2_itim (rwx) : ORIGIN = 0x01810000, LENGTH = 28k 63 u54_3_itim (rwx) : ORIGIN = 0x01818000, LENGTH = 28k 64 u54_4_itim (rwx) : ORIGIN = 0x01820000, LENGTH = 28k 65 l2lim (rwx) : ORIGIN = 0x08000000, LENGTH = 256k 66 scratchpad(rwx) : ORIGIN = 0x0A000000, LENGTH = 256k 67 /* This 1K of DTIM is used to run code when switching the envm clock */ 68 switch_code_dtim (rx) : ORIGIN = 0x01001c00, LENGTH = 1k 69 /* DDR sections example */ 70 ddr_cached_32bit (rwx) : ORIGIN = 0x80000000, LENGTH = 768M 71 ddr_non_cached_32bit (rwx) : ORIGIN = 0xC0000000, LENGTH = 256M 72 ddr_wcb_32bit (rwx) : ORIGIN = 0xD0000000, LENGTH = 256M 73 ddr_cached_38bit (rwx) : ORIGIN = 0x1000000000, LENGTH = 1024M 74 ddr_non_cached_38bit (rwx) : ORIGIN = 0x1400000000, LENGTH = 0k 75 ddr_wcb_38bit (rwx) : ORIGIN = 0x1800000000, LENGTH = 0k 76} 77HEAP_SIZE = 0k; /* needs to be calculated for your application if using */ 78 79/* 80 * Stack size for our single hart U54 application. 81 */ 82STACK_SIZE_U54_APPLICATION = 8k; 83 84/* 85 * A small amount of unitialised memory used to store information 86 * obtained from the boot-loader on start-up 87 */ 88UNITITALISED_MEM = 16B; 89 90/* reset address 0xC0000000 */ 91SECTION_START_ADDRESS = 0x80000000; 92 93 94SECTIONS 95{ 96 97 /* text: test code section */ 98 . = SECTION_START_ADDRESS; 99 .text : ALIGN(0x10) 100 { 101 __text_load = LOADADDR(.text); 102 __text_start = .; 103 *(.text.init) 104 . = ALIGN(0x10); 105 *(.text .text.* .gnu.linkonce.t.*) 106 *(.plt) 107 . = ALIGN(0x10); 108 109 KEEP (*crtbegin.o(.ctors)) 110 KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 111 KEEP (*(SORT(.ctors.*))) 112 KEEP (*crtend.o(.ctors)) 113 KEEP (*crtbegin.o(.dtors)) 114 KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 115 KEEP (*(SORT(.dtors.*))) 116 KEEP (*crtend.o(.dtors)) 117 118 *(.rodata .rodata.* .gnu.linkonce.r.*) 119 *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) 120 *(.gcc_except_table) 121 *(.eh_frame_hdr) 122 *(.eh_frame) 123 124 KEEP (*(.init)) 125 KEEP (*(.fini)) 126 127 PROVIDE_HIDDEN (__preinit_array_start = .); 128 KEEP (*(.preinit_array)) 129 PROVIDE_HIDDEN (__preinit_array_end = .); 130 PROVIDE_HIDDEN (__init_array_start = .); 131 KEEP (*(SORT(.init_array.*))) 132 KEEP (*(.init_array)) 133 PROVIDE_HIDDEN (__init_array_end = .); 134 PROVIDE_HIDDEN (__fini_array_start = .); 135 KEEP (*(.fini_array)) 136 KEEP (*(SORT(.fini_array.*))) 137 PROVIDE_HIDDEN (__fini_array_end = .); 138 139 *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) 140 *(.srodata*) 141 142 . = ALIGN(0x10); 143 __text_end = .; 144 } > ddr_cached_32bit 145 146 /* short/global data section */ 147 .sdata : ALIGN(0x10) 148 { 149 __sdata_load = LOADADDR(.sdata); 150 __sdata_start = .; 151 /* offset used with gp(gloabl pointer) are +/- 12 bits, so set point to middle of expected sdata range */ 152 /* If sdata more than 4K, linker used direct addressing. Perhaps we should add check/warning to linker script if sdata is > 4k */ 153 __global_pointer$ = . + 0x800; 154 *(.sdata .sdata.* .gnu.linkonce.s.*) 155 . = ALIGN(0x10); 156 __sdata_end = .; 157 } > ddr_cached_32bit 158 159 /* data section */ 160 .data : ALIGN(0x10) 161 { 162 __data_load = LOADADDR(.data); 163 __data_start = .; 164 *(.got.plt) *(.got) 165 *(.shdata) 166 *(.data .data.* .gnu.linkonce.d.*) 167 . = ALIGN(0x10); 168 __data_end = .; 169 } > ddr_cached_32bit 170 171 /* sbss section */ 172 .sbss : ALIGN(0x10) 173 { 174 __sbss_start = .; 175 *(.sbss .sbss.* .gnu.linkonce.sb.*) 176 *(.scommon) 177 . = ALIGN(0x10); 178 __sbss_end = .; 179 } > ddr_cached_32bit 180 181 /* sbss section */ 182 .bss : ALIGN(0x10) 183 { 184 __bss_start = .; 185 *(.shbss) 186 *(.bss .bss.* .gnu.linkonce.b.*) 187 *(COMMON) 188 . = ALIGN(0x10); 189 __bss_end = .; 190 } > ddr_cached_32bit 191 192 /* End of uninitialized data segment */ 193 _end = .; 194 195 .heap : ALIGN(0x10) 196 { 197 __heap_start = .; 198 . += HEAP_SIZE; 199 __heap_end = .; 200 . = ALIGN(0x10); 201 _heap_end = __heap_end; 202 } > ddr_cached_32bit 203 204 /* must be on 4k boundary- corresponds to page size */ 205 .stack : ALIGN(0x1000) 206 { 207 PROVIDE(__app_stack_bottom = .); 208 . += STACK_SIZE_U54_APPLICATION; 209 PROVIDE(__app_stack_top = .); 210 } > ddr_cached_32bit 211 212 /* 213 * used by a program loaded by a bootloader to store information passed 214 * from boot-loader 215 * a0 holds the hart ID 216 * a1 hold pointer to device data, which includes pointer to shared memory 217 * when enabled by setting MPFS_HAL_SHARED_MEM_ENABLED define in the 218 * mss_sw_config.h 219 */ 220 .no_init : ALIGN(0x10) 221 { 222 PROVIDE(__uninit_bottom$ = .); 223 . += UNITITALISED_MEM; 224 PROVIDE(__uninit_top_h$ = .); 225 } > ddr_cached_32bit 226} 227