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