1/* 2 * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. 3 * SPDX-License-Identifier: Apache-2.0 4 */ 5 6#include <zephyr/devicetree.h> 7#include <zephyr/linker/sections.h> 8#include <zephyr/linker/linker-defs.h> 9#include <zephyr/linker/linker-tool.h> 10 11#if !defined(CONFIG_BOOTLOADER_MCUBOOT) 12#error "APPCPU image must use MCUboot image format." 13#endif /* CONFIG_BOOTLOADER_MCUBOOT */ 14 15#include "memory.h" 16 17/* User available SRAM memory segments */ 18appcpu_iram_end = USER_IRAM_END; 19appcpu_dram_end = USER_DRAM_END; 20 21appcpu_iram_org = appcpu_iram_end - APPCPU_SRAM_SIZE; 22appcpu_dram_org = appcpu_dram_end - APPCPU_SRAM_SIZE; 23 24appcpu_iram_len = APPCPU_SRAM_SIZE; 25appcpu_dram_len = APPCPU_SRAM_SIZE; 26 27/* Aliases */ 28#define ROMABLE_REGION FLASH 29#define RODATA_REGION dram0_1_seg /* drom0_1_seg */ 30#define RAMABLE_REGION dram0_1_seg 31#define IRAM_REGION iram0_1_seg 32 33/* Zephyr macro re-definitions */ 34#undef GROUP_DATA_LINK_IN 35#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion AT > lregion 36 37#undef GROUP_NOLOAD_LINK_IN 38#define GROUP_NOLOAD_LINK_IN(vregion, lregion) > vregion 39 40/* Flash segments (rodata and text) should be mapped in the virtual address spaces. 41 * Executing directly from LMA is not possible. */ 42#undef GROUP_ROM_LINK_IN 43#define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion 44 45/* Make sure new sections have consistent alignment between input and output sections */ 46#undef SECTION_DATA_PROLOGUE 47#define SECTION_DATA_PROLOGUE(name, options, align) name options : ALIGN_WITH_INPUT 48 49#undef SECTION_PROLOGUE 50#define SECTION_PROLOGUE SECTION_DATA_PROLOGUE 51 52MEMORY 53{ 54 mcuboot_hdr (R): org = 0x0, len = 0x20 55 metadata (R): org = 0x20, len = 0x20 56 FLASH (R): org = 0x40, len = FLASH_SIZE - 0x40 57 58 iram0_1_seg(RX): org = appcpu_iram_org, len = appcpu_iram_len 59 dram0_1_seg(RW): org = appcpu_dram_org, len = appcpu_dram_len 60 61#ifdef CONFIG_GEN_ISR_TABLES 62 IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 63#endif 64} 65 66/* Default entry point: */ 67ENTRY(__appcpu_start) 68 69/* Used as a pointer to the heap end */ 70_heap_sentry = DRAM_RESERVED_START; 71 72SECTIONS 73{ 74 /* Reserve space for MCUboot header in the binary */ 75 .mcuboot_header : 76 { 77 QUAD(0x0) 78 QUAD(0x0) 79 QUAD(0x0) 80 QUAD(0x0) 81 } > mcuboot_hdr 82 /* Image load table */ 83 .metadata : 84 { 85 /* 0. Magic byte for load header */ 86 LONG(0xace637d3) 87 88 /* 1. Application entry point address */ 89 KEEP(*(.entry_addr)) 90 91 /* IRAM metadata: 92 * 2. Destination address (VMA) for IRAM region 93 * 3. Flash offset (LMA) for start of IRAM region 94 * 4. Size of IRAM region 95 */ 96 LONG(ADDR(.iram0.vectors)) 97 LONG(LOADADDR(.iram0.vectors)) 98 LONG(_iram_end - _init_start); 99 100 /* DRAM metadata: 101 * 5. Destination address (VMA) for DRAM region 102 * 6. Flash offset (LMA) for start of DRAM region 103 * 7. Size of DRAM region 104 */ 105 LONG(ADDR(.dram0.data)) 106 LONG(LOADADDR(.dram0.data)) 107 LONG(_data_end - _data_start) 108 } > metadata 109 110 #include <zephyr/linker/rel-sections.ld> 111 112#ifdef CONFIG_LLEXT 113 #include <zephyr/linker/llext-sections.ld> 114#endif 115 116 /* --- START OF IRAM --- */ 117 118 /* Send .iram0 code to iram */ 119 .iram0.vectors : ALIGN(4) 120 { 121 /* Vectors go to IRAM */ 122 _init_start = ABSOLUTE(.); 123 /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ 124 . = 0x0; 125 KEEP(*(.WindowVectors.text)); 126 . = 0x180; 127 KEEP(*(.Level2InterruptVector.text)); 128 . = 0x1c0; 129 KEEP(*(.Level3InterruptVector.text)); 130 . = 0x200; 131 KEEP(*(.Level4InterruptVector.text)); 132 . = 0x240; 133 KEEP(*(.Level5InterruptVector.text)); 134 . = 0x280; 135 KEEP(*(.DebugExceptionVector.text)); 136 . = 0x2c0; 137 KEEP(*(.NMIExceptionVector.text)); 138 . = 0x300; 139 KEEP(*(.KernelExceptionVector.text)); 140 . = 0x340; 141 KEEP(*(.UserExceptionVector.text)); 142 . = 0x3C0; 143 KEEP(*(.DoubleExceptionVector.text)); 144 . = 0x400; 145 _invalid_pc_placeholder = ABSOLUTE(.); 146 *(.*Vector.literal) 147 148 *(.UserEnter.literal); 149 *(.UserEnter.text); 150 . = ALIGN (16); 151 *(.entry.text) 152 *(.init.literal) 153 *(.init) 154 _init_end = ABSOLUTE(.); 155 156 _iram_start = ABSOLUTE(.); 157 } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) 158 159 .iram0.text : ALIGN(4) 160 { 161 _iram_text_start = ABSOLUTE(.); 162 *(.iram1 .iram1.*) 163 *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) 164 *libesp32.a:panic.*(.literal .text .literal.* .text.*) 165 *librtc.a:(.literal .text .literal.* .text.*) 166 *libarch__xtensa__core.a:(.literal .text .literal.* .text.*) 167 *libkernel.a:(.literal .text .literal.* .text.*) 168 *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) 169 *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) 170 *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) 171 *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) 172 *libzephyr.a:windowspill_asm.*(.literal .text .literal.* .text.*) 173 *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) 174 *libdrivers__timer.a:xtensa_sys_timer.*(.literal .text .literal.* .text.*) 175 *libzephyr.a:systimer_hal.*(.literal .text .literal.* .text.*) 176 *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) 177 *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) 178 *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) 179 *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) 180 *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) 181 *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) 182 *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) 183 *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) 184 *libzephyr.a:loader.*(.literal .text .literal.* .text.*) 185 *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) 186 *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) 187 *libc.a:*(.literal .text .literal.* .text.*) 188 *libphy.a:(.phyiram .phyiram.*) 189 *libgcov.a:(.literal .text .literal.* .text.*) 190 191 . = ALIGN(16); 192 193 } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) 194 195 .flash.text : ALIGN(16) 196 { 197 _stext = .; 198 _text_start = ABSOLUTE(.); 199 200 *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) 201 *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ 202 *(.fini.literal) 203 *(.fini) 204 *(.gnu.version) 205 *(.literal .text .literal.* .text.*) 206 207 /* CPU will try to prefetch up to 16 bytes of 208 * of instructions. This means that any configuration (e.g. MMU, PMS) must allow 209 * safe access to up to 16 bytes after the last real instruction, add 210 * dummy bytes to ensure this 211 */ 212 . += 16; 213 214 _text_end = ABSOLUTE(.); 215 _etext = .; 216 217 /* Similar to _iram_start, this symbol goes here so it is 218 * resolved by addr2line in preference to the first symbol in 219 * the flash.text segment. 220 */ 221 . = ALIGN(4); 222 _flash_cache_start = ABSOLUTE(0); 223 224 . = ALIGN(4); 225 _iram_end = ABSOLUTE(.); 226 227 } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) 228 229 /* --- END OF IRAM --- */ 230 231 /* --- START OF DRAM --- */ 232 233 .dram0.dummy (NOLOAD): 234 { 235 . = ORIGIN(dram0_1_seg) + MAX(_iram_end, appcpu_iram_org) - appcpu_iram_org; 236 . = ALIGN(16); 237 } GROUP_LINK_IN(RAMABLE_REGION) 238 239 .dram0.data : 240 { 241 . = ALIGN (8); 242 __data_start = ABSOLUTE(.); 243 _data_start = ABSOLUTE(.); 244 245 *(.data) 246 *(.data.*) 247 *(.gnu.linkonce.d.*) 248 *(.data1) 249 *(.sdata) 250 *(.sdata.*) 251 *(.gnu.linkonce.s.*) 252 *(.sdata2) 253 *(.sdata2.*) 254 *(.gnu.linkonce.s2.*) 255 /* rodata for panic handler(libarch__xtensa__core.a) and all 256 * dependent functions should be placed in DRAM to avoid issue 257 * when flash cache is disabled */ 258 *libarch__xtensa__core.a:(.rodata .rodata.*) 259 *libkernel.a:fatal.*(.rodata .rodata.*) 260 *libkernel.a:init.*(.rodata .rodata.*) 261 *libzephyr.a:cbprintf_complete*(.rodata .rodata.*) 262 *libzephyr.a:systimer_hal.*(.rodata .rodata.*) 263 *libzephyr.a:log_core.*(.rodata .rodata.*) 264 *libzephyr.a:log_backend_uart.*(.rodata .rodata.*) 265 *libzephyr.a:log_output.*(.rodata .rodata.*) 266 *libzephyr.a:loader.*(.rodata .rodata.*) 267 *libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*) 268 *libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*) 269 270 . = ALIGN(4); 271 #include <snippets-rwdata.ld> 272 . = ALIGN(4); 273 274 KEEP(*(.jcr)) 275 *(.dram1 .dram1.*) 276 . = ALIGN(16); 277 278 } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) 279 280 #include <snippets-data-sections.ld> 281 #include <zephyr/linker/common-ram.ld> 282 #include <snippets-ram-sections.ld> 283 #include <zephyr/linker/cplusplus-ram.ld> 284 #include <zephyr/linker/kobject-data.ld> 285 #include <zephyr/linker/common-rom/common-rom-logging.ld> 286 287 .dram0.rodata : ALIGN(4) 288 { 289 _rodata_start = ABSOLUTE(.); 290 291 *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ 292 *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */ 293 294 __rodata_region_start = ABSOLUTE(.); 295 . = ALIGN(4); 296 #include <snippets-rodata.ld> 297 298 . = ALIGN(4); 299 *(EXCLUDE_FILE ( 300 *libarch__xtensa__core.a:* 301 *libkernel.a:fatal.* 302 *libkernel.a:init.* 303 *libzephyr.a:cbprintf_complete* 304 *libzephyr.a:log_core.* 305 *libzephyr.a:log_backend_uart.* 306 *libzephyr.a:log_output.* 307 *libzephyr.a:loader.* 308 *libdrivers__serial.a:uart_esp32.*) .rodata) 309 310 *(EXCLUDE_FILE ( 311 *libarch__xtensa__core.a:* 312 *libkernel.a:fatal.* 313 *libkernel.a:init.* 314 *libzephyr.a:cbprintf_complete* 315 *libzephyr.a:log_core.* 316 *libzephyr.a:log_backend_uart.* 317 *libzephyr.a:log_output.* 318 *libzephyr.a:loader.* 319 *libdrivers__serial.a:uart_esp32.*) .rodata.*) 320 321 . = ALIGN(4); 322 323 *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ 324 *(.gnu.linkonce.r.*) 325 *(.rodata1) 326 __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); 327 *(.xt_except_table) 328 *(.gcc_except_table .gcc_except_table.*) 329 *(.gnu.linkonce.e.*) 330 *(.gnu.version_r) 331 . = (. + 3) & ~ 3; 332 __eh_frame = ABSOLUTE(.); 333 KEEP(*(.eh_frame)) 334 . = (. + 7) & ~ 3; 335 336 /* C++ exception handlers table: */ 337 __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); 338 *(.xt_except_desc) 339 *(.gnu.linkonce.h.*) 340 __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); 341 *(.xt_except_desc_end) 342 *(.dynamic) 343 *(.gnu.version_d) 344 . = ALIGN(4); 345 __rodata_region_end = ABSOLUTE(.); 346 /* Literals are also RO data. */ 347 _lit4_start = ABSOLUTE(.); 348 *(*.lit4) 349 *(.lit4.*) 350 *(.gnu.linkonce.lit4.*) 351 _lit4_end = ABSOLUTE(.); 352 . = ALIGN(4); 353 _thread_local_start = ABSOLUTE(.); 354 *(.tdata) 355 *(.tdata.*) 356 *(.tbss) 357 *(.tbss.*) 358 *(.rodata_wlog) 359 *(.rodata_wlog*) 360 _thread_local_end = ABSOLUTE(.); 361 _rodata_reserved_end = ABSOLUTE(.); 362 . = ALIGN(4); 363 } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) 364 365 /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. 366 * Executing directly from LMA is not possible. */ 367 #include <zephyr/linker/cplusplus-rom.ld> 368 #include <zephyr/linker/common-rom/common-rom-init.ld> 369 #include <zephyr/linker/common-rom/common-rom-kernel-devices.ld> 370 #include <zephyr/linker/common-rom/common-rom-ztest.ld> 371 #include <zephyr/linker/common-rom/common-rom-net.ld> 372 #include <zephyr/linker/common-rom/common-rom-bt.ld> 373 #include <zephyr/linker/common-rom/common-rom-debug.ld> 374 #include <zephyr/linker/common-rom/common-rom-misc.ld> 375 #include <zephyr/linker/thread-local-storage.ld> 376 #include <snippets-sections.ld> 377 378 /* Create an explicit section at the end of all the data that shall be mapped into drom. 379 * This is used to calculate the size of the _image_drom_size variable */ 380 .dram0.rodata_end : ALIGN(16) 381 { 382 . = ALIGN(16); 383 _image_rodata_end = ABSOLUTE(.); 384 } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) 385 386 .dram0.end : 387 { 388 __data_end = ABSOLUTE(.); 389 _data_end = ABSOLUTE(.); 390 } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) 391 392 .dram0.noinit (NOLOAD): 393 { 394 . = ALIGN(8); 395 *(.noinit) 396 *(.noinit.*) 397 . = ALIGN(8) ; 398 } GROUP_LINK_IN(RAMABLE_REGION) 399 400 /* Shared RAM */ 401 .dram0.bss (NOLOAD) : 402 { 403 . = ALIGN (8); 404 _bss_start = ABSOLUTE(.); /* required by bluetooth library */ 405 __bss_start = ABSOLUTE(.); 406 407 *(.dynsbss) 408 *(.sbss) 409 *(.sbss.*) 410 *(.gnu.linkonce.sb.*) 411 *(.scommon) 412 *(.sbss2) 413 *(.sbss2.*) 414 *(.gnu.linkonce.sb2.*) 415 *(.dynbss) 416 *(.bss) 417 *(.bss.*) 418 *(.share.mem) 419 *(.gnu.linkonce.b.*) 420 *(COMMON) 421 . = ALIGN (8); 422 __bss_end = ABSOLUTE(.); 423 } GROUP_LINK_IN(RAMABLE_REGION) 424 425 /* Provide total SRAM usage, including IRAM and DRAM */ 426 _image_ram_start = _init_start - IRAM_DRAM_OFFSET; 427 #include <zephyr/linker/ram-end.ld> 428 429 ASSERT(((__bss_end - ORIGIN(dram0_1_seg)) <= LENGTH(dram0_1_seg)), "DRAM segment data does not fit.") 430 431 /* --- END OF DRAM --- */ 432 433#ifdef CONFIG_GEN_ISR_TABLES 434#include <zephyr/linker/intlist.ld> 435#endif 436 437#include <zephyr/linker/debug-sections.ld> 438 439 .xtensa.info 0 : { *(.xtensa.info) } 440 .xt.insn 0 : 441 { 442 KEEP (*(.xt.insn)) 443 KEEP (*(.gnu.linkonce.x.*)) 444 } 445 .xt.prop 0 : 446 { 447 KEEP (*(.xt.prop)) 448 KEEP (*(.xt.prop.*)) 449 KEEP (*(.gnu.linkonce.prop.*)) 450 } 451 .xt.lit 0 : 452 { 453 KEEP (*(.xt.lit)) 454 KEEP (*(.xt.lit.*)) 455 KEEP (*(.gnu.linkonce.p.*)) 456 } 457 .xt.profile_range 0 : 458 { 459 KEEP (*(.xt.profile_range)) 460 KEEP (*(.gnu.linkonce.profile_range.*)) 461 } 462 .xt.profile_ranges 0 : 463 { 464 KEEP (*(.xt.profile_ranges)) 465 KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) 466 } 467 .xt.profile_files 0 : 468 { 469 KEEP (*(.xt.profile_files)) 470 KEEP (*(.gnu.linkonce.xt.profile_files.*)) 471 } 472} 473 474ASSERT(((_iram_end - ORIGIN(iram0_1_seg)) <= LENGTH(iram0_1_seg)), 475 "IRAM0 segment data does not fit.") 476