mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(esp_system): allow .bss to spill over into L2MEM above 0x4ff40000
This commit introduce SOC_MEM_NON_CONTIGUOUS_SRAM flag (that enebled for esp32p4). If SOC_MEM_NON_CONTIGUOUS_SRAM is enabled: - LDFLAGS+=--enable-non-contiguous-regions - ldgen.py replaces "arrays[*]" from sections.ld.in with objects under SURROUND keyword. (e.g. from linker.lf: data -> dram0_data SURROUND(foo)) - "mapping[*]" - refers to all other data If SOC_MEM_NON_CONTIGUOUS_SRAM, sections.ld.in file should contain at least one block of code like this (otherwise it does not make sense): .dram0.bss (NOLOAD) : { arrays[dram0_bss] mapping[dram0_bss] } > sram_low .dram1.bss (NOLOAD) : { /* do not place here arrays[dram0_bss] because it may be splited * between segments */ mapping[dram0_bss] } > sram_high
This commit is contained in:
parent
4b5b064caf
commit
824c8e0593
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -10,7 +10,11 @@
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// Bootloader version info
|
||||
const __attribute__((weak)) __attribute__((section(".data_bootloader_desc"))) esp_bootloader_desc_t esp_bootloader_desc = {
|
||||
#if BOOTLOADER_BUILD
|
||||
__attribute__((section(".data_bootloader_desc")))
|
||||
#endif
|
||||
__attribute__((weak))
|
||||
const esp_bootloader_desc_t esp_bootloader_desc = {
|
||||
.magic_byte = ESP_BOOTLOADER_DESC_MAGIC_BYTE,
|
||||
.reserved = { 0 },
|
||||
.version = CONFIG_BOOTLOADER_PROJECT_VER,
|
||||
|
@ -143,3 +143,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
idf_component_optional_requires(PRIVATE esp_psram)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_MEM_NON_CONTIGUOUS_SRAM)
|
||||
target_link_options(${COMPONENT_LIB} INTERFACE "-Wl,--enable-non-contiguous-regions")
|
||||
endif()
|
||||
|
@ -3,6 +3,9 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ld.common"
|
||||
|
||||
/* Default entry point: */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
@ -296,6 +299,7 @@ SECTIONS
|
||||
* will be merged when creating the final bin image. */
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} >default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata)
|
||||
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
{
|
||||
|
@ -4,6 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ld.common"
|
||||
|
||||
/* Default entry point */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
@ -93,20 +95,9 @@ SECTIONS
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
|
||||
/* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */
|
||||
mapping[dram0_bss]
|
||||
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.share.mem)
|
||||
*(.gnu.linkonce.b.*)
|
||||
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
@ -174,7 +165,8 @@ SECTIONS
|
||||
* section will match .flash.rodata's begin address. Thus, both sections
|
||||
* will be merged when creating the final bin image. */
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} >default_rodata_seg
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata)
|
||||
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
{
|
||||
@ -234,7 +226,12 @@ SECTIONS
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
. = ALIGN(ALIGNOF(.flash.tls));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls)
|
||||
|
||||
.flash.tls : ALIGN(8)
|
||||
{
|
||||
_thread_local_start = ABSOLUTE(.);
|
||||
*(.tdata)
|
||||
*(.tdata.*)
|
||||
@ -243,6 +240,7 @@ SECTIONS
|
||||
_thread_local_end = ABSOLUTE(.);
|
||||
. = ALIGN(ALIGNOF(.eh_frame));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame)
|
||||
|
||||
/* Keep this section shall be at least aligned on 4 */
|
||||
.eh_frame : ALIGN(8)
|
||||
@ -254,6 +252,7 @@ SECTIONS
|
||||
* them adjacent. */
|
||||
. = ALIGN(ALIGNOF(.eh_frame_hdr));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr)
|
||||
|
||||
/* To avoid any exception in C++ exception frame unwinding code, this section
|
||||
* shall be aligned on 8. */
|
||||
|
@ -4,6 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ld.common"
|
||||
|
||||
/* Default entry point */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
@ -206,20 +208,9 @@ SECTIONS
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
|
||||
/* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */
|
||||
mapping[dram0_bss]
|
||||
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.share.mem)
|
||||
*(.gnu.linkonce.b.*)
|
||||
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
@ -287,7 +278,8 @@ SECTIONS
|
||||
* section will match .flash.rodata's begin address. Thus, both sections
|
||||
* will be merged when creating the final bin image. */
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} >default_rodata_seg
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata)
|
||||
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
{
|
||||
@ -347,7 +339,12 @@ SECTIONS
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
. = ALIGN(ALIGNOF(.flash.tls));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls)
|
||||
|
||||
.flash.tls : ALIGN(8)
|
||||
{
|
||||
_thread_local_start = ABSOLUTE(.);
|
||||
*(.tdata)
|
||||
*(.tdata.*)
|
||||
@ -356,6 +353,7 @@ SECTIONS
|
||||
_thread_local_end = ABSOLUTE(.);
|
||||
. = ALIGN(ALIGNOF(.eh_frame));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame)
|
||||
|
||||
/* Keep this section shall be at least aligned on 4 */
|
||||
.eh_frame : ALIGN(8)
|
||||
@ -367,6 +365,7 @@ SECTIONS
|
||||
* them adjacent. */
|
||||
. = ALIGN(ALIGNOF(.eh_frame_hdr));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr)
|
||||
|
||||
/* To avoid any exception in C++ exception frame unwinding code, this section
|
||||
* shall be aligned on 8. */
|
||||
|
@ -4,6 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ld.common"
|
||||
|
||||
/* Default entry point */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
@ -46,6 +48,7 @@ SECTIONS
|
||||
|
||||
*(.rtc.force_fast .rtc.force_fast.*)
|
||||
. = ALIGN(4) ;
|
||||
|
||||
_rtc_force_fast_end = ABSOLUTE(.);
|
||||
} > lp_ram_seg
|
||||
|
||||
@ -241,21 +244,10 @@ SECTIONS
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
|
||||
/* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */
|
||||
mapping[dram0_bss]
|
||||
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.share.mem)
|
||||
*(.gnu.linkonce.b.*)
|
||||
|
||||
. = ALIGN (8);
|
||||
. = ALIGN(4);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
|
||||
@ -322,7 +314,8 @@ SECTIONS
|
||||
* section will match .flash.rodata's begin address. Thus, both sections
|
||||
* will be merged when creating the final bin image. */
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} >default_rodata_seg
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata)
|
||||
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
{
|
||||
@ -382,7 +375,12 @@ SECTIONS
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
. = ALIGN(ALIGNOF(.flash.tls));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls)
|
||||
|
||||
.flash.tls : ALIGN(8)
|
||||
{
|
||||
_thread_local_start = ABSOLUTE(.);
|
||||
*(.tdata)
|
||||
*(.tdata.*)
|
||||
@ -391,6 +389,7 @@ SECTIONS
|
||||
_thread_local_end = ABSOLUTE(.);
|
||||
. = ALIGN(ALIGNOF(.eh_frame));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame)
|
||||
|
||||
/* Keep this section shall be at least aligned on 4 */
|
||||
.eh_frame : ALIGN(8)
|
||||
@ -402,6 +401,7 @@ SECTIONS
|
||||
* them adjacent. */
|
||||
. = ALIGN(ALIGNOF(.eh_frame_hdr));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr)
|
||||
|
||||
/* To avoid any exception in C++ exception frame unwinding code, this section
|
||||
* shall be aligned on 8. */
|
||||
|
@ -15,20 +15,9 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "ld.common"
|
||||
|
||||
/**
|
||||
* physical memory is mapped twice to the vritual address (IRAM and DRAM).
|
||||
* `I_D_SRAM_OFFSET` is the offset between the two locations of the same physical memory
|
||||
*/
|
||||
#define SRAM_IRAM_START 0x40800000
|
||||
#define SRAM_DRAM_START 0x40800000
|
||||
|
||||
#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START)
|
||||
#define SRAM_DRAM_END 0x4086E610 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */
|
||||
|
||||
#define SRAM_IRAM_ORG (SRAM_IRAM_START)
|
||||
#define SRAM_DRAM_ORG (SRAM_DRAM_START)
|
||||
|
||||
#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG
|
||||
#define SRAM_SEG_START 0x40800000
|
||||
#define SRAM_SEG_END 0x4086E610 /* 2nd stage bootloader iram_loader_seg start address */
|
||||
#define SRAM_SEG_SIZE SRAM_SEG_END - SRAM_SEG_START
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/*
|
||||
@ -37,8 +26,6 @@
|
||||
#define IDRAM0_2_SEG_SIZE (CONFIG_MMU_PAGE_SIZE << 8)
|
||||
#endif
|
||||
|
||||
#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/**
|
||||
@ -47,9 +34,6 @@ MEMORY
|
||||
* are connected to the data port of the CPU and eg allow byte-wise access.
|
||||
*/
|
||||
|
||||
/* IRAM for PRO CPU. */
|
||||
iram0_0_seg (RX) : org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped instruction data */
|
||||
irom_seg (RX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20
|
||||
@ -67,7 +51,7 @@ MEMORY
|
||||
* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
|
||||
* Enabling Bluetooth & Trace Memory features in menuconfig will decrease the amount of RAM available.
|
||||
*/
|
||||
dram0_0_seg (RW) : org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN
|
||||
sram_seg (RWX) : org = SRAM_SEG_START, len = SRAM_SEG_SIZE
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped constant data */
|
||||
@ -96,7 +80,7 @@ MEMORY
|
||||
lp_reserved_seg(RW) : org = 0x50000000 + 0x4000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM
|
||||
}
|
||||
|
||||
/* Heap ends at top of dram0_0_seg */
|
||||
/* Heap ends at top of sram_seg */
|
||||
_heap_end = 0x40000000;
|
||||
|
||||
_data_seg_org = ORIGIN(rtc_data_seg);
|
||||
@ -115,13 +99,13 @@ REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg );
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
REGION_ALIAS("default_code_seg", irom_seg);
|
||||
#else
|
||||
REGION_ALIAS("default_code_seg", iram0_0_seg);
|
||||
REGION_ALIAS("default_code_seg", sram_seg);
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
REGION_ALIAS("default_rodata_seg", drom_seg);
|
||||
#else
|
||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||
REGION_ALIAS("default_rodata_seg", sram_seg);
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
/**
|
||||
|
@ -4,6 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ld.common"
|
||||
|
||||
/* Default entry point */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
@ -158,7 +160,7 @@ SECTIONS
|
||||
|
||||
mapping[iram0_text]
|
||||
|
||||
} > iram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
/* Marks the end of IRAM code segment */
|
||||
.iram0.text_end (NOLOAD) :
|
||||
@ -169,7 +171,7 @@ SECTIONS
|
||||
/* iram_end_test section exists for use by memprot unit tests only */
|
||||
*(.iram_end_test)
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
.iram0.data :
|
||||
{
|
||||
@ -179,7 +181,7 @@ SECTIONS
|
||||
mapping[iram0_data]
|
||||
|
||||
_iram_data_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
.iram0.bss (NOLOAD) :
|
||||
{
|
||||
@ -191,16 +193,7 @@ SECTIONS
|
||||
_iram_bss_end = ABSOLUTE(.);
|
||||
. = ALIGN(16);
|
||||
_iram_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
.dram0.dummy (NOLOAD):
|
||||
{
|
||||
. = ORIGIN(dram0_0_seg) + _iram_end - _iram_start;
|
||||
} > dram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
.dram0.data :
|
||||
{
|
||||
@ -218,7 +211,7 @@ SECTIONS
|
||||
|
||||
_data_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > dram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
/**
|
||||
* This section holds data that should not be initialized at power up.
|
||||
@ -233,7 +226,7 @@ SECTIONS
|
||||
*(.noinit .noinit.*)
|
||||
. = ALIGN(4) ;
|
||||
_noinit_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
/* Shared RAM */
|
||||
.dram0.bss (NOLOAD) :
|
||||
@ -241,25 +234,12 @@ SECTIONS
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
|
||||
/* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */
|
||||
mapping[dram0_bss]
|
||||
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.share.mem)
|
||||
*(.gnu.linkonce.b.*)
|
||||
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
|
||||
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.")
|
||||
} > sram_seg
|
||||
|
||||
.flash.text :
|
||||
{
|
||||
@ -322,7 +302,8 @@ SECTIONS
|
||||
* section will match .flash.rodata's begin address. Thus, both sections
|
||||
* will be merged when creating the final bin image. */
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} >default_rodata_seg
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata)
|
||||
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
{
|
||||
@ -382,7 +363,12 @@ SECTIONS
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
. = ALIGN(ALIGNOF(.flash.tls));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls)
|
||||
|
||||
.flash.tls : ALIGN(8)
|
||||
{
|
||||
_thread_local_start = ABSOLUTE(.);
|
||||
*(.tdata)
|
||||
*(.tdata.*)
|
||||
@ -391,6 +377,7 @@ SECTIONS
|
||||
_thread_local_end = ABSOLUTE(.);
|
||||
. = ALIGN(ALIGNOF(.eh_frame));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame)
|
||||
|
||||
/* Keep this section shall be at least aligned on 4 */
|
||||
.eh_frame : ALIGN(8)
|
||||
@ -402,6 +389,7 @@ SECTIONS
|
||||
* them adjacent. */
|
||||
. = ALIGN(ALIGNOF(.eh_frame_hdr));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr)
|
||||
|
||||
/* To avoid any exception in C++ exception frame unwinding code, this section
|
||||
* shall be aligned on 8. */
|
||||
@ -432,11 +420,5 @@ SECTIONS
|
||||
{
|
||||
. = ALIGN (16);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
} > sram_seg
|
||||
}
|
||||
|
||||
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||
"IRAM0 segment data does not fit.")
|
||||
|
||||
ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
|
||||
"DRAM segment data does not fit.")
|
||||
|
@ -15,20 +15,9 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "ld.common"
|
||||
|
||||
/**
|
||||
* physical memory is mapped twice to the vritual address (IRAM and DRAM).
|
||||
* `I_D_SRAM_OFFSET` is the offset between the two locations of the same physical memory
|
||||
*/
|
||||
#define SRAM_IRAM_START 0x40800000
|
||||
#define SRAM_DRAM_START 0x40800000
|
||||
|
||||
#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START)
|
||||
#define SRAM_DRAM_END 0x4083EFD0 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */
|
||||
|
||||
#define SRAM_IRAM_ORG (SRAM_IRAM_START)
|
||||
#define SRAM_DRAM_ORG (SRAM_DRAM_START)
|
||||
|
||||
#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG
|
||||
#define SRAM_SEG_START 0x40800000
|
||||
#define SRAM_SEG_END 0x4083EFD0 /* 2nd stage bootloader iram_loader_seg start address */
|
||||
#define SRAM_SEG_SIZE SRAM_SEG_END - SRAM_SEG_START
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/*
|
||||
@ -37,8 +26,6 @@
|
||||
#define IDRAM0_2_SEG_SIZE (CONFIG_MMU_PAGE_SIZE << 8)
|
||||
#endif
|
||||
|
||||
#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/**
|
||||
@ -47,9 +34,6 @@ MEMORY
|
||||
* are connected to the data port of the CPU and eg allow byte-wise access.
|
||||
*/
|
||||
|
||||
/* IRAM for PRO CPU. */
|
||||
iram0_0_seg (RX) : org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped instruction data */
|
||||
irom_seg (RX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20
|
||||
@ -67,7 +51,7 @@ MEMORY
|
||||
* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
|
||||
* Enabling Bluetooth & Trace Memory features in menuconfig will decrease the amount of RAM available.
|
||||
*/
|
||||
dram0_0_seg (RW) : org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN
|
||||
sram_seg (RWX) : org = SRAM_SEG_START, len = SRAM_SEG_SIZE
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped constant data */
|
||||
@ -92,7 +76,7 @@ MEMORY
|
||||
lp_reserved_seg(RW) : org = 0x50000000 + 0x1000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM
|
||||
}
|
||||
|
||||
/* Heap ends at top of dram0_0_seg */
|
||||
/* Heap ends at top of sram_seg */
|
||||
_heap_end = 0x40000000;
|
||||
|
||||
_data_seg_org = ORIGIN(rtc_data_seg);
|
||||
@ -110,13 +94,13 @@ REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg );
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
REGION_ALIAS("default_code_seg", irom_seg);
|
||||
#else
|
||||
REGION_ALIAS("default_code_seg", iram0_0_seg);
|
||||
REGION_ALIAS("default_code_seg", sram_seg);
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
REGION_ALIAS("default_rodata_seg", drom_seg);
|
||||
#else
|
||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||
REGION_ALIAS("default_rodata_seg", sram_seg);
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
/**
|
||||
|
@ -4,6 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ld.common"
|
||||
|
||||
/* Default entry point */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
@ -158,7 +160,7 @@ SECTIONS
|
||||
|
||||
mapping[iram0_text]
|
||||
|
||||
} > iram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
/* Marks the end of IRAM code segment */
|
||||
.iram0.text_end (NOLOAD) :
|
||||
@ -169,7 +171,7 @@ SECTIONS
|
||||
/* iram_end_test section exists for use by memprot unit tests only */
|
||||
*(.iram_end_test)
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
.iram0.data :
|
||||
{
|
||||
@ -179,7 +181,7 @@ SECTIONS
|
||||
mapping[iram0_data]
|
||||
|
||||
_iram_data_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
.iram0.bss (NOLOAD) :
|
||||
{
|
||||
@ -191,16 +193,7 @@ SECTIONS
|
||||
_iram_bss_end = ABSOLUTE(.);
|
||||
. = ALIGN(16);
|
||||
_iram_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
.dram0.dummy (NOLOAD):
|
||||
{
|
||||
. = ORIGIN(dram0_0_seg) + _iram_end - _iram_start;
|
||||
} > dram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
.dram0.data :
|
||||
{
|
||||
@ -218,7 +211,7 @@ SECTIONS
|
||||
|
||||
_data_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > dram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
/**
|
||||
* This section holds data that should not be initialized at power up.
|
||||
@ -233,7 +226,7 @@ SECTIONS
|
||||
*(.noinit .noinit.*)
|
||||
. = ALIGN(4) ;
|
||||
_noinit_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
} > sram_seg
|
||||
|
||||
/* Shared RAM */
|
||||
.dram0.bss (NOLOAD) :
|
||||
@ -241,25 +234,12 @@ SECTIONS
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
|
||||
/* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */
|
||||
mapping[dram0_bss]
|
||||
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.share.mem)
|
||||
*(.gnu.linkonce.b.*)
|
||||
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
|
||||
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.")
|
||||
} > sram_seg
|
||||
|
||||
.flash.text :
|
||||
{
|
||||
@ -322,7 +302,8 @@ SECTIONS
|
||||
* section will match .flash.rodata's begin address. Thus, both sections
|
||||
* will be merged when creating the final bin image. */
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} >default_rodata_seg
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata)
|
||||
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
{
|
||||
@ -381,7 +362,12 @@ SECTIONS
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
. = ALIGN(ALIGNOF(.flash.tls));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.rodata, .flash.tls)
|
||||
|
||||
.flash.tls : ALIGN(8)
|
||||
{
|
||||
_thread_local_start = ABSOLUTE(.);
|
||||
*(.tdata)
|
||||
*(.tdata.*)
|
||||
@ -391,6 +377,7 @@ SECTIONS
|
||||
_rodata_reserved_end = ABSOLUTE(.);
|
||||
. = ALIGN(ALIGNOF(.eh_frame));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame)
|
||||
|
||||
/* Keep this section shall be at least aligned on 4 */
|
||||
.eh_frame : ALIGN(8)
|
||||
@ -402,6 +389,7 @@ SECTIONS
|
||||
* them adjacent. */
|
||||
. = ALIGN(ALIGNOF(.eh_frame_hdr));
|
||||
} > default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr)
|
||||
|
||||
/* To avoid any exception in C++ exception frame unwinding code, this section
|
||||
* shall be aligned on 8. */
|
||||
@ -423,11 +411,5 @@ SECTIONS
|
||||
{
|
||||
. = ALIGN (16);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
} > sram_seg
|
||||
}
|
||||
|
||||
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||
"IRAM0 segment data does not fit.")
|
||||
|
||||
ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
|
||||
"DRAM segment data does not fit.")
|
||||
|
@ -15,20 +15,17 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "ld.common"
|
||||
|
||||
/**
|
||||
* physical memory is mapped twice to the vritual address (IRAM and DRAM).
|
||||
* `I_D_SRAM_OFFSET` is the offset between the two locations of the same physical memory
|
||||
#define SRAM_LOW_START 0x4FF00000
|
||||
#define SRAM_LOW_END 0x4FF2CBD0 /* 2nd stage bootloader iram_loader_seg start address */
|
||||
#define SRAM_LOW_SIZE SRAM_LOW_END - SRAM_LOW_START
|
||||
|
||||
/* If the cache size is less than 512KB, then there is a region of RAM
|
||||
* above the ROM-reserved region and below the start of the cache.
|
||||
*/
|
||||
#define SRAM_IRAM_START 0x4ff00000
|
||||
#define SRAM_DRAM_START 0x4ff00000
|
||||
#define SRAM_HIGH_START 0x4FF40000
|
||||
#define SRAM_HIGH_SIZE 0x80000 - CONFIG_CACHE_L2_CACHE_SIZE
|
||||
#define SRAM_HIGH_END SRAM_HIGH_START + SRAM_HIGH_SIZE
|
||||
|
||||
#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START)
|
||||
#define SRAM_DRAM_END 0x4FF2CBD0 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */
|
||||
|
||||
#define SRAM_IRAM_ORG (SRAM_IRAM_START)
|
||||
#define SRAM_DRAM_ORG (SRAM_DRAM_START)
|
||||
|
||||
#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/**
|
||||
@ -37,8 +34,6 @@
|
||||
#define IDROM_SEG_SIZE (CONFIG_MMU_PAGE_SIZE << 10)
|
||||
#endif
|
||||
|
||||
#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/**
|
||||
@ -49,9 +44,6 @@ MEMORY
|
||||
/* TCM */
|
||||
tcm_idram_seg (RX) : org = 0x30100000, len = 0x2000
|
||||
|
||||
/* IRAM for PRO CPU. */
|
||||
iram0_0_seg (RX) : org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped instruction data */
|
||||
irom_seg (RX) : org = 0x40000020, len = IDROM_SEG_SIZE - 0x20
|
||||
@ -69,7 +61,9 @@ MEMORY
|
||||
* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
|
||||
* Enabling Bluetooth & Trace Memory features in menuconfig will decrease the amount of RAM available.
|
||||
*/
|
||||
dram0_0_seg (RW) : org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN
|
||||
sram_low (RWX) : org = SRAM_LOW_START, len = SRAM_LOW_SIZE
|
||||
|
||||
sram_high (RW) : org = SRAM_HIGH_START, len = SRAM_HIGH_SIZE
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped constant data */
|
||||
@ -115,15 +109,17 @@ REGION_ALIAS("rtc_data_location", rtc_iram_seg );
|
||||
REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg );
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
REGION_ALIAS("default_code_seg", irom_seg);
|
||||
REGION_ALIAS("text_seg_low", irom_seg);
|
||||
#else
|
||||
REGION_ALIAS("default_code_seg", iram0_0_seg);
|
||||
REGION_ALIAS("text_seg_low", sram_low);
|
||||
REGION_ALIAS("text_seg_high", sram_high);
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
REGION_ALIAS("default_rodata_seg", drom_seg);
|
||||
REGION_ALIAS("rodata_seg_low", drom_seg);
|
||||
#else
|
||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||
REGION_ALIAS("rodata_seg_low", sram_low);
|
||||
REGION_ALIAS("rodata_seg_high", sram_high);
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
/**
|
||||
@ -131,7 +127,7 @@ REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg );
|
||||
* also be first in the segment.
|
||||
*/
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg),
|
||||
ASSERT(_flash_rodata_dummy_start == ORIGIN(rodata_seg_low),
|
||||
".flash_rodata_dummy section must be placed at the beginning of the rodata segment.")
|
||||
#endif
|
||||
|
||||
|
@ -4,6 +4,9 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "ld.common"
|
||||
|
||||
/* Default entry point */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
@ -18,6 +21,7 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
_rtc_fast_start = ABSOLUTE(.);
|
||||
|
||||
arrays[rtc_text]
|
||||
mapping[rtc_text]
|
||||
|
||||
*rtc_wake_stub*.*(.literal .text .literal.* .text.*)
|
||||
@ -40,10 +44,12 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
_rtc_force_fast_start = ABSOLUTE(.);
|
||||
|
||||
arrays[rtc_force_fast]
|
||||
mapping[rtc_force_fast]
|
||||
|
||||
*(.rtc.force_fast .rtc.force_fast.*)
|
||||
. = ALIGN(4) ;
|
||||
|
||||
_rtc_force_fast_end = ABSOLUTE(.);
|
||||
} > lp_ram_seg
|
||||
|
||||
@ -57,6 +63,7 @@ SECTIONS
|
||||
{
|
||||
_rtc_data_start = ABSOLUTE(.);
|
||||
|
||||
arrays[rtc_data]
|
||||
mapping[rtc_data]
|
||||
|
||||
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
|
||||
@ -70,6 +77,7 @@ SECTIONS
|
||||
*rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*)
|
||||
*rtc_wake_stub*.*(COMMON)
|
||||
|
||||
arrays[rtc_bss]
|
||||
mapping[rtc_bss]
|
||||
|
||||
_rtc_bss_end = ABSOLUTE(.);
|
||||
@ -145,6 +153,7 @@ SECTIONS
|
||||
/* Code marked as running out of TCM */
|
||||
_tcm_text_start = ABSOLUTE(.);
|
||||
|
||||
arrays[tcm_text]
|
||||
mapping[tcm_text]
|
||||
|
||||
_tcm_text_end = ABSOLUTE(.);
|
||||
@ -155,6 +164,7 @@ SECTIONS
|
||||
{
|
||||
_tcm_data_start = ABSOLUTE(.);
|
||||
|
||||
arrays[tcm_data]
|
||||
mapping[tcm_data]
|
||||
|
||||
_tcm_data_end = ABSOLUTE(.);
|
||||
@ -177,9 +187,10 @@ SECTIONS
|
||||
/* Code marked as running out of IRAM */
|
||||
_iram_text_start = ABSOLUTE(.);
|
||||
|
||||
arrays[iram0_text]
|
||||
mapping[iram0_text]
|
||||
|
||||
} > iram0_0_seg
|
||||
} > sram_low
|
||||
|
||||
/* Marks the end of IRAM code segment */
|
||||
.iram0.text_end (NOLOAD) :
|
||||
@ -190,38 +201,31 @@ SECTIONS
|
||||
/* iram_end_test section exists for use by memprot unit tests only */
|
||||
*(.iram_end_test)
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
} > sram_low
|
||||
|
||||
.iram0.data :
|
||||
{
|
||||
. = ALIGN(16);
|
||||
_iram_data_start = ABSOLUTE(.);
|
||||
|
||||
arrays[iram0_data]
|
||||
mapping[iram0_data]
|
||||
|
||||
_iram_data_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
} > sram_low
|
||||
|
||||
.iram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(16);
|
||||
_iram_bss_start = ABSOLUTE(.);
|
||||
|
||||
arrays[iram0_bss]
|
||||
mapping[iram0_bss]
|
||||
|
||||
_iram_bss_end = ABSOLUTE(.);
|
||||
. = ALIGN(16);
|
||||
_iram_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
.dram0.dummy (NOLOAD):
|
||||
{
|
||||
. = ORIGIN(dram0_0_seg) + _iram_end - _iram_start;
|
||||
} > dram0_0_seg
|
||||
} > sram_low
|
||||
|
||||
.dram0.data :
|
||||
{
|
||||
@ -235,11 +239,12 @@ SECTIONS
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
|
||||
arrays[dram0_data]
|
||||
mapping[dram0_data]
|
||||
|
||||
_data_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > dram0_0_seg
|
||||
} > sram_low
|
||||
|
||||
/**
|
||||
* This section holds data that should not be initialized at power up.
|
||||
@ -254,33 +259,7 @@ SECTIONS
|
||||
*(.noinit .noinit.*)
|
||||
. = ALIGN(4) ;
|
||||
_noinit_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
|
||||
/* Shared RAM */
|
||||
.dram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
|
||||
mapping[dram0_bss]
|
||||
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.share.mem)
|
||||
*(.gnu.linkonce.b.*)
|
||||
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
|
||||
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.")
|
||||
} > sram_low
|
||||
|
||||
.flash.text :
|
||||
{
|
||||
@ -288,6 +267,7 @@ SECTIONS
|
||||
_instruction_reserved_start = ABSOLUTE(.); /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */
|
||||
_text_start = ABSOLUTE(.);
|
||||
|
||||
arrays[flash_text]
|
||||
mapping[flash_text]
|
||||
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
@ -313,7 +293,7 @@ SECTIONS
|
||||
* the flash.text segment.
|
||||
*/
|
||||
_flash_cache_start = ABSOLUTE(0);
|
||||
} > default_code_seg
|
||||
} > text_seg_low
|
||||
|
||||
/**
|
||||
* This dummy section represents the .flash.text section but in default_rodata_seg.
|
||||
@ -329,7 +309,7 @@ SECTIONS
|
||||
/* Prepare the alignment of the section above. Few bytes (0x20) must be
|
||||
* added for the mapping header. */
|
||||
. = ALIGN(_esp_mmu_block_size) + 0x20;
|
||||
} > default_rodata_seg
|
||||
} > rodata_seg_low
|
||||
|
||||
.flash.appdesc : ALIGN(0x10)
|
||||
{
|
||||
@ -343,12 +323,14 @@ SECTIONS
|
||||
* section will match .flash.rodata's begin address. Thus, both sections
|
||||
* will be merged when creating the final bin image. */
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} > default_rodata_seg
|
||||
} > rodata_seg_low
|
||||
ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata)
|
||||
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
{
|
||||
_flash_rodata_start = ABSOLUTE(.);
|
||||
|
||||
arrays[flash_rodata]
|
||||
mapping[flash_rodata]
|
||||
|
||||
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||
@ -359,6 +341,10 @@ SECTIONS
|
||||
*(.gcc_except_table .gcc_except_table.*)
|
||||
*(.gnu.linkonce.e.*)
|
||||
*(.gnu.version_r)
|
||||
} > rodata_seg_low
|
||||
|
||||
.flash.init_array :
|
||||
{
|
||||
. = (. + 7) & ~ 3;
|
||||
/*
|
||||
* C++ constructor and destructor tables
|
||||
@ -403,7 +389,12 @@ SECTIONS
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
. = ALIGN(ALIGNOF(.flash.tls));
|
||||
} > rodata_seg_low
|
||||
ASSERT_SECTIONS_GAP(.flash.init_array, .flash.tls)
|
||||
|
||||
.flash.tls : ALIGN(8)
|
||||
{
|
||||
_thread_local_start = ABSOLUTE(.);
|
||||
*(.tdata)
|
||||
*(.tdata.*)
|
||||
@ -411,7 +402,8 @@ SECTIONS
|
||||
*(.tbss.*)
|
||||
_thread_local_end = ABSOLUTE(.);
|
||||
. = ALIGN(ALIGNOF(.eh_frame));
|
||||
} > default_rodata_seg
|
||||
} > rodata_seg_low
|
||||
ASSERT_SECTIONS_GAP(.flash.tls, .eh_frame)
|
||||
|
||||
/* Keep this section shall be at least aligned on 4 */
|
||||
.eh_frame : ALIGN(8)
|
||||
@ -422,7 +414,8 @@ SECTIONS
|
||||
/* Guarantee that this section and the next one will be merged by making
|
||||
* them adjacent. */
|
||||
. = ALIGN(ALIGNOF(.eh_frame_hdr));
|
||||
} > default_rodata_seg
|
||||
} > rodata_seg_low
|
||||
ASSERT_SECTIONS_GAP(.eh_frame, .eh_frame_hdr)
|
||||
|
||||
/* To avoid any exception in C++ exception frame unwinding code, this section
|
||||
* shall be aligned on 8. */
|
||||
@ -431,7 +424,8 @@ SECTIONS
|
||||
__eh_frame_hdr = ABSOLUTE(.);
|
||||
KEEP (*(.eh_frame_hdr))
|
||||
__eh_frame_hdr_end = ABSOLUTE(.);
|
||||
} > default_rodata_seg
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} > rodata_seg_low
|
||||
|
||||
/*
|
||||
This section is a place where we dump all the rodata which aren't used at runtime,
|
||||
@ -445,19 +439,46 @@ SECTIONS
|
||||
*/
|
||||
_rodata_reserved_end = ABSOLUTE(.);
|
||||
. = ALIGN (4);
|
||||
arrays[rodata_noload]
|
||||
mapping[rodata_noload]
|
||||
} > default_rodata_seg
|
||||
} > rodata_seg_low
|
||||
|
||||
.dram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_bss_start_low = ABSOLUTE(.);
|
||||
|
||||
/* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */
|
||||
arrays[dram0_bss]
|
||||
mapping[dram0_bss]
|
||||
|
||||
. = ALIGN(4);
|
||||
_bss_end_low = ABSOLUTE(.);
|
||||
} > sram_low
|
||||
|
||||
.dram1.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_bss_start_high = ABSOLUTE(.);
|
||||
|
||||
/* ldgen places all bss-related data to mapping[dram0_bss] (See esp_system/app.lf). */
|
||||
mapping[dram0_bss]
|
||||
|
||||
. = ALIGN(4);
|
||||
_bss_end_high = ABSOLUTE(.);
|
||||
} > sram_high
|
||||
|
||||
/* Marks the end of data, bss and possibly rodata */
|
||||
.dram0.heap_start (NOLOAD) :
|
||||
.dram0.heap_start_low (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
_heap_start_low = ABSOLUTE(.);
|
||||
} > sram_low
|
||||
|
||||
/* Marks the end of data, bss and possibly rodata */
|
||||
.dram1.heap_start_high (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
_heap_start_high = ABSOLUTE(.);
|
||||
} > sram_high
|
||||
}
|
||||
|
||||
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||
"IRAM0 segment data does not fit.")
|
||||
|
||||
ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
|
||||
"DRAM segment data does not fit.")
|
||||
|
@ -4,6 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ld.common"
|
||||
|
||||
/* Default entry point: */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
@ -295,6 +297,7 @@ SECTIONS
|
||||
* will be merged when creating the final bin image. */
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} >default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata)
|
||||
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
{
|
||||
|
@ -4,6 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "ld.common"
|
||||
|
||||
/* Default entry point */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
@ -324,6 +326,7 @@ SECTIONS
|
||||
* will be merged when creating the final bin image. */
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} >default_rodata_seg
|
||||
ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata)
|
||||
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
{
|
||||
|
@ -1,33 +1,51 @@
|
||||
# For each supported target, a memory.ld.in and sections.ld.in is processed and dictate the
|
||||
# memory layout of the app.
|
||||
#
|
||||
# memory.ld.in goes through the preprocessor
|
||||
# sections.ld.in goes through linker script generator
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
idf_build_get_property(sdkconfig_header SDKCONFIG_HEADER)
|
||||
|
||||
set(ld_input "${CMAKE_CURRENT_LIST_DIR}/${target}/memory.ld.in")
|
||||
set(ld_output "${CMAKE_CURRENT_BINARY_DIR}/ld/memory.ld")
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${ld_output}")
|
||||
idf_build_get_property(config_dir CONFIG_DIR)
|
||||
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/ld")
|
||||
|
||||
# Process the template file through the linker script generation mechanism, and use the output for linking the
|
||||
# final binary
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/${target}/sections.ld.in"
|
||||
# Cmake script that generates linker script from "*.ld.in" scripts using compiler preprocessor
|
||||
set(linker_script_generator "${CMAKE_CURRENT_BINARY_DIR}/ld/linker_script_generator.cmake")
|
||||
file(WRITE ${linker_script_generator}
|
||||
[=[
|
||||
execute_process(COMMAND "${CC}" "-C" "-P" "-x" "c" "-E" "-I" "${CONFIG_DIR}" "-I" "${LD_DIR}" "${SOURCE}"
|
||||
RESULT_VARIABLE RET_CODE
|
||||
OUTPUT_VARIABLE PREPROCESSED_LINKER_SCRIPT
|
||||
ERROR_VARIABLE ERROR_VAR)
|
||||
if(RET_CODE AND NOT RET_CODE EQUAL 0)
|
||||
message(FATAL_ERROR "Can't generate ${TARGET}\nRET_CODE: ${RET_CODE}\nERROR_MESSAGE: ${ERROR_VAR}")
|
||||
endif()
|
||||
string(REPLACE "\\n" "\n" TEXT "${PREPROCESSED_LINKER_SCRIPT}")
|
||||
file(WRITE "${TARGET}" "${TEXT}")
|
||||
]=])
|
||||
|
||||
function(preprocess_linker_file name_in name_out out_path)
|
||||
set(script_in "${CMAKE_CURRENT_LIST_DIR}/${target}/${name_in}")
|
||||
set(script_out "${CMAKE_CURRENT_BINARY_DIR}/ld/${name_out}")
|
||||
set(${out_path} ${script_out} PARENT_SCOPE)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${script_out}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
"-DCC=${CMAKE_C_COMPILER}"
|
||||
"-DSOURCE=${script_in}"
|
||||
"-DTARGET=${script_out}"
|
||||
"-DCONFIG_DIR=${config_dir}"
|
||||
"-DLD_DIR=${CMAKE_CURRENT_LIST_DIR}"
|
||||
-P "${linker_script_generator}"
|
||||
MAIN_DEPENDENCY ${script_in}
|
||||
DEPENDS ${sdkconfig_header}
|
||||
COMMENT "Generating ${script_out} linker script..."
|
||||
VERBATIM)
|
||||
add_custom_target("${name_out}" DEPENDS "${script_out}")
|
||||
add_dependencies(${COMPONENT_LIB} "${name_out}")
|
||||
endfunction()
|
||||
|
||||
# Generage memory.ld
|
||||
preprocess_linker_file("memory.ld.in" "memory.ld" ld_out_path)
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${ld_out_path}")
|
||||
|
||||
# Generage sections.ld.in and pass it through linker script generator
|
||||
preprocess_linker_file("sections.ld.in" "sections.ld.in" ld_out_path)
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${ld_out_path}"
|
||||
PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/sections.ld")
|
||||
|
||||
idf_build_get_property(config_dir CONFIG_DIR)
|
||||
# Preprocess memory.ld.in linker script to include configuration, becomes memory.ld
|
||||
add_custom_command(
|
||||
OUTPUT ${ld_output}
|
||||
COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o ${ld_output} -I ${config_dir}
|
||||
-I "${CMAKE_CURRENT_LIST_DIR}" ${ld_input}
|
||||
MAIN_DEPENDENCY ${ld_input}
|
||||
DEPENDS ${sdkconfig_header}
|
||||
COMMENT "Generating memory.ld linker script..."
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(memory_ld DEPENDS ${ld_output})
|
||||
add_dependencies(${COMPONENT_LIB} memory_ld)
|
||||
|
@ -7,26 +7,26 @@
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* CPU instruction prefetch padding size for flash mmap scenario */
|
||||
_esp_flash_mmap_prefetch_pad_size = 16;
|
||||
#define _esp_flash_mmap_prefetch_pad_size 16
|
||||
|
||||
/* CPU instruction prefetch padding size for memory protection scenario */
|
||||
#ifdef CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE
|
||||
_esp_memprot_prefetch_pad_size = CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE;
|
||||
#define _esp_memprot_prefetch_pad_size CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE
|
||||
#else
|
||||
_esp_memprot_prefetch_pad_size = 0;
|
||||
#define _esp_memprot_prefetch_pad_size 0
|
||||
#endif
|
||||
|
||||
/* Memory alignment size for PMS */
|
||||
#ifdef CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE
|
||||
_esp_memprot_align_size = CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE;
|
||||
#define _esp_memprot_align_size CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE
|
||||
#else
|
||||
_esp_memprot_align_size = 0;
|
||||
#define _esp_memprot_align_size 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_APP_BUILD_TYPE_RAM
|
||||
_esp_mmu_block_size = 0;
|
||||
#define _esp_mmu_block_size 0
|
||||
#else
|
||||
_esp_mmu_block_size = (CONFIG_MMU_PAGE_SIZE);
|
||||
#define _esp_mmu_block_size CONFIG_MMU_PAGE_SIZE
|
||||
#endif
|
||||
|
||||
#if CONFIG_SOC_RTC_MEM_SUPPORTED
|
||||
@ -49,3 +49,8 @@ _esp_mmu_block_size = (CONFIG_MMU_PAGE_SIZE);
|
||||
#define RESERVE_RTC_MEM (ESP_BOOTLOADER_RESERVE_RTC + RTC_TIMER_RESERVE_RTC)
|
||||
#endif
|
||||
#endif // SOC_RTC_MEM_SUPPORTED
|
||||
|
||||
#define QUOTED_STRING(STRING) #STRING
|
||||
#define ASSERT_SECTIONS_GAP(PREV_SECTION, NEXT_SECTION) \
|
||||
ASSERT((ADDR(NEXT_SECTION) == ADDR(PREV_SECTION) + SIZEOF(PREV_SECTION)), \
|
||||
QUOTED_STRING(The gap between PREV_SECTION and NEXT_SECTION must not exist to produce the final bin image.))
|
||||
|
@ -123,8 +123,13 @@
|
||||
#include "esp_private/startup_internal.h"
|
||||
#include "esp_private/system_internal.h"
|
||||
|
||||
#if SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
extern int _bss_start_low, _bss_start_high;
|
||||
extern int _bss_end_low, _bss_end_high;
|
||||
#else
|
||||
extern int _bss_start;
|
||||
extern int _bss_end;
|
||||
#endif // SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
extern int _rtc_bss_start;
|
||||
extern int _rtc_bss_end;
|
||||
#if CONFIG_BT_LE_RELEASE_IRAM_SUPPORTED
|
||||
@ -413,7 +418,12 @@ void IRAM_ATTR call_start_cpu0(void)
|
||||
#endif
|
||||
|
||||
//Clear BSS. Please do not attempt to do any complex stuff (like early logging) before this.
|
||||
#if SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
memset(&_bss_start_low, 0, (&_bss_end_low - &_bss_start_low) * sizeof(_bss_start_low));
|
||||
memset(&_bss_start_high, 0, (&_bss_end_high - &_bss_start_high) * sizeof(_bss_start_high));
|
||||
#else
|
||||
memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
|
||||
#endif // SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
|
||||
#if CONFIG_BT_LE_RELEASE_IRAM_SUPPORTED
|
||||
// Clear Bluetooth bss
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -330,18 +330,14 @@ void vPortEndScheduler(void)
|
||||
FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, uint32_t *ret_threadptr_reg_init)
|
||||
{
|
||||
/*
|
||||
TLS layout at link-time, where 0xNNN is the offset that the linker calculates to a particular TLS variable.
|
||||
|
||||
LOW ADDRESS
|
||||
|---------------------------| Linker Symbols
|
||||
| Section | --------------
|
||||
| .flash.rodata |
|
||||
0x0|---------------------------| <- _flash_rodata_start
|
||||
^ | Other Data |
|
||||
| |---------------------------| <- _thread_local_start
|
||||
| | .tbss | ^
|
||||
V | | |
|
||||
0xNNN | int example; | | tls_area_size
|
||||
| .flash.tls |
|
||||
0x0|---------------------------| <- _thread_local_start
|
||||
| .tbss | ^
|
||||
| | |
|
||||
| int example; | | tls_area_size
|
||||
| | |
|
||||
| .tdata | V
|
||||
|---------------------------| <- _thread_local_end
|
||||
@ -351,7 +347,7 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u
|
||||
HIGH ADDRESS
|
||||
*/
|
||||
// Calculate TLS area size and round up to multiple of 16 bytes.
|
||||
extern char _thread_local_start, _thread_local_end, _flash_rodata_start;
|
||||
extern char _thread_local_start, _thread_local_end;
|
||||
const uint32_t tls_area_size = ALIGNUP(16, (uint32_t)&_thread_local_end - (uint32_t)&_thread_local_start);
|
||||
// TODO: check that TLS area fits the stack
|
||||
|
||||
@ -360,27 +356,8 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u
|
||||
// Initialize the TLS area with the initialization values of each TLS variable
|
||||
memcpy((void *)uxStackPointer, &_thread_local_start, tls_area_size);
|
||||
|
||||
/*
|
||||
Calculate the THREADPTR register's initialization value based on the link-time offset and the TLS area allocated on
|
||||
the stack.
|
||||
|
||||
HIGH ADDRESS
|
||||
|---------------------------|
|
||||
| .tdata (*) |
|
||||
^ | int example; |
|
||||
| | |
|
||||
| | .tbss (*) |
|
||||
| |---------------------------| <- uxStackPointer (start of TLS area)
|
||||
0xNNN | | | ^
|
||||
| | | |
|
||||
| ... | _thread_local_start - _rodata_start
|
||||
| | | |
|
||||
| | | V
|
||||
V | | <- threadptr register's value
|
||||
|
||||
LOW ADDRESS
|
||||
*/
|
||||
*ret_threadptr_reg_init = (uint32_t)uxStackPointer - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start);
|
||||
// Save tls start address
|
||||
*ret_threadptr_reg_init = (uint32_t)uxStackPointer;
|
||||
return uxStackPointer;
|
||||
}
|
||||
|
||||
|
@ -189,18 +189,14 @@ void vPortEndScheduler(void)
|
||||
FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, uint32_t *ret_threadptr_reg_init)
|
||||
{
|
||||
/*
|
||||
TLS layout at link-time, where 0xNNN is the offset that the linker calculates to a particular TLS variable.
|
||||
|
||||
LOW ADDRESS
|
||||
|---------------------------| Linker Symbols
|
||||
| Section | --------------
|
||||
| .flash.rodata |
|
||||
0x0|---------------------------| <- _flash_rodata_start
|
||||
^ | Other Data |
|
||||
| |---------------------------| <- _thread_local_start
|
||||
| | .tbss | ^
|
||||
V | | |
|
||||
0xNNN | int example; | | tls_area_size
|
||||
| .flash.tls |
|
||||
0x0|---------------------------| <- _thread_local_start
|
||||
| .tbss | ^
|
||||
| | |
|
||||
| int example; | | tls_area_size
|
||||
| | |
|
||||
| .tdata | V
|
||||
|---------------------------| <- _thread_local_end
|
||||
@ -210,7 +206,7 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u
|
||||
HIGH ADDRESS
|
||||
*/
|
||||
// Calculate TLS area size and round up to multiple of 16 bytes.
|
||||
extern char _thread_local_start, _thread_local_end, _flash_rodata_start;
|
||||
extern char _thread_local_start, _thread_local_end;
|
||||
const uint32_t tls_area_size = ALIGNUP(16, (uint32_t)&_thread_local_end - (uint32_t)&_thread_local_start);
|
||||
// TODO: check that TLS area fits the stack
|
||||
|
||||
@ -219,27 +215,8 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u
|
||||
// Initialize the TLS area with the initialization values of each TLS variable
|
||||
memcpy((void *)uxStackPointer, &_thread_local_start, tls_area_size);
|
||||
|
||||
/*
|
||||
Calculate the THREADPTR register's initialization value based on the link-time offset and the TLS area allocated on
|
||||
the stack.
|
||||
|
||||
HIGH ADDRESS
|
||||
|---------------------------|
|
||||
| .tdata (*) |
|
||||
^ | int example; |
|
||||
| | |
|
||||
| | .tbss (*) |
|
||||
| |---------------------------| <- uxStackPointer (start of TLS area)
|
||||
0xNNN | | | ^
|
||||
| | | |
|
||||
| ... | _thread_local_start - _rodata_start
|
||||
| | | |
|
||||
| | | V
|
||||
V | | <- threadptr register's value
|
||||
|
||||
LOW ADDRESS
|
||||
*/
|
||||
*ret_threadptr_reg_init = (uint32_t)uxStackPointer - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start);
|
||||
// Save tls start address
|
||||
*ret_threadptr_reg_init = (uint32_t)uxStackPointer;
|
||||
return uxStackPointer;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -89,7 +89,7 @@ const soc_memory_region_t soc_memory_regions[] = {
|
||||
const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_memory_region_t);
|
||||
|
||||
|
||||
extern int _data_start, _heap_start, _iram_start, _iram_end, _rtc_force_slow_end;
|
||||
extern int _data_start, _bss_start_high, _heap_start_low, _heap_start_high, _iram_start, _iram_end, _rtc_force_slow_end;
|
||||
extern int _tcm_text_start, _tcm_data_end;
|
||||
extern int _rtc_reserved_start, _rtc_reserved_end;
|
||||
|
||||
@ -100,7 +100,8 @@ extern int _rtc_reserved_start, _rtc_reserved_end;
|
||||
*/
|
||||
|
||||
// Static data region. DRAM used by data+bss and possibly rodata
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_data);
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start_low, dram_data_low);
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_bss_start_high, (intptr_t)&_heap_start_high, dram_data_high);
|
||||
|
||||
// Target has a shared D/IRAM virtual address, no need to calculate I_D_OFFSET like previous chips
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code);
|
||||
|
@ -1403,6 +1403,10 @@ config SOC_MEM_TCM_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EMAC_USE_IO_MUX
|
||||
bool
|
||||
default y
|
||||
|
@ -592,7 +592,7 @@
|
||||
#define SOC_TSENS_IS_INDEPENDENT_FROM_ADC (1) /*!< Temperature sensor is a separate module, not share regs with ADC */
|
||||
|
||||
/*-------------------------- Memory CAPS --------------------------*/
|
||||
#define SOC_MEM_TCM_SUPPORTED (1)
|
||||
|
||||
#define SOC_MEM_TCM_SUPPORTED (1)
|
||||
#define SOC_MEM_NON_CONTIGUOUS_SRAM (1)
|
||||
/*--------------------------- EMAC --------------------------------*/
|
||||
#define SOC_EMAC_USE_IO_MUX (1) /*!< GPIO matrix is used to select GPIO pads */
|
||||
|
@ -532,26 +532,53 @@ The linker script template is the skeleton in which the generated placement rule
|
||||
|
||||
To reference the placement rules collected under a ``target`` token, the following syntax is used:
|
||||
|
||||
.. code-block:: none
|
||||
.. only:: SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
|
||||
mapping[target]
|
||||
.. code-block:: none
|
||||
|
||||
arrays[target] /* refers to objects under the SURROUND keyword */
|
||||
mapping[target] /* refers to all other data */
|
||||
|
||||
.. only:: not SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
mapping[target]
|
||||
|
||||
Example:
|
||||
|
||||
The example below is an excerpt from a possible linker script template. It defines an output section ``.iram0.text``, and inside is a marker referencing the target ``iram0_text``.
|
||||
|
||||
.. code-block:: none
|
||||
.. only:: SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
|
||||
.iram0.text :
|
||||
{
|
||||
/* Code marked as runnning out of IRAM */
|
||||
_iram_text_start = ABSOLUTE(.);
|
||||
.. code-block:: none
|
||||
|
||||
/* Marker referencing iram0_text */
|
||||
mapping[iram0_text]
|
||||
.iram0.text :
|
||||
{
|
||||
/* Code marked as runnning out of IRAM */
|
||||
_iram_text_start = ABSOLUTE(.);
|
||||
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
/* Markers referencing iram0_text */
|
||||
arrays[iram0_text]
|
||||
mapping[iram0_text]
|
||||
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
.. only:: not SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
.iram0.text :
|
||||
{
|
||||
/* Code marked as runnning out of IRAM */
|
||||
_iram_text_start = ABSOLUTE(.);
|
||||
|
||||
/* Marker referencing iram0_text */
|
||||
mapping[iram0_text]
|
||||
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
Suppose the generator collected the fragment definitions below:
|
||||
|
||||
|
@ -532,26 +532,53 @@
|
||||
|
||||
如需引用一个 ``目标`` 标记下的所有存放规则,请使用以下语法:
|
||||
|
||||
.. code-block:: none
|
||||
.. only:: SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
|
||||
mapping[target]
|
||||
.. code-block:: none
|
||||
|
||||
arrays[target]
|
||||
mapping[target]
|
||||
|
||||
.. only:: not SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
mapping[target]
|
||||
|
||||
示例:
|
||||
|
||||
以下示例是某个链接器脚本模板的摘录,定义了输出段 ``.iram0.text``,该输出段包含一个引用目标 ``iram0_text`` 的标记。
|
||||
|
||||
.. code-block:: none
|
||||
.. only:: SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
|
||||
.iram0.text :
|
||||
{
|
||||
/* 标记 IRAM 空间不足 */
|
||||
_iram_text_start = ABSOLUTE(.);
|
||||
.. code-block:: none
|
||||
|
||||
/* 引用 iram0_text */
|
||||
mapping[iram0_text]
|
||||
.iram0.text :
|
||||
{
|
||||
/* 标记 IRAM 空间不足 */
|
||||
_iram_text_start = ABSOLUTE(.);
|
||||
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
/* 引用 iram0_text */
|
||||
arrays[iram0_text]
|
||||
mapping[iram0_text]
|
||||
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
.. only:: not SOC_MEM_NON_CONTIGUOUS_SRAM
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
.iram0.text :
|
||||
{
|
||||
/* 标记 IRAM 空间不足 */
|
||||
_iram_text_start = ABSOLUTE(.);
|
||||
|
||||
/* 引用 iram0_text */
|
||||
mapping[iram0_text]
|
||||
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
假设链接器脚本生成器收集到了以下片段定义:
|
||||
|
||||
|
@ -1246,7 +1246,6 @@ tools/ldgen/test/data/linker_script.ld
|
||||
tools/templates/sample_component/include/main.h
|
||||
tools/templates/sample_component/main.c
|
||||
tools/test_apps/build_system/embed_test/main/test_main.c
|
||||
tools/test_apps/build_system/ldalign_test/main/test_main.c
|
||||
tools/test_apps/build_system/ldgen_test/main/src1.c
|
||||
tools/test_apps/build_system/ldgen_test/main/src2.c
|
||||
tools/test_apps/build_system/ldgen_test/main/test_main.c
|
||||
|
@ -1,9 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import argparse
|
||||
import errno
|
||||
import json
|
||||
@ -19,7 +18,8 @@ from ldgen.generation import Generation
|
||||
from ldgen.ldgen_common import LdGenFailure
|
||||
from ldgen.linker_script import LinkerScript
|
||||
from ldgen.sdkconfig import SDKConfig
|
||||
from pyparsing import ParseException, ParseFatalException
|
||||
from pyparsing import ParseException
|
||||
from pyparsing import ParseFatalException
|
||||
|
||||
|
||||
def _update_environment(args):
|
||||
@ -148,7 +148,8 @@ def main():
|
||||
raise LdGenFailure('failed to parse %s\n%s' % (fragment_file, str(e)))
|
||||
generation_model.add_fragments_from_file(fragment_file)
|
||||
|
||||
mapping_rules = generation_model.generate(sections_infos)
|
||||
non_contiguous_sram = sdkconfig.evaluate_expression('SOC_MEM_NON_CONTIGUOUS_SRAM')
|
||||
mapping_rules = generation_model.generate(sections_infos, non_contiguous_sram)
|
||||
|
||||
script_model = LinkerScript(input_file)
|
||||
script_model.fill(mapping_rules)
|
||||
|
@ -1,17 +1,22 @@
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import collections
|
||||
import fnmatch
|
||||
import itertools
|
||||
from collections import namedtuple
|
||||
|
||||
from .entity import Entity
|
||||
from .fragments import Keep, Scheme, Sections, Sort, Surround
|
||||
from .fragments import Keep
|
||||
from .fragments import Scheme
|
||||
from .fragments import Sections
|
||||
from .fragments import Sort
|
||||
from .fragments import Surround
|
||||
from .ldgen_common import LdGenFailure
|
||||
from .output_commands import AlignAtAddress, InputSectionDesc, SymbolAtAddress
|
||||
from .output_commands import AlignAtAddress
|
||||
from .output_commands import InputSectionDesc
|
||||
from .output_commands import SymbolAtAddress
|
||||
|
||||
|
||||
class Placement:
|
||||
@ -149,7 +154,7 @@ class EntityNode:
|
||||
|
||||
return child
|
||||
|
||||
def get_output_commands(self):
|
||||
def get_output_commands(self, non_contiguous_sram):
|
||||
commands = collections.defaultdict(list)
|
||||
|
||||
def process_commands(cmds):
|
||||
@ -157,18 +162,18 @@ class EntityNode:
|
||||
commands[target].extend(commands_list)
|
||||
|
||||
# Process the commands generated from this node
|
||||
node_commands = self.get_node_output_commands()
|
||||
node_commands = self.get_node_output_commands(non_contiguous_sram)
|
||||
process_commands(node_commands)
|
||||
|
||||
# Process the commands generated from this node's children
|
||||
# recursively
|
||||
for child in sorted(self.children, key=lambda c: c.name):
|
||||
children_commands = child.get_output_commands()
|
||||
children_commands = child.get_output_commands(non_contiguous_sram)
|
||||
process_commands(children_commands)
|
||||
|
||||
return commands
|
||||
|
||||
def get_node_output_commands(self):
|
||||
def get_node_output_commands(self, non_contiguous_sram):
|
||||
commands = collections.defaultdict(list)
|
||||
|
||||
for sections in self.get_output_sections():
|
||||
@ -176,6 +181,7 @@ class EntityNode:
|
||||
if placement.is_significant():
|
||||
assert placement.node == self
|
||||
|
||||
tied = False
|
||||
keep = False
|
||||
sort = None
|
||||
surround_type = []
|
||||
@ -188,14 +194,16 @@ class EntityNode:
|
||||
elif isinstance(flag, Sort):
|
||||
sort = (flag.first, flag.second)
|
||||
else: # SURROUND or ALIGN
|
||||
if non_contiguous_sram and isinstance(flag, Surround):
|
||||
tied = True
|
||||
surround_type.append(flag)
|
||||
|
||||
for flag in surround_type:
|
||||
if flag.pre:
|
||||
if isinstance(flag, Surround):
|
||||
commands[placement.target].append(SymbolAtAddress('_%s_start' % flag.symbol))
|
||||
commands[placement.target].append(SymbolAtAddress(f'_{flag.symbol}_start', tied))
|
||||
else: # ALIGN
|
||||
commands[placement.target].append(AlignAtAddress(flag.alignment))
|
||||
commands[placement.target].append(AlignAtAddress(flag.alignment, tied))
|
||||
|
||||
# This is for expanded object node and symbol node placements without checking for
|
||||
# the type.
|
||||
@ -203,7 +211,7 @@ class EntityNode:
|
||||
command_sections = sections if sections == placement_sections else placement_sections
|
||||
|
||||
command = InputSectionDesc(placement.node.entity, command_sections,
|
||||
[e.node.entity for e in placement.exclusions], keep, sort)
|
||||
[e.node.entity for e in placement.exclusions], keep, sort, tied)
|
||||
commands[placement.target].append(command)
|
||||
|
||||
# Generate commands for intermediate, non-explicit exclusion placements here,
|
||||
@ -211,15 +219,15 @@ class EntityNode:
|
||||
for subplacement in placement.subplacements:
|
||||
if not subplacement.flags and not subplacement.explicit:
|
||||
command = InputSectionDesc(subplacement.node.entity, subplacement.sections,
|
||||
[e.node.entity for e in subplacement.exclusions], keep, sort)
|
||||
[e.node.entity for e in subplacement.exclusions], keep, sort, tied)
|
||||
commands[placement.target].append(command)
|
||||
|
||||
for flag in surround_type:
|
||||
if flag.post:
|
||||
if isinstance(flag, Surround):
|
||||
commands[placement.target].append(SymbolAtAddress('_%s_end' % flag.symbol))
|
||||
commands[placement.target].append(SymbolAtAddress(f'_{flag.symbol}_end', tied))
|
||||
else: # ALIGN
|
||||
commands[placement.target].append(AlignAtAddress(flag.alignment))
|
||||
commands[placement.target].append(AlignAtAddress(flag.alignment, tied))
|
||||
|
||||
return commands
|
||||
|
||||
@ -504,7 +512,7 @@ class Generation:
|
||||
res.sort(key=lambda m: m.entity)
|
||||
return res
|
||||
|
||||
def generate(self, entities):
|
||||
def generate(self, entities, non_contiguous_sram):
|
||||
scheme_dictionary = self._prepare_scheme_dictionary()
|
||||
entity_mappings = self._prepare_entity_mappings(scheme_dictionary, entities)
|
||||
root_node = RootNode()
|
||||
@ -516,7 +524,7 @@ class Generation:
|
||||
raise GenerationException(str(e))
|
||||
|
||||
# Traverse the tree, creating the placements
|
||||
commands = root_node.get_output_commands()
|
||||
commands = root_node.get_output_commands(non_contiguous_sram)
|
||||
|
||||
return commands
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import collections
|
||||
import os
|
||||
|
||||
from pyparsing import ParseException, Suppress, White
|
||||
from pyparsing import ParseException
|
||||
from pyparsing import Suppress
|
||||
from pyparsing import White
|
||||
|
||||
from .fragments import Fragment
|
||||
from .generation import GenerationException
|
||||
@ -21,7 +22,8 @@ class LinkerScript:
|
||||
The <target> is where output commands (see output_commands.py) are placed.
|
||||
"""
|
||||
|
||||
Marker = collections.namedtuple('Marker', 'target indent rules')
|
||||
MappingMarker = collections.namedtuple('MappingMarker', 'target indent rules')
|
||||
ArraysMarker = collections.namedtuple('ArraysMarker', 'target indent rules')
|
||||
|
||||
def __init__(self, template_file):
|
||||
self.members = []
|
||||
@ -33,30 +35,39 @@ class LinkerScript:
|
||||
lines = template_file.readlines()
|
||||
|
||||
target = Fragment.IDENTIFIER
|
||||
reference = Suppress('mapping') + Suppress('[') + target + Suppress(']')
|
||||
pattern = White(' \t') + reference
|
||||
pattern_mapping = White(' \t') + Suppress('mapping') + Suppress('[') + target + Suppress(']')
|
||||
pattern_arrays = White(' \t') + Suppress('arrays') + Suppress('[') + target + Suppress(']')
|
||||
|
||||
# Find the markers in the template file line by line. If line does not match marker grammar,
|
||||
# set it as a literal to be copied as is to the output file.
|
||||
for line in lines:
|
||||
try:
|
||||
parsed = pattern.parse_string(line)
|
||||
except ParseException:
|
||||
# Does not match marker syntax
|
||||
parsed = False
|
||||
for pattern in (pattern_arrays, pattern_mapping):
|
||||
try:
|
||||
indent, target = pattern.parse_string(line)
|
||||
if pattern is pattern_arrays:
|
||||
marker = LinkerScript.ArraysMarker(target, indent, [])
|
||||
else:
|
||||
marker = LinkerScript.MappingMarker(target, indent, [])
|
||||
self.members.append(marker)
|
||||
parsed = True
|
||||
except ParseException:
|
||||
continue
|
||||
if not parsed:
|
||||
# Does not match markers syntax
|
||||
self.members.append(line)
|
||||
else:
|
||||
indent, target = parsed
|
||||
marker = LinkerScript.Marker(target, indent, [])
|
||||
self.members.append(marker)
|
||||
|
||||
def fill(self, mapping_rules):
|
||||
for member in self.members:
|
||||
target = None
|
||||
try:
|
||||
target = member.target
|
||||
rules = member.rules
|
||||
|
||||
rules.extend(mapping_rules[target])
|
||||
if isinstance(member, self.ArraysMarker):
|
||||
rules = [x for x in mapping_rules[target] if x.tied]
|
||||
else:
|
||||
rules = [x for x in mapping_rules[target] if not x.tied]
|
||||
member.rules.extend(rules)
|
||||
except KeyError:
|
||||
message = GenerationException.UNDEFINED_REFERENCE + " to target '" + target + "'."
|
||||
raise GenerationException(message)
|
||||
|
@ -1,8 +1,7 @@
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from .entity import Entity
|
||||
|
||||
# Contains classes for output section commands referred to in
|
||||
@ -20,8 +19,9 @@ class AlignAtAddress:
|
||||
command to be emitted.
|
||||
"""
|
||||
|
||||
def __init__(self, alignment):
|
||||
def __init__(self, alignment, tied=False):
|
||||
self.alignment = alignment
|
||||
self.tied = tied
|
||||
|
||||
def __str__(self):
|
||||
return ('. = ALIGN(%d);' % self.alignment)
|
||||
@ -43,8 +43,9 @@ class SymbolAtAddress:
|
||||
an InputSectionDesc.
|
||||
"""
|
||||
|
||||
def __init__(self, symbol):
|
||||
def __init__(self, symbol, tied=False):
|
||||
self.symbol = symbol
|
||||
self.tied = tied
|
||||
|
||||
def __str__(self):
|
||||
return ('%s = ABSOLUTE(.);' % self.symbol)
|
||||
@ -64,7 +65,7 @@ class InputSectionDesc:
|
||||
the emitted input section description.
|
||||
"""
|
||||
|
||||
def __init__(self, entity, sections, exclusions=None, keep=False, sort=None):
|
||||
def __init__(self, entity, sections, exclusions=None, keep=False, sort=None, tied=False):
|
||||
assert entity.specificity != Entity.Specificity.SYMBOL
|
||||
|
||||
self.entity = entity
|
||||
@ -81,6 +82,7 @@ class InputSectionDesc:
|
||||
|
||||
self.keep = keep
|
||||
self.sort = sort
|
||||
self.tied = tied
|
||||
|
||||
def __str__(self):
|
||||
sections_string = '( )'
|
||||
|
@ -1,9 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import collections
|
||||
import fnmatch
|
||||
import os
|
||||
@ -123,7 +122,7 @@ class DefaultMappingTest(GenerationTest):
|
||||
# Checks that default rules are generated from
|
||||
# the default scheme properly and even if no mappings
|
||||
# are defined.
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
self.compare_rules(expected, actual)
|
||||
@ -234,7 +233,7 @@ entries:
|
||||
* (noflash) #1
|
||||
"""
|
||||
self.add_fragments(alt if alt else mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -272,7 +271,7 @@ entries:
|
||||
"""
|
||||
|
||||
self.add_fragments(alt if alt else mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -311,7 +310,7 @@ entries:
|
||||
croutine:prvCheckPendingReadyList (noflash) #1
|
||||
"""
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -367,7 +366,7 @@ entries:
|
||||
"""
|
||||
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -428,7 +427,7 @@ entries:
|
||||
croutine:prvCheckPendingReadyList (default) #2
|
||||
"""
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -497,7 +496,7 @@ entries:
|
||||
"""
|
||||
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -591,7 +590,7 @@ entries:
|
||||
"""
|
||||
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -642,7 +641,7 @@ entries:
|
||||
"""
|
||||
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
# Generate default command A
|
||||
@ -690,7 +689,7 @@ entries:
|
||||
croutine (noflash_data) #2
|
||||
"""
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -744,7 +743,7 @@ entries:
|
||||
croutine (noflash_data) #2
|
||||
"""
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -783,7 +782,7 @@ entries:
|
||||
self.add_fragments(alt if alt else mapping)
|
||||
|
||||
with self.assertRaises(GenerationException):
|
||||
self.generation.generate(self.entities)
|
||||
self.generation.generate(self.entities, False)
|
||||
|
||||
def test_same_entity_conflicting_section(self):
|
||||
# Test same entity being mapped by scheme conflicting with another.
|
||||
@ -862,7 +861,7 @@ entries:
|
||||
"""
|
||||
|
||||
self.add_fragments(alt if alt else mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -951,7 +950,7 @@ entries:
|
||||
"""
|
||||
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -1048,7 +1047,7 @@ entries:
|
||||
"""
|
||||
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -1090,7 +1089,7 @@ entries:
|
||||
self.add_fragments(mapping)
|
||||
|
||||
with self.assertRaises(GenerationException):
|
||||
self.generation.generate(self.entities)
|
||||
self.generation.generate(self.entities, False)
|
||||
|
||||
def test_root_mapping_fragment_conflict(self):
|
||||
# Test that root mapping fragments are also checked for
|
||||
@ -1111,7 +1110,7 @@ entries:
|
||||
|
||||
self.add_fragments(mapping)
|
||||
with self.assertRaises(GenerationException):
|
||||
self.generation.generate(self.entities)
|
||||
self.generation.generate(self.entities, False)
|
||||
|
||||
def test_root_mapping_fragment_duplicate(self):
|
||||
# Same root mappings have no effect.
|
||||
@ -1135,7 +1134,7 @@ entries:
|
||||
"""
|
||||
|
||||
self.add_fragments(mapping)
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
# Generate default command A
|
||||
@ -1180,7 +1179,7 @@ entries:
|
||||
self.add_fragments(scheme)
|
||||
self.add_fragments(alt if alt else mapping)
|
||||
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
if perf >= 1:
|
||||
@ -1231,7 +1230,7 @@ entries:
|
||||
self.generation.mappings = {}
|
||||
self.add_fragments(alt if alt else mapping)
|
||||
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
if perf_level < 4 and perf_level > 0:
|
||||
@ -1331,7 +1330,7 @@ entries:
|
||||
|
||||
self.add_fragments(mapping)
|
||||
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -1394,7 +1393,7 @@ entries:
|
||||
self.generation.mappings = {}
|
||||
self.add_fragments(mapping)
|
||||
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -1451,7 +1450,7 @@ entries:
|
||||
|
||||
self.add_fragments(mapping)
|
||||
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -1507,7 +1506,7 @@ entries:
|
||||
|
||||
self.add_fragments(mapping)
|
||||
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -1564,7 +1563,7 @@ entries:
|
||||
self.generation.mappings = {}
|
||||
self.add_fragments(mapping)
|
||||
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -1621,7 +1620,7 @@ entries:
|
||||
|
||||
self.add_fragments(mapping)
|
||||
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -1665,7 +1664,7 @@ entries:
|
||||
|
||||
self.add_fragments(mapping)
|
||||
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -1692,7 +1691,7 @@ entries:
|
||||
|
||||
self.add_fragments(mapping)
|
||||
|
||||
actual = self.generation.generate(self.entities)
|
||||
actual = self.generation.generate(self.entities, False)
|
||||
expected = self.generate_default_rules()
|
||||
|
||||
flash_text = expected['flash_text']
|
||||
@ -1719,7 +1718,7 @@ entries:
|
||||
self.add_fragments(mapping)
|
||||
|
||||
with self.assertRaises(GenerationException):
|
||||
self.generation.generate(self.entities)
|
||||
self.generation.generate(self.entities, False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -16,6 +16,10 @@ tools/test_apps/build_system/embed_test:
|
||||
temporary: false
|
||||
reason: Hardware independent feature, no need to test on all targets
|
||||
|
||||
tools/test_apps/build_system/ld_non_contiguous_memory:
|
||||
disable:
|
||||
- if: SOC_MEM_NON_CONTIGUOUS_SRAM != 1
|
||||
|
||||
tools/test_apps/linux_compatible/driver_mock:
|
||||
enable:
|
||||
- if: IDF_TARGET == "linux"
|
||||
|
@ -0,0 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(test_non_contiguous_regions)
|
@ -0,0 +1,2 @@
|
||||
| Supported Targets | ESP32-P4 |
|
||||
| ----------------- | -------- |
|
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "test_app_main.c"
|
||||
LDFRAGMENTS "linker.lf")
|
@ -0,0 +1,13 @@
|
||||
[sections:main_dram]
|
||||
entries:
|
||||
buf1
|
||||
buf2
|
||||
|
||||
[scheme:main_dram_config]
|
||||
entries:
|
||||
main_dram -> dram0_bss
|
||||
|
||||
[mapping:main]
|
||||
archive: libmain.a
|
||||
entries:
|
||||
* (main_dram_config)
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
extern int _bss_start_low, _bss_start_high;
|
||||
extern int _bss_end_low, _bss_end_high;
|
||||
|
||||
char buf1[100 * 1024];
|
||||
char buf2[100 * 1024];
|
||||
|
||||
static void test_mem_write(char* buf, size_t size_bytes, int seed)
|
||||
{
|
||||
srand(seed);
|
||||
for (size_t i = 0; i < size_bytes; ++i) {
|
||||
buf[i] = (char) (rand() % 256);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_mem_read(char* buf, size_t size_bytes, int seed)
|
||||
{
|
||||
size_t num_errors = 0;
|
||||
srand(seed);
|
||||
printf("Testing at %p ... ", buf);
|
||||
for (size_t i = 0; i < size_bytes; ++i) {
|
||||
if (buf[i] != (char) (rand() % 256)) {
|
||||
++num_errors;
|
||||
}
|
||||
}
|
||||
printf("%s!\n", num_errors == 0 ? "OK" : "ERROR");
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
if (! (((void *)&_bss_start_low <= (void *)buf2) && ((void *)buf2 < (void *)&_bss_end_low)))
|
||||
printf("buf2 (%p) is expected to be placed in low sram (%p .. %p)\n", buf2, &_bss_start_low, &_bss_end_low);
|
||||
else
|
||||
printf("buf2 placed in low sram\n");
|
||||
if (! ((void *)&_bss_start_high <= (void *)buf1 && (void *)buf1 < (void *)&_bss_end_high))
|
||||
printf("buf1 (%p) is expected to be placed in high sram (%p .. %p)\n", buf1, &_bss_start_high, &_bss_end_high);
|
||||
else
|
||||
printf("buf1 placed in high sram\n");
|
||||
|
||||
test_mem_write(buf2, sizeof(buf1), 1);
|
||||
test_mem_write(buf1, sizeof(buf1), 0);
|
||||
test_mem_read(buf1, sizeof(buf1), 0);
|
||||
test_mem_read(buf2, sizeof(buf2), 1);
|
||||
test_mem_write(buf2, sizeof(buf1), 1);
|
||||
test_mem_read(buf1, sizeof(buf1), 0);
|
||||
test_mem_read(buf2, sizeof(buf2), 1);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
TEST_APP_IN_FLASH = [pytest.param('app_in_flash', marks=pytest.mark.esp32p4)]
|
||||
|
||||
|
||||
@pytest.mark.esp32p4
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize('config', TEST_APP_IN_FLASH, indirect=True)
|
||||
def test_ld_non_contiguous_memory(dut: Dut) -> None:
|
||||
dut.expect_exact('buf2 placed in low sram')
|
||||
dut.expect_exact('buf1 placed in high sram')
|
||||
for _ in range(0, 4):
|
||||
dut.expect(r'Testing at 0x[0-9a-f]+ ... OK!')
|
@ -1,22 +0,0 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
#"Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
set(COMPONENTS main)
|
||||
|
||||
project(ldalign_test)
|
||||
|
||||
idf_build_get_property(python PYTHON)
|
||||
idf_build_get_property(elf EXECUTABLE)
|
||||
|
||||
set(check_alignment "${CMAKE_CURRENT_LIST_DIR}/check_alignment.py")
|
||||
set(readelf "${_CMAKE_TOOLCHAIN_PREFIX}readelf")
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${elf}
|
||||
POST_BUILD
|
||||
COMMAND ${python} ${check_alignment} ${readelf} $<TARGET_FILE:${elf}>
|
||||
)
|
@ -1,2 +0,0 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
@ -1,7 +0,0 @@
|
||||
Runs a build test to check alignment and position of `.flash.appdesc` and
|
||||
`.flash.rodata` sections. Indeed, `.flash.appdesc` shall ALWAYS be aligned on
|
||||
a 16-byte bounds, whereas `.flash.rodata` can have any alignment. In any case,
|
||||
the end address of first one shall match the start address of the second one.
|
||||
This will let both of them be merged when generating the final bin image.
|
||||
The Python script that performs the checks, `check_alignment.py`, automatically
|
||||
runs after the app is built.
|
@ -1,53 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import subprocess
|
||||
from typing import Tuple
|
||||
|
||||
argparser = argparse.ArgumentParser()
|
||||
|
||||
argparser.add_argument('readelf')
|
||||
argparser.add_argument('elf')
|
||||
|
||||
args = argparser.parse_args()
|
||||
|
||||
# Get the content of the readelf command
|
||||
contents = subprocess.check_output([args.readelf, '-S', args.elf]).decode()
|
||||
|
||||
|
||||
# Define a class for readelf parsing error
|
||||
class ParsingError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
# Look for the start address and size of any section
|
||||
def find_partition_info(sectionname): # type: (str) -> Tuple[int, int, int]
|
||||
match = re.search(sectionname + r'\s+PROGBITS\s+([a-f0-9]+) [a-f0-9]+ ([a-f0-9]+) \d+\s+[A-Z]+ 0 0 (\d+)',
|
||||
contents)
|
||||
if not match:
|
||||
raise ParsingError('ELF header parsing error')
|
||||
# Return the address of the section, the size and the alignment
|
||||
address = match.group(1)
|
||||
size = match.group(2)
|
||||
alignment = match.group(3)
|
||||
return (int(address, 16), int(size, 16), int(alignment, 10))
|
||||
|
||||
|
||||
# Get address and size for .flash.appdesc section
|
||||
app_address, app_size, app_align = find_partition_info('.flash.appdesc')
|
||||
|
||||
# Same goes for .flash.rodata section
|
||||
rodata_address, _, rodata_align = find_partition_info('.flash.rodata')
|
||||
|
||||
# Assert than everything is as expected:
|
||||
# appdesc is aligned on 16
|
||||
# rodata is aligned on 64
|
||||
# appdesc ends where rodata starts
|
||||
assert app_align == 16, '.flash.appdesc section should have been aligned on 16!'
|
||||
assert rodata_align == 64, '.flash.rodata section should have been aligned on 64!'
|
||||
assert app_address + app_size == rodata_address, ".flash.appdesc's end address and .flash.rodata's begin start must have no gap in between!"
|
@ -1,3 +0,0 @@
|
||||
idf_component_register(SRCS "test_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
@ -1,16 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
const static uint32_t __attribute__ ((aligned (64))) testTab[] =
|
||||
{
|
||||
0xff445566, 0x44556677, 0x33221100,
|
||||
0x88997755, 0x99887755, 0x88997755,
|
||||
0x99546327, 0x7946fa9e, 0xa6b5f8ee,
|
||||
0x12345678
|
||||
};
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/* Do something with the array, in order to avoid it being discarded. */
|
||||
for (uint32_t i = 0; i < 10; i++)
|
||||
printf ("%x\n", testTab[i]);
|
||||
}
|
@ -16,6 +16,10 @@ if(NOT CONFIG_SOC_RTC_MEM_SUPPORTED)
|
||||
set(args "--no-rtc")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_MEM_NON_CONTIGUOUS_SRAM)
|
||||
set(args "--non-contiguous-sram")
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${elf}
|
||||
POST_BUILD
|
||||
|
@ -1,22 +1,27 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# Check placements in this test app for main
|
||||
# specified in main/linker.lf
|
||||
|
||||
import argparse
|
||||
import subprocess
|
||||
|
||||
from pyparsing import LineEnd, LineStart, Literal, Optional, Word, alphanums, hexnums
|
||||
from pyparsing import alphanums
|
||||
from pyparsing import hexnums
|
||||
from pyparsing import LineEnd
|
||||
from pyparsing import LineStart
|
||||
from pyparsing import Literal
|
||||
from pyparsing import Optional
|
||||
from pyparsing import Word
|
||||
|
||||
argparser = argparse.ArgumentParser()
|
||||
|
||||
argparser.add_argument('objdump')
|
||||
argparser.add_argument('elf')
|
||||
argparser.add_argument('--no-rtc', action='store_true')
|
||||
argparser.add_argument('--non-contiguous-sram', action='store_true')
|
||||
|
||||
args = argparser.parse_args()
|
||||
|
||||
@ -57,6 +62,15 @@ assert sym1_start % 9 == 0, '_sym1_start is not aligned as specified in linker f
|
||||
assert sym1_end % 12 == 0, '_sym1_end is not aligned as specified in linker fragment'
|
||||
print('check placement pass: _sym1_start < func1 < __sym1_end and alignments checked')
|
||||
|
||||
func0 = check_location('func0', '.iram0.text')
|
||||
|
||||
if args.non_contiguous_sram:
|
||||
assert func1 < func0, 'check placement fail: func1 comes after func0'
|
||||
print('check placement pass: func1 < func0 checked')
|
||||
else:
|
||||
assert func1 > func0, 'check placement fail: func0 comes after func1'
|
||||
print('check placement pass: func1 > func0 checked')
|
||||
|
||||
# src1:func2 (rtc) - explicit mapping for func2 using 'rtc' scheme
|
||||
if not args.no_rtc:
|
||||
check_location('func2', '.rtc.text')
|
||||
|
@ -5,5 +5,7 @@ entries:
|
||||
src1 (default)
|
||||
src1:func1 (noflash);
|
||||
text->iram0_text KEEP() ALIGN(9) ALIGN(12, post) SURROUND(sym1)
|
||||
src1:func0 (noflash);
|
||||
text->iram0_text KEEP()
|
||||
if SOC_RTC_MEM_SUPPORTED = y:
|
||||
src1:func2 (rtc)
|
||||
|
@ -1,5 +1,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void func0(void)
|
||||
{
|
||||
printf("Hello from func0!\n");
|
||||
}
|
||||
|
||||
void func1(void)
|
||||
{
|
||||
printf("Hello from func1!\n");
|
||||
|
Loading…
Reference in New Issue
Block a user