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