mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
refactor(ulp): assemble LP-core linker scripts from base, layout and checks
This commit is contained in:
@@ -1,120 +1,16 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* LP-core RISC-V linker script, assembled from base + layout + checks.
|
||||
* A custom layout replaces the default via LP_CORE_LINKER_INCLUDE.
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
#include "ld.common"
|
||||
#if CONFIG_ULP_COPROC_RUN_FROM_HP_MEM
|
||||
#include "ld.hp_mem_defs"
|
||||
#endif
|
||||
#include "lp_core_riscv_base.ld.in"
|
||||
|
||||
#if CONFIG_ESP_ROM_HAS_LP_ROM
|
||||
/* With LP-ROM memory layout is different due to LP ROM stack/data */
|
||||
/* For P4 ECO5 we also reserve some RTC MEM at the first for MSPI workaround */
|
||||
#define ULP_MEM_START_ADDRESS SOC_RTC_DRAM_LOW + RESERVE_RTC_MEM + MSPI_WORKAROUND_SIZE
|
||||
#ifdef LP_CORE_LINKER_INCLUDE
|
||||
#include LP_CORE_LINKER_INCLUDE
|
||||
#else
|
||||
#define ULP_MEM_START_ADDRESS (SOC_RTC_DRAM_LOW)
|
||||
#include "lp_core_riscv_default_layout.ld.in"
|
||||
#endif
|
||||
|
||||
#define ALIGN_DOWN(SIZE, AL) (SIZE & ~(AL - 1))
|
||||
/* Ensure the end where the shared memory starts is aligned to 8 bytes
|
||||
if updating this also update the same in ulp_lp_core_memory_shared.c
|
||||
*/
|
||||
#define ALIGNED_COPROC_MEM ALIGN_DOWN(CONFIG_ULP_COPROC_RESERVE_MEM, 0x8)
|
||||
|
||||
ENTRY(reset_vector)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* First 128 bytes for exception/interrupt vectors */
|
||||
vector_table(RX) : ORIGIN = ULP_MEM_START_ADDRESS, LENGTH = 0x80
|
||||
lp_ram(RWX) : ORIGIN = ULP_MEM_START_ADDRESS + 0x80, LENGTH = ALIGNED_COPROC_MEM - 0x80 - CONFIG_ULP_SHARED_MEM
|
||||
shared_mem_ram(RW) : ORIGIN = ULP_MEM_START_ADDRESS + ALIGNED_COPROC_MEM - CONFIG_ULP_SHARED_MEM, LENGTH = CONFIG_ULP_SHARED_MEM
|
||||
#if CONFIG_ULP_COPROC_RUN_FROM_HP_MEM
|
||||
hp_ram(RWX) : ORIGIN = ULP_HP_MEM_START, LENGTH = ULP_HP_MEM_SIZE
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ULP_COPROC_RUN_FROM_HP_MEM
|
||||
REGION_ALIAS("default_app_seg", hp_ram);
|
||||
#else
|
||||
REGION_ALIAS("default_app_seg", lp_ram);
|
||||
#endif
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.vector.text :
|
||||
{
|
||||
/* Exception/interrupt vectors */
|
||||
__mtvec_base = .;
|
||||
KEEP (*(.init.vector .init.vector.*))
|
||||
} > vector_table
|
||||
|
||||
. = ORIGIN(lp_ram);
|
||||
|
||||
/* Interrupt/exception handlers stay in LP RAM (reachable on wakeup before HP SRAM is up). */
|
||||
.rtc_text ALIGN(4):
|
||||
{
|
||||
_lp_text_start = .;
|
||||
*(.text.vectors) /* Default reset vector must link to offset 0x80 */
|
||||
*(.text.handlers)
|
||||
*(.text.handlers.*)
|
||||
} > lp_ram
|
||||
|
||||
#if CONFIG_ULP_COPROC_RUN_FROM_HP_MEM
|
||||
/* End of LP-resident code (handlers only); align to 128 bytes. */
|
||||
. = ALIGN(128);
|
||||
_lp_text_end = .;
|
||||
. = ORIGIN(hp_ram);
|
||||
#endif
|
||||
|
||||
.text ALIGN(4):
|
||||
{
|
||||
*(.text)
|
||||
*(.text*)
|
||||
} > default_app_seg
|
||||
|
||||
.rodata ALIGN(4):
|
||||
{
|
||||
*(.rodata)
|
||||
*(.rodata*)
|
||||
} > default_app_seg
|
||||
|
||||
/* 128-byte alignment required for PMP TOR granularity (SOC_CPU_PMP_REGION_GRANULARITY) */
|
||||
. = ALIGN(128);
|
||||
#if !CONFIG_ULP_COPROC_RUN_FROM_HP_MEM
|
||||
_lp_text_end = .;
|
||||
#endif
|
||||
_lp_data_start = .;
|
||||
|
||||
.data ALIGN(4):
|
||||
{
|
||||
_data_start = .;
|
||||
*(.data)
|
||||
*(.data*)
|
||||
*(.sdata)
|
||||
*(.sdata*)
|
||||
_data_end = .;
|
||||
} > default_app_seg
|
||||
|
||||
.bss ALIGN(4) :
|
||||
{
|
||||
_bss_start = .;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(.sbss)
|
||||
*(.sbss*)
|
||||
PROVIDE(end = .);
|
||||
_bss_end = .;
|
||||
} > default_app_seg
|
||||
|
||||
__stack_top = ORIGIN(lp_ram) + LENGTH(lp_ram);
|
||||
|
||||
. = ORIGIN(shared_mem_ram);
|
||||
.shared_mem (ALIGN(4)) :
|
||||
{
|
||||
KEEP(*(.shared_mem))
|
||||
} > shared_mem_ram
|
||||
}
|
||||
#include "lp_core_riscv_checks.ld.in"
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Base part of the LP-core linker script (base + layout + checks). It defines:
|
||||
* - the usable LP-RAM window bounds LP_CORE_USER_MEMORY_REGION_START and
|
||||
* LP_CORE_USER_MEMORY_REGION_END;
|
||||
* - ENTRY, the interrupt vector table, the HP/LP shared-memory section and a
|
||||
* default __stack_top;
|
||||
* - the section-boundary macros a custom layout composes: LP_CORE_TEXT_START,
|
||||
* LP_CORE_TEXT_END, LP_CORE_DATA_START and LP_CORE_DATA_END, plus the
|
||||
* LP_CORE_DEFAULT_TEXT / LP_CORE_DEFAULT_DATA convenience macros used by the
|
||||
* default layout.
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
#include "ld.common"
|
||||
#if CONFIG_ULP_COPROC_RUN_FROM_HP_MEM
|
||||
#include "ld.hp_mem_defs"
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_ROM_HAS_LP_ROM
|
||||
/* With LP-ROM memory layout is different due to LP ROM stack/data */
|
||||
/* For P4 ECO5 we also reserve some RTC MEM at the first for MSPI workaround */
|
||||
#define ULP_MEM_START_ADDRESS SOC_RTC_DRAM_LOW + RESERVE_RTC_MEM + MSPI_WORKAROUND_SIZE
|
||||
#else
|
||||
#define ULP_MEM_START_ADDRESS (SOC_RTC_DRAM_LOW)
|
||||
#endif
|
||||
|
||||
#define ALIGN_DOWN(SIZE, AL) (SIZE & ~(AL - 1))
|
||||
/* Ensure the end where the shared memory starts is aligned to 8 bytes
|
||||
if updating this also update the same in ulp_lp_core_memory_shared.c
|
||||
*/
|
||||
#define ALIGNED_COPROC_MEM ALIGN_DOWN(CONFIG_ULP_COPROC_RESERVE_MEM, 0x8)
|
||||
#define ULP_VECTOR_TABLE_LENGTH 0x80
|
||||
|
||||
/* Free LP-RAM window a layout may use, between the vector table and shared memory. */
|
||||
#define LP_CORE_USER_MEMORY_REGION_START (ULP_MEM_START_ADDRESS + ULP_VECTOR_TABLE_LENGTH)
|
||||
#define LP_CORE_USER_MEMORY_REGION_END (ULP_MEM_START_ADDRESS + ALIGNED_COPROC_MEM - CONFIG_ULP_SHARED_MEM)
|
||||
|
||||
/*
|
||||
* Section-boundary macros a custom layout composes at each region boundary.
|
||||
* ESP-IDF injects any config-dependent handling here, so the layout composes
|
||||
* them the same way regardless of the active configuration.
|
||||
*/
|
||||
|
||||
/* Reset vector and early handlers at the boot offset, placed first in `region`
|
||||
(which must start at LP_CORE_USER_MEMORY_REGION_START). */
|
||||
#define LP_CORE_TEXT_START(region) \
|
||||
. = ORIGIN(region) ; \
|
||||
.rtc_text ALIGN(4) : { \
|
||||
*(.text.vectors) /* Reset vector must link to offset 0x80 */ \
|
||||
*(.text.handlers) \
|
||||
*(.text.handlers.*) \
|
||||
} > region
|
||||
|
||||
/* End of the executable region in LP RAM: the RX/RW boundary the PMP setup uses
|
||||
under memory protection. (Memory protection and running from HP RAM are
|
||||
mutually exclusive, so the boundary always follows the LP-RAM .text here.) */
|
||||
#if CONFIG_ULP_LP_CORE_MEMPROT
|
||||
#define LP_CORE_TEXT_END() . = ALIGN(128) ; _lp_text_end = . ;
|
||||
#else
|
||||
#define LP_CORE_TEXT_END()
|
||||
#endif
|
||||
|
||||
/* Start of the writable data region. */
|
||||
#define LP_CORE_DATA_START() . = ALIGN(128) ; _lp_data_start = . ;
|
||||
|
||||
/* End of the writable data region, before the stack. Marks the lowest address
|
||||
the stack may descend to: the framework derives the default __stack_size from
|
||||
it and bounds-checks the stack against it. A layout must compose this (or
|
||||
assign _lp_data_end directly). */
|
||||
#define LP_CORE_DATA_END() . = ALIGN(4) ; _lp_data_end = . ;
|
||||
|
||||
/* Convenience: standard executable and data section placement into `region`. */
|
||||
#define LP_CORE_DEFAULT_TEXT(region) \
|
||||
.text ALIGN(4) : { *(.text) *(.text*) } > region \
|
||||
.rodata ALIGN(4) : { *(.rodata) *(.rodata*) } > region
|
||||
#define LP_CORE_DEFAULT_DATA(region) \
|
||||
.data ALIGN(4) : { _data_start = . ; *(.data) *(.data*) *(.sdata) *(.sdata*) _data_end = . ; } > region \
|
||||
.bss ALIGN(4) : { _bss_start = . ; *(.bss) *(.bss*) *(.sbss) *(.sbss*) PROVIDE(end = .) ; _bss_end = . ; } > region
|
||||
|
||||
/* Default stack top, at the top of the usable window. A layout whose data does
|
||||
not reach the window end may override it to the top of its own data region.
|
||||
The companion __stack_size defaults to __stack_top - _lp_data_end (computed in
|
||||
the checks part, once the layout has placed its data); a layout may override
|
||||
either. Both are weak defaults, so a custom layout can take ownership. */
|
||||
PROVIDE(__stack_top = LP_CORE_USER_MEMORY_REGION_END);
|
||||
|
||||
ENTRY(reset_vector)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* First 128 bytes for exception/interrupt vectors */
|
||||
vector_table(RX) : ORIGIN = ULP_MEM_START_ADDRESS, LENGTH = ULP_VECTOR_TABLE_LENGTH
|
||||
shared_mem_ram(RW) : ORIGIN = LP_CORE_USER_MEMORY_REGION_END, LENGTH = CONFIG_ULP_SHARED_MEM
|
||||
#if CONFIG_ULP_COPROC_RUN_FROM_HP_MEM
|
||||
hp_ram(RWX) : ORIGIN = ULP_HP_MEM_START, LENGTH = ULP_HP_MEM_SIZE
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.vector.text :
|
||||
{
|
||||
/* Exception/interrupt vectors */
|
||||
__mtvec_base = .;
|
||||
KEEP (*(.init.vector .init.vector.*))
|
||||
} > vector_table
|
||||
|
||||
/* Shared memory, agreed with ulp_lp_core_memory_shared.c. */
|
||||
. = ORIGIN(shared_mem_ram);
|
||||
_lp_shared_start = ORIGIN(shared_mem_ram);
|
||||
.shared_mem (ALIGN(4)) : { KEEP(*(.shared_mem)) } > shared_mem_ram
|
||||
|
||||
/* Position the location counter at the window start so the layout part's
|
||||
sections flow into their region. A layout that omits LP_CORE_TEXT_START
|
||||
is then caught by the checks part instead of an obscure overflow. */
|
||||
. = LP_CORE_USER_MEMORY_REGION_START;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Checks part (base + layout + checks). Link-time ASSERTs that catch
|
||||
* misplacement, overflow, and missing symbols in the layout part.
|
||||
*/
|
||||
ASSERT(DEFINED(reset_vector),
|
||||
"LP core linker: reset_vector is not defined")
|
||||
|
||||
ASSERT(__mtvec_base == ULP_MEM_START_ADDRESS,
|
||||
"LP core linker: vector table is not at the reserved LP base")
|
||||
|
||||
ASSERT(reset_vector == LP_CORE_USER_MEMORY_REGION_START,
|
||||
"LP core linker: reset vector is not at the required offset")
|
||||
|
||||
/* The layout must mark the end of writable data so the framework can size and
|
||||
bounds-check the stack. */
|
||||
ASSERT(DEFINED(_lp_data_end),
|
||||
"LP core linker: end of writable data is not marked; compose LP_CORE_DATA_END() (or assign _lp_data_end) in the layout")
|
||||
|
||||
/* Default stack size: all free space between the data end and the stack top.
|
||||
A layout that assigns __stack_size wins (PROVIDE yields and does not evaluate
|
||||
the expression). */
|
||||
PROVIDE(__stack_size = __stack_top - _lp_data_end);
|
||||
|
||||
ASSERT(__stack_top <= _lp_shared_start,
|
||||
"LP core linker: application overruns into the reserved shared-memory region")
|
||||
|
||||
ASSERT(__stack_top <= ULP_MEM_START_ADDRESS + ALIGNED_COPROC_MEM,
|
||||
"LP core linker: image exceeds the reserved LP coprocessor memory")
|
||||
|
||||
/* The stack grows down from __stack_top for __stack_size bytes; its lowest
|
||||
address must not descend into the data region. */
|
||||
ASSERT(__stack_top - __stack_size >= _lp_data_end,
|
||||
"LP core linker: stack region overlaps the data region (__stack_size too large or __stack_top too low)")
|
||||
|
||||
#if CONFIG_ULP_LP_CORE_MEMPROT
|
||||
ASSERT(DEFINED(_lp_text_end),
|
||||
"LP core linker: _lp_text_end must be defined when CONFIG_ULP_LP_CORE_MEMPROT is enabled (it marks the RX/RW boundary used by the PMP setup)")
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Default layout part (base + layout + checks). Replaced by a custom layout
|
||||
* when LP_CORE_LINKER_INCLUDE is set via the LINKER_LAYOUT option. Routes the
|
||||
* application to HP RAM when CONFIG_ULP_COPROC_RUN_FROM_HP_MEM is enabled.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
lp_ram(RWX) : ORIGIN = LP_CORE_USER_MEMORY_REGION_START, LENGTH = LP_CORE_USER_MEMORY_REGION_END - LP_CORE_USER_MEMORY_REGION_START
|
||||
}
|
||||
|
||||
#if CONFIG_ULP_COPROC_RUN_FROM_HP_MEM
|
||||
REGION_ALIAS("default_app_seg", hp_ram);
|
||||
#else
|
||||
REGION_ALIAS("default_app_seg", lp_ram);
|
||||
#endif
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
LP_CORE_TEXT_START(lp_ram)
|
||||
#if CONFIG_ULP_COPROC_RUN_FROM_HP_MEM
|
||||
. = ORIGIN(hp_ram);
|
||||
#endif
|
||||
|
||||
LP_CORE_DEFAULT_TEXT(default_app_seg)
|
||||
|
||||
LP_CORE_TEXT_END()
|
||||
LP_CORE_DATA_START()
|
||||
|
||||
LP_CORE_DEFAULT_DATA(default_app_seg)
|
||||
|
||||
LP_CORE_DATA_END()
|
||||
}
|
||||
Reference in New Issue
Block a user