mirror of
https://github.com/apache/nuttx.git
synced 2026-10-11 16:20:21 +00:00
The common Xtensa BUILD_KERNEL support needs the chip to say what it can do and where its memory goes. The chip selects the address environment options it now implements, keeps the kernel and user heaps apart, and the linker scripts separate kernel from user text and data so the two worlds can be given different permissions. kernel_oct configures a board for it, with the user-program layout and the boot ROMFS a kernel build loads its programs from. The ROMFS placeholder is rebuilt with the image, the generated copy is ignored, and the programs are given stack sizes and room for a fork() child. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
484 lines
15 KiB
Text
484 lines
15 KiB
Text
/****************************************************************************
|
|
* boards/xtensa/esp32s3/common/scripts/legacy_sections.ld
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
/* A kernel build archives the architecture objects into libkarch.a rather
|
|
* than libarch.a, so the placement rules below have to name the right one.
|
|
* Getting this wrong is silent and fatal: the octal-flash bring-up functions
|
|
* stay in mapped flash and are called while that mapping is being
|
|
* reconfigured.
|
|
*/
|
|
|
|
#ifdef CONFIG_BUILD_KERNEL
|
|
# define ARCHLIB *libkarch.a
|
|
#else
|
|
# define ARCHLIB *libarch.a
|
|
#endif
|
|
|
|
/* Default entry point: */
|
|
|
|
ENTRY(__start);
|
|
|
|
_diram_i_start = 0x40378000;
|
|
|
|
SECTIONS
|
|
{
|
|
/* Send .iram0 code to iram */
|
|
|
|
.iram0.vectors :
|
|
{
|
|
_iram_start = ABSOLUTE(.);
|
|
|
|
/* Vectors go to IRAM. */
|
|
|
|
_init_start = ABSOLUTE(.);
|
|
|
|
/* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
|
|
|
|
. = 0x0;
|
|
KEEP (*(.window_vectors.text));
|
|
. = 0x180;
|
|
KEEP (*(.xtensa_level2_vector.text));
|
|
. = 0x1c0;
|
|
KEEP (*(.xtensa_level3_vector.text));
|
|
. = 0x200;
|
|
KEEP (*(.xtensa_level4_vector.text));
|
|
. = 0x240;
|
|
KEEP (*(.xtensa_level5_vector.text));
|
|
. = 0x280;
|
|
KEEP (*(.debug_exception_vector.text));
|
|
. = 0x2c0;
|
|
KEEP (*(.nmi_vector.text));
|
|
. = 0x300;
|
|
KEEP (*(.kernel_exception_vector.text));
|
|
. = 0x340;
|
|
KEEP (*(.user_exception_vector.text));
|
|
. = 0x3c0;
|
|
KEEP (*(.double_exception_vector.text));
|
|
. = 0x400;
|
|
*(.*_vector.literal)
|
|
|
|
. = ALIGN(16);
|
|
|
|
*(.entry.text)
|
|
*(.init.literal)
|
|
*(.init)
|
|
} >iram0_0_seg
|
|
|
|
.iram0.text :
|
|
{
|
|
/* Code marked as running out of IRAM */
|
|
|
|
*(.iram1 .iram1.*)
|
|
|
|
ARCHLIB:esp32s3_cpuindex.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:esp32s3_user.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:esp32s3_spiflash.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:xtensa_assert.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:xtensa_cpuint.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:xtensa_cpupause.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:xtensa_irqdispatch.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:xtensa_modifyreg32.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:xtensa_testset.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:esp_app_desc.*(.literal .text .literal.* .text.*)
|
|
|
|
ARCHLIB:*esp_rom_spiflash.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:*esp_rom_cache_esp32s2_esp32s3.*(.literal .text .literal.* .text.*)
|
|
|
|
*libc.a:sq_remlast.*(.literal .text .literal.* .text.*)
|
|
|
|
*libdrivers.a:syslog_flush.*(.literal .text .literal.* .text.*)
|
|
|
|
*libsched.a:assert.*(.literal .text .literal.* .text.*)
|
|
*libsched.a:irq_csection.*(.literal .text .literal.* .text.*)
|
|
*libsched.a:irq_dispatch.*(.literal .text .literal.* .text.*)
|
|
*libsched.a:irq_spinlock.*(.literal .text .literal.* .text.*)
|
|
*libsched.a:sched_lock.*(.literal .text .literal.* .text.*)
|
|
*libsched.a:sched_note.*(.literal .text .literal.* .text.*)
|
|
*libsched.a:sched_suspendscheduler.*(.literal .text .literal.* .text.*)
|
|
*libsched.a:sched_thistask.*(.literal .text .literal.* .text.*)
|
|
*libsched.a:sched_unlock.*(.literal .text .literal.* .text.*)
|
|
*libsched.a:spinlock.*(.literal .text .literal.* .text.*)
|
|
*libsched.a:stack_record.*(.literal .text .literal.* .text.*)
|
|
|
|
*libc.a:*lib_instrument.*(.literal .text .literal.* .text.*)
|
|
*libc.a:arch_atomic.*(.literal .text .literal.* .text.*)
|
|
|
|
#ifdef CONFIG_ESP32S3_SPEED_UP_ISR
|
|
ARCHLIB:xtensa_switchcontext.*(.literal.up_switch_context .text.up_switch_context)
|
|
|
|
ARCHLIB:esp32s3_timerisr.*(.literal.systimer_isr .text.systimer_isr)
|
|
ARCHLIB:esp32s3_idle.*(.literal.up_idle .text.up_idle)
|
|
ARCHLIB:esp32s3_dma.*(.literal.esp32s3_dma_load .text.esp32s3_dma_load \
|
|
.literal.esp32s3_dma_enable .text.esp32s3_dma_enable)
|
|
|
|
*libsched.a:sched_processtimer.*(.literal.nxsched_process_timer .text.nxsched_process_timer)
|
|
*libsched.a:clock_initialize.*(.literal.clock_timer .text.clock_timer)
|
|
*libsched.a:wd_start.*(.literal.wd_timer .text.wd_timer)
|
|
*libsched.a:sched_roundrobin.*(.literal.nxsched_process_roundrobin .text.nxsched_process_roundrobin)
|
|
*libsched.a:sched_reprioritizertr.*(.literal.nxsched_reprioritize_rtr .text.nxsched_reprioritize_rtr)
|
|
*libsched.a:sched_removereadytorun.*(.literal.nxsched_remove_readytorun .text.nxsched_remove_readytorun)
|
|
*libsched.a:sched_addreadytorun.*(.literal.nxsched_add_readytorun .text.nxsched_add_readytorun)
|
|
*libsched.a:sched_addprioritized.*(.literal.nxsched_add_prioritized .text.nxsched_add_prioritized)
|
|
*libsched.a:sched_mergepending.*(.literal.nxsched_merge_pending .text.nxsched_merge_pending)
|
|
|
|
*libc.a:sq_remfirst.*(.literal.sq_remfirst .text.sq_remfirst)
|
|
#endif
|
|
|
|
ARCHLIB:esp32s3_spi_timing.*(.literal .text .literal.* .text.*)
|
|
#ifdef CONFIG_ESP32S3_SPIRAM_MODE_QUAD
|
|
ARCHLIB:esp32s3_psram_quad.*(.literal .text .literal.* .text.*)
|
|
#endif
|
|
#ifdef CONFIG_ESP32S3_SPIRAM_MODE_OCT
|
|
ARCHLIB:esp32s3_psram_octal.*(.literal .text .literal.* .text.*)
|
|
#endif
|
|
#if defined(CONFIG_STACK_CANARIES) && \
|
|
(defined(CONFIG_ESP32S3_SPIFLASH) || \
|
|
defined(CONFIG_ESP32S3_SPIRAM))
|
|
*libc.a:lib_stackchk.*(.literal .text .literal.* .text.*)
|
|
#endif
|
|
ARCHLIB:*cache_hal.*(.text .text.* .literal .literal.*)
|
|
ARCHLIB:*esp_rom_cache_esp32s2_esp32s3.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:esp_cache.*(.literal .literal.* .text .text.*)
|
|
ARCHLIB:cache_utils.*(.literal .literal.* .text .text.*)
|
|
ARCHLIB:spi_flash_hal_iram.*(.literal .literal.* .text .text.*)
|
|
ARCHLIB:spi_flash_hal_gpspi.*(.literal .literal.* .text .text.*)
|
|
ARCHLIB:spi_flash_encrypt_hal_iram.*(.text .text.* .literal .literal.*)
|
|
ARCHLIB:spi_flash_chip*.*(.literal .literal.* .text .text.*)
|
|
ARCHLIB:spi_flash_wrap.*(.literal .literal.* .text .text.*)
|
|
ARCHLIB:esp_spiflash.*(.literal .text .literal.* .text.*)
|
|
ARCHLIB:esp_flash_spi_init.*(.text .text.* .literal .literal.*)
|
|
ARCHLIB:esp_flash_api.*(.text .text.* .literal .literal.*)
|
|
ARCHLIB:spi_flash_os_func*.*(.literal .literal.* .text .text.*)
|
|
ARCHLIB:*flash_brownout_hook.*(.literal .literal.* .text .text.*)
|
|
ARCHLIB:memspi_host_driver.*(.literal .literal.* .text .text.*)
|
|
|
|
*(.wifirxiram .wifirxiram.*)
|
|
*(.wifi0iram .wifi0iram.*)
|
|
*(.wifiorslpiram .wifiorslpiram.*)
|
|
*(.wifislpiram .wifislpiram.*)
|
|
*(.wifislprxiram .wifislprxiram.*)
|
|
*(.phyiram .phyiram.*)
|
|
|
|
/* align + add 16B for CPU dummy speculative instr. fetch */
|
|
|
|
. = ALIGN(4) + 16;
|
|
|
|
_iram_text = ABSOLUTE(.);
|
|
} >iram0_0_seg
|
|
|
|
.dram0.dummy (NOLOAD) :
|
|
{
|
|
/* This section is required to skip .iram0.text area because iram0_0_seg
|
|
* and dram0_0_seg reflect the same address space on different buses.
|
|
*/
|
|
|
|
. = ORIGIN(dram0_0_seg) + MAX(_iram_end, _diram_i_start) - _diram_i_start;
|
|
} >dram0_0_seg
|
|
|
|
/* Shared RAM */
|
|
|
|
.dram0.bss (NOLOAD) :
|
|
{
|
|
/* .bss initialized on power-up */
|
|
|
|
. = ALIGN(8);
|
|
_sbss = ABSOLUTE(.);
|
|
|
|
*(.bss .bss.*)
|
|
*(COMMON)
|
|
*(.dynsbss)
|
|
*(.sbss)
|
|
*(.sbss.*)
|
|
*(.gnu.linkonce.sb.*)
|
|
*(.scommon)
|
|
*(.sbss2)
|
|
*(.sbss2.*)
|
|
*(.gnu.linkonce.sb2.*)
|
|
*(.dynbss)
|
|
*(.share.mem)
|
|
*(.gnu.linkonce.b.*)
|
|
|
|
. = ALIGN(8);
|
|
_ebss = ABSOLUTE(.);
|
|
} >dram0_0_seg
|
|
|
|
.noinit (NOLOAD) :
|
|
{
|
|
/* This section contains data that is not initialized during load,
|
|
* or during the application's initialization sequence.
|
|
*/
|
|
|
|
. = ALIGN(4);
|
|
|
|
*(.noinit .noinit.*)
|
|
|
|
. = ALIGN(4);
|
|
} >dram0_0_seg
|
|
|
|
.dram0.data :
|
|
{
|
|
/* .data initialized on power-up in ROMed configurations. */
|
|
|
|
_sdata = ABSOLUTE(.);
|
|
KEEP (*(.data))
|
|
KEEP (*(.data.*))
|
|
KEEP (*(.gnu.linkonce.d.*))
|
|
KEEP (*(.data1))
|
|
KEEP (*(.sdata))
|
|
KEEP (*(.sdata.*))
|
|
KEEP (*(.gnu.linkonce.s.*))
|
|
KEEP (*(.sdata2))
|
|
KEEP (*(.sdata2.*))
|
|
KEEP (*(.gnu.linkonce.s2.*))
|
|
KEEP (*(.jcr))
|
|
*(.dram1 .dram1.*)
|
|
|
|
*libphy.a:(.rodata .rodata.*)
|
|
ARCHLIB:xtensa_context.*(.rodata .rodata.*)
|
|
ARCHLIB:*cache_hal.*(.rodata .rodata.*)
|
|
#if defined(CONFIG_STACK_CANARIES) && \
|
|
(defined(CONFIG_ESP32S3_SPIFLASH) || \
|
|
defined(CONFIG_ESP32S3_SPIRAM))
|
|
*libc.a:lib_stackchk.*(.rodata .rodata.*)
|
|
#endif
|
|
|
|
ARCHLIB:esp_cache.*(.rodata .rodata.*)
|
|
ARCHLIB:cache_utils.*(.rodata .rodata.*)
|
|
ARCHLIB:spi_flash_hal_iram.*(.rodata .rodata.*)
|
|
ARCHLIB:spi_flash_hal_gpspi.*(.rodata .rodata.*)
|
|
ARCHLIB:spi_flash_encrypt_hal_iram.*(.rodata .rodata.*)
|
|
ARCHLIB:spi_flash_chip*.*(.rodata .rodata.*)
|
|
ARCHLIB:spi_flash_wrap.*(.rodata .rodata.*)
|
|
ARCHLIB:esp_spiflash.*(.rodata .rodata.*)
|
|
ARCHLIB:esp_flash_spi_init.*(.rodata .rodata.*)
|
|
ARCHLIB:esp_flash_api.*(.rodata .rodata.*)
|
|
ARCHLIB:spi_flash_os_func*.*(.rodata .rodata.*)
|
|
ARCHLIB:flash_brownout_hook.*(.rodata .rodata.*)
|
|
ARCHLIB:memspi_host_driver.*(.rodata .rodata.*)
|
|
*libc.a:arch_atomic.*(.rodata .rodata.*)
|
|
_edata = ABSOLUTE(.);
|
|
. = ALIGN(4);
|
|
|
|
/* Heap starts at the end of .data */
|
|
|
|
_sheap = ABSOLUTE(.);
|
|
} >dram0_0_seg
|
|
|
|
.flash.text :
|
|
{
|
|
_stext = .;
|
|
_instruction_reserved_start = ABSOLUTE(.);
|
|
|
|
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
|
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
|
|
*(.fini.literal)
|
|
*(.fini)
|
|
*(.gnu.version)
|
|
|
|
*(EXCLUDE_FILE(*libnet80211.a *libpp.a) .wifi0iram EXCLUDE_FILE(*libnet80211.a *libpp.a) .wifi0iram.*)
|
|
*(.wifiextrairam .wifiextrairam.*)
|
|
*(EXCLUDE_FILE(*libpp.a) .wifiorslpiram EXCLUDE_FILE(*libpp.a) .wifiorslpiram.*)
|
|
*(EXCLUDE_FILE(*libnet80211.a *libpp.a) .wifirxiram EXCLUDE_FILE(*libnet80211.a *libpp.a) .wifirxiram.*)
|
|
*(.wifislpiram .wifislpiram.*)
|
|
*(EXCLUDE_FILE(*libnet80211.a *libpp.a) .wifislprxiram EXCLUDE_FILE(*libnet80211.a *libpp.a) .wifislprxiram.*)
|
|
|
|
/* CPU will try to prefetch up to 16 bytes of instructions.
|
|
* This means that any configuration (e.g. MMU, PMS) must allow
|
|
* safe access to up to 16 bytes after the last real instruction, add
|
|
* dummy bytes to ensure this
|
|
*/
|
|
|
|
. += 16;
|
|
|
|
_instruction_reserved_end = ABSOLUTE(.);
|
|
_etext = .;
|
|
} >default_code_seg
|
|
|
|
.flash_rodata_dummy (NOLOAD) :
|
|
{
|
|
/* This dummy section represents the .flash.text section but in default_rodata_seg.
|
|
* Thus, it must have its alignment and (at least) its size.
|
|
*/
|
|
|
|
/* Start at the same alignment constraint than .flash.text */
|
|
|
|
. = ALIGN(ALIGNOF(.flash.text));
|
|
|
|
/* Create an empty gap as big as .flash.text section */
|
|
|
|
. = SIZEOF(.flash.text);
|
|
|
|
/* Prepare the alignment of the section above. Few bytes (0x20) must be
|
|
* added for the mapping header.
|
|
*/
|
|
|
|
. = ALIGN(0x10000) + 0x20;
|
|
} >default_rodata_seg
|
|
|
|
.flash.rodata : ALIGN(0x10)
|
|
{
|
|
_rodata_reserved_start = ABSOLUTE(.);
|
|
_srodata = ABSOLUTE(.);
|
|
|
|
/* !DO NOT PUT ANYTHING BEFORE THIS! */
|
|
/* Should be the first. App version info. */
|
|
*(.rodata_desc .rodata_desc.*)
|
|
|
|
*(.rodata)
|
|
*(.rodata.*)
|
|
#ifdef CONFIG_ESPRESSIF_WIRELESS
|
|
*(.rodata_wlog_verbose.*)
|
|
*(.rodata_wlog_debug.*)
|
|
*(.rodata_wlog_info.*)
|
|
*(.rodata_wlog_warning.*)
|
|
*(.rodata_wlog_error.*)
|
|
#endif
|
|
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
|
*(.gnu.linkonce.r.*)
|
|
*(.rodata1)
|
|
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
|
|
*(.xt_except_table)
|
|
*(.gcc_except_table)
|
|
*(.gcc_except_table.*)
|
|
*(.gnu.linkonce.e.*)
|
|
*(.gnu.version_r)
|
|
*(.eh_frame)
|
|
|
|
. = ALIGN(4);
|
|
|
|
/* C++ constructor and destructor tables, properly ordered: */
|
|
|
|
_sinit = ABSOLUTE(.);
|
|
__init_array_start = ABSOLUTE(.);
|
|
KEEP (*crtbegin.o(.ctors))
|
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
|
KEEP (*(SORT(.ctors.*)))
|
|
KEEP (*(.ctors))
|
|
__init_array_end = ABSOLUTE(.);
|
|
_einit = ABSOLUTE(.);
|
|
KEEP (*crtbegin.o(.dtors))
|
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
|
KEEP (*(SORT(.dtors.*)))
|
|
KEEP (*(.dtors))
|
|
|
|
/* System init functions registered via ESP_SYSTEM_INIT_FN */
|
|
|
|
. = ALIGN(4);
|
|
_esp_system_init_fn_array_start = ABSOLUTE(.);
|
|
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
|
|
_esp_system_init_fn_array_end = ABSOLUTE(.);
|
|
|
|
/* C++ exception handlers table: */
|
|
|
|
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
|
|
*(.xt_except_desc)
|
|
*(.gnu.linkonce.h.*)
|
|
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
|
*(.xt_except_desc_end)
|
|
*(.dynamic)
|
|
*(.gnu.version_d)
|
|
_erodata = ABSOLUTE(.);
|
|
|
|
/* Literals are also RO data. */
|
|
|
|
_lit4_start = ABSOLUTE(.);
|
|
*(*.lit4)
|
|
*(.lit4.*)
|
|
*(.gnu.linkonce.lit4.*)
|
|
_lit4_end = ABSOLUTE(.);
|
|
_rodata_reserved_end = ABSOLUTE(.);
|
|
. = ALIGN(4);
|
|
} >default_rodata_seg
|
|
|
|
/* Marks the end of IRAM code segment */
|
|
|
|
.iram0.text_end (NOLOAD) :
|
|
{
|
|
/* ESP32-S3 memprot requires 16B padding for possible CPU prefetch and
|
|
* 256B alignment for PMS split lines.
|
|
*/
|
|
|
|
. += 16;
|
|
. = ALIGN(256);
|
|
} >iram0_0_seg
|
|
|
|
.iram0.data :
|
|
{
|
|
. = ALIGN(4);
|
|
|
|
*(.iram.data)
|
|
*(.iram.data.*)
|
|
} >iram0_0_seg
|
|
|
|
.iram0.bss (NOLOAD) :
|
|
{
|
|
. = ALIGN(4);
|
|
|
|
*(.iram.bss)
|
|
*(.iram.bss.*)
|
|
|
|
. = ALIGN(4);
|
|
_iram_end = ABSOLUTE(.);
|
|
} >iram0_0_seg
|
|
|
|
/* RTC BSS section. */
|
|
|
|
.rtc.bss (NOLOAD) :
|
|
{
|
|
*(.rtc.bss)
|
|
} >rtc_slow_seg
|
|
|
|
.rtc.data :
|
|
{
|
|
. = ALIGN(4);
|
|
*(.rtc.data)
|
|
*(.rtc.data.*)
|
|
*(.rtc.rodata)
|
|
*(.rtc.rodata.*)
|
|
|
|
/* Whatever is left from the RTC memory is used as a special heap. */
|
|
|
|
. = ALIGN (4);
|
|
_srtcheap = ABSOLUTE(.);
|
|
} > rtc_slow_seg
|
|
|
|
/* This section holds RTC data that should have fixed addresses.
|
|
* The data are not initialized at power-up and are retained during deep sleep.
|
|
*/
|
|
|
|
.rtc_reserved (NOLOAD):
|
|
{
|
|
. = ALIGN(4);
|
|
_rtc_reserved_start = ABSOLUTE(.);
|
|
|
|
/* New data can only be added here to ensure existing data are not moved.
|
|
* Because data have adhered to the end of the segment and code is relied on it.
|
|
* >> put new data here <<
|
|
*/
|
|
|
|
*(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*)
|
|
KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*))
|
|
_rtc_reserved_end = ABSOLUTE(.);
|
|
} > rtc_reserved_seg
|
|
}
|