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