1/* 2 * Copyright (c) 2016-2017 Jean-Paul Etienne <fractalclone@gmail.com> 3 * Copyright (c) 2021 Andes Technology Corporation 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8/** 9 * @file 10 * @brief Linker command/script file 11 * 12 * Linker script for the ae350 platform 13 */ 14 15#include <soc.h> 16#include <zephyr/devicetree.h> 17 18#include <zephyr/linker/sections.h> 19#include <zephyr/linker/devicetree_regions.h> 20 21#include <zephyr/linker/linker-defs.h> 22#include <zephyr/linker/linker-tool.h> 23 24#ifdef CONFIG_XIP 25#define ROMABLE_REGION ROM 26#else 27#define ROMABLE_REGION RAM 28#endif 29#define RAMABLE_REGION RAM 30 31#define _EXCEPTION_SECTION_NAME exceptions 32#define _RESET_SECTION_NAME reset 33 34#ifdef CONFIG_XIP 35#if DT_NODE_HAS_COMPAT_STATUS(DT_CHOSEN(zephyr_flash), soc_nv_flash, okay) 36#ifdef CONFIG_FLASH_LOAD_OFFSET 37#define ROM_BASE (DT_REG_ADDR(DT_CHOSEN(zephyr_flash)) + \ 38 CONFIG_FLASH_LOAD_OFFSET) 39#else /* !CONFIG_FLASH_LOAD_OFFSET */ 40#define ROM_BASE DT_REG_ADDR(DT_CHOSEN(zephyr_flash)) 41#endif /* CONFIG_FLASH_LOAD_OFFSET */ 42#define ROM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_flash)) 43#elif DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_flash), jedec_spi_nor) 44/* For jedec,spi-nor we expect the spi controller to memory map the flash 45 * and for that mapping to be the second register property of the spi 46 * controller. 47 */ 48#define SPI_CTRL DT_PARENT(DT_CHOSEN(zephyr_flash)) 49#define ROM_BASE DT_REG_ADDR_BY_IDX(SPI_CTRL, 1) 50#define ROM_SIZE DT_REG_SIZE_BY_IDX(SPI_CTRL, 1) 51#endif 52#else /* CONFIG_XIP */ 53#define ROM_BASE CONFIG_SRAM_BASE_ADDRESS 54#define ROM_SIZE KB(CONFIG_SRAM_SIZE) 55#endif /* CONFIG_XIP */ 56 57#define RAM_BASE CONFIG_SRAM_BASE_ADDRESS 58#define RAM_SIZE KB(CONFIG_SRAM_SIZE) 59 60#ifdef CONFIG_RISCV_PMP 61 #define MPU_MIN_SIZE CONFIG_PMP_GRANULARITY 62 #define MPU_MIN_SIZE_ALIGN . = ALIGN(MPU_MIN_SIZE); 63 #if defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) 64 #define MPU_ALIGN(region_size) \ 65 . = ALIGN(MPU_MIN_SIZE); \ 66 . = ALIGN( 1 << LOG2CEIL(region_size)) 67 #else 68 #define MPU_ALIGN(region_size) \ 69 . = ALIGN(MPU_MIN_SIZE) 70 #endif 71#else 72 #define MPU_MIN_SIZE_ALIGN 73 #define MPU_ALIGN(region_size) . = ALIGN(4) 74#endif 75 76MEMORY 77{ 78#ifdef CONFIG_XIP 79 ROM (rx) : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE 80#endif 81 RAM (rwx) : ORIGIN = RAM_BASE, LENGTH = RAM_SIZE 82 83 LINKER_DT_REGIONS() 84 85 /* Used by and documented in include/linker/intlist.ld */ 86 IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K 87} 88 89ENTRY(CONFIG_KERNEL_ENTRY) 90 91SECTIONS 92 { 93 94#include <zephyr/linker/rel-sections.ld> 95 96 /* 97 * The .plt and .iplt are here according to 98 * 'riscv32-zephyr-elf-ld --verbose', before text section. 99 */ 100 SECTION_PROLOGUE(.plt,,) 101 { 102 *(.plt) 103 } 104 105 SECTION_PROLOGUE(.iplt,,) 106 { 107 *(.iplt) 108 } 109 110 GROUP_START(ROMABLE_REGION) 111 112 SECTION_PROLOGUE(rom_start,,) 113 { 114 . = ALIGN(16); 115 MPU_ALIGN(__rom_region_size); 116 __rom_region_start = .; 117/* Located in generated directory. This file is populated by calling 118 * zephyr_linker_sources(ROM_START ...). 119 */ 120#include <snippets-rom-start.ld> 121 } GROUP_LINK_IN(ROMABLE_REGION) 122 123#ifdef CONFIG_CODE_DATA_RELOCATION 124#include <linker_relocate.ld> 125#endif 126 127 SECTION_PROLOGUE(_RESET_SECTION_NAME,,) 128 { 129 KEEP(*(.reset.*)) 130 } GROUP_LINK_IN(ROMABLE_REGION) 131 132 SECTION_PROLOGUE(_EXCEPTION_SECTION_NAME,,) 133 { 134 KEEP(*(".exception.entry.*")) 135 *(".exception.other.*") 136 } GROUP_LINK_IN(ROMABLE_REGION) 137 138 SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) 139 { 140 . = ALIGN(4); 141 KEEP(*(.openocd_debug)) 142 KEEP(*(".openocd_debug.*")) 143 144 __text_region_start = .; 145 146 *(.text) 147 *(".text.*") 148 *(.gnu.linkonce.t.*) 149#include <zephyr/linker/kobject-text.ld> 150 } GROUP_LINK_IN(ROMABLE_REGION) 151 152 __text_region_end = .; 153 154 __rodata_region_start = .; 155#include <zephyr/linker/common-rom.ld> 156#include <zephyr/linker/thread-local-storage.ld> 157 158 SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) 159 { 160 . = ALIGN(4); 161 *(.srodata) 162 *(".srodata.*") 163 *(.rodata) 164 *(".rodata.*") 165 *(.gnu.linkonce.r.*) 166 *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) 167 168/* Located in generated directory. This file is populated by the 169 * zephyr_linker_sources() Cmake function. 170 */ 171#include <snippets-rodata.ld> 172#include <zephyr/linker/kobject-rom.ld> 173 . = ALIGN(4); 174 } GROUP_LINK_IN(ROMABLE_REGION) 175 176#include <zephyr/linker/cplusplus-rom.ld> 177 __rodata_region_end = .; 178 179 /* For non-XIP system, __rom_region_end symbol should be set to 180 * the end of common ROMABLE_REGIONs (text and rodata) instead of 181 * the linker script end, so it wouldn't mistakenly contain 182 * RAMABLE_REGION in it. 183 */ 184#ifndef CONFIG_XIP 185#ifdef CONFIG_RISCV_PMP 186 SECTION_PROLOGUE(rom_mpu_padding,,) 187 { 188 MPU_ALIGN(__rodata_region_end - __rom_region_start); 189 } GROUP_LINK_IN(ROMABLE_REGION) 190#endif /* CONFIG_RISCV_PMP */ 191 192 __rom_region_end = .; 193 __rom_region_size = __rom_region_end - __rom_region_start; 194#endif /* CONFIG_XIP */ 195 GROUP_END(ROMABLE_REGION) 196 197 GROUP_START(RAMABLE_REGION) 198 199 . = RAM_BASE; 200 _image_ram_start = .; 201 202#ifdef CONFIG_SOC_ANDES_V5_PMA 203#pragma push_macro("MPU_ALIGN") 204#undef MPU_ALIGN 205/* Make linker section alignment comply with PMA granularity. */ 206#define MPU_ALIGN(region_size) \ 207 . = ALIGN(CONFIG_SOC_ANDES_V5_PMA_REGION_MIN_ALIGN_AND_SIZE); \ 208 . = ALIGN( 1 << LOG2CEIL(region_size)) 209#endif 210 211/* Located in generated directory. This file is populated by the 212 * zephyr_linker_sources() Cmake function. 213 */ 214#include <snippets-ram-sections.ld> 215 216#ifdef CONFIG_SOC_ANDES_V5_PMA 217#pragma pop_macro("MPU_ALIGN") 218#endif 219 220#if defined(CONFIG_USERSPACE) 221#define APP_SHARED_ALIGN MPU_MIN_SIZE_ALIGN 222#define SMEM_PARTITION_ALIGN MPU_ALIGN 223 224#include <app_smem.ld> 225 226 _app_smem_size = _app_smem_end - _app_smem_start; 227 _app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME); 228#endif /* CONFIG_USERSPACE */ 229 230 SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) 231 { 232 MPU_MIN_SIZE_ALIGN 233 /* 234 * For performance, BSS section is assumed to be 4 byte aligned and 235 * a multiple of 4 bytes 236 */ 237 . = ALIGN(4); 238 __bss_start = .; 239 __kernel_ram_start = .; 240 *(.sbss) 241 *(".sbss.*") 242 *(.bss) 243 *(".bss.*") 244 COMMON_SYMBOLS 245 246#ifdef CONFIG_CODE_DATA_RELOCATION 247#include <linker_sram_bss_relocate.ld> 248#endif 249 250 /* 251 * As memory is cleared in words only, it is simpler to ensure the BSS 252 * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. 253 */ 254 __bss_end = ALIGN(4); 255 } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) 256 257#include <zephyr/linker/common-noinit.ld> 258 259 SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) 260 { 261 . = ALIGN(4); 262 /* _image_ram_start = .; */ 263 __data_region_start = .; 264 __data_start = .; 265 266 *(.data) 267 *(".data.*") 268 269#ifdef CONFIG_RISCV_GP 270 /* 271 * RISC-V architecture has 12-bit signed immediate offsets in the 272 * instructions. If we can put the most commonly accessed globals 273 * in a special 4K span of memory addressed by the GP register, then 274 * we can access those values in a single instruction, saving both 275 * codespace and runtime. 276 * 277 * Since these immediate offsets are signed, place gp 0x800 past the 278 * beginning of .sdata so that we can use both positive and negative 279 * offsets. 280 */ 281 . = ALIGN(8); 282 PROVIDE (__global_pointer$ = . + 0x800); 283#endif 284 285 *(.sdata .sdata.* .gnu.linkonce.s.*) 286 287/* Located in generated directory. This file is populated by the 288 * zephyr_linker_sources() Cmake function. 289 */ 290#include <snippets-rwdata.ld> 291 292#ifdef CONFIG_CODE_DATA_RELOCATION 293#include <linker_sram_data_relocate.ld> 294#endif 295 296 __data_end = .; 297 298 } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) 299 __data_size = __data_end - __data_start; 300 __data_load_start = LOADADDR(_DATA_SECTION_NAME); 301 302 __data_region_load_start = LOADADDR(_DATA_SECTION_NAME); 303 304#include <zephyr/linker/common-ram.ld> 305#include <zephyr/linker/kobject-data.ld> 306#include <zephyr/linker/cplusplus-ram.ld> 307 308/* Located in generated directory. This file is populated by the 309 * zephyr_linker_sources() Cmake function. 310 */ 311#include <snippets-data-sections.ld> 312 313 __data_region_end = .; 314 315 __kernel_ram_end = .; 316 __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; 317 318#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) 319GROUP_START(ITCM) 320 321 SECTION_PROLOGUE(_ITCM_SECTION_NAME,,SUBALIGN(8)) 322 { 323 __itcm_start = .; 324 *(.itcm) 325 *(".itcm.*") 326 __itcm_end = .; 327 } GROUP_LINK_IN(ITCM AT> ROMABLE_REGION) 328 329 __itcm_size = __itcm_end - __itcm_start; 330 __itcm_load_start = LOADADDR(_ITCM_SECTION_NAME); 331 332GROUP_END(ITCM) 333#endif 334 335#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) 336GROUP_START(DTCM) 337 338 SECTION_PROLOGUE(_DTCM_BSS_SECTION_NAME, (NOLOAD),SUBALIGN(8)) 339 { 340 __dtcm_start = .; 341 __dtcm_bss_start = .; 342 *(.dtcm_bss) 343 *(".dtcm_bss.*") 344 __dtcm_bss_end = .; 345 } GROUP_LINK_IN(DTCM) 346 347 SECTION_PROLOGUE(_DTCM_NOINIT_SECTION_NAME, (NOLOAD),SUBALIGN(8)) 348 { 349 __dtcm_noinit_start = .; 350 *(.dtcm_noinit) 351 *(".dtcm_noinit.*") 352 __dtcm_noinit_end = .; 353 } GROUP_LINK_IN(DTCM) 354 355 SECTION_PROLOGUE(_DTCM_DATA_SECTION_NAME,,SUBALIGN(8)) 356 { 357 __dtcm_data_start = .; 358 *(.dtcm_data) 359 *(".dtcm_data.*") 360 __dtcm_data_end = .; 361 } GROUP_LINK_IN(DTCM AT> ROMABLE_REGION) 362 363 __dtcm_end = .; 364 365 __dtcm_data_load_start = LOADADDR(_DTCM_DATA_SECTION_NAME); 366 367GROUP_END(DTCM) 368#endif 369 370/* Located in generated directory. This file is populated by the 371 * zephyr_linker_sources() Cmake function. 372 */ 373#include <snippets-sections.ld> 374 375#define LAST_RAM_ALIGN MPU_MIN_SIZE_ALIGN 376 377#include <zephyr/linker/ram-end.ld> 378 379 GROUP_END(RAMABLE_REGION) 380 381#include <zephyr/linker/debug-sections.ld> 382 383 /DISCARD/ : { *(.note.GNU-stack) } 384 385 SECTION_PROLOGUE(.riscv.attributes, 0,) 386 { 387 KEEP(*(.riscv.attributes)) 388 KEEP(*(.gnu.attributes)) 389 } 390 391 /* Sections generated from 'zephyr,memory-region' nodes */ 392 LINKER_DT_SECTIONS() 393 394/* Because ROMABLE_REGION != RAMABLE_REGION in XIP-system, it is valid 395 * to set __rom_region_end symbol at the end of linker script and 396 * doesn't mistakenly contain the RAMABLE_REGION in it. 397 */ 398#ifdef CONFIG_XIP 399/* Must be last in romable region */ 400SECTION_PROLOGUE(.last_section,,) 401{ 402#ifdef CONFIG_LINKER_LAST_SECTION_ID 403 /* Fill last section with a word to ensure location counter and actual rom 404 * region data usage match. */ 405 LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN) 406#endif 407} GROUP_LINK_IN(ROMABLE_REGION) 408 409#ifndef CONFIG_RISCV_PMP 410/* To provide the image size as a const expression, 411 * calculate this value here. */ 412__rom_region_end = LOADADDR(.last_section) + SIZEOF(.last_section); 413#else 414SECTION_PROLOGUE(rom_mpu_padding,(NOLOAD),) 415{ 416 MPU_ALIGN(__rom_region_size); 417 __rom_region_end = .; 418} GROUP_LINK_IN(ROMABLE_REGION) 419#endif /* !CONFIG_RISCV_PMP */ 420__rom_region_size = __rom_region_end - __rom_region_start; 421#endif 422 423} 424