Merge branch 'feat/ldgen_fast_reflashing' into 'master'

feat(ldgen): initial support for fast reflashing

Closes IDF-14213

See merge request espressif/esp-idf!42780
This commit is contained in:
Roland Dobai
2025-11-18 10:28:49 +01:00
22 changed files with 1248 additions and 242 deletions
+4
View File
@@ -159,6 +159,10 @@ if(CONFIG_COMPILER_NO_MERGE_CONSTANTS)
list(APPEND compile_options "-fno-merge-constants") list(APPEND compile_options "-fno-merge-constants")
endif() endif()
if(CONFIG_COMPILER_ENABLE_TEXT_SECTION_LITERALS)
list(APPEND compile_options "-mtext-section-literals")
endif()
if(CONFIG_COMPILER_STACK_CHECK_MODE_NORM) if(CONFIG_COMPILER_STACK_CHECK_MODE_NORM)
list(APPEND compile_options "-fstack-protector") list(APPEND compile_options "-fstack-protector")
elseif(CONFIG_COMPILER_STACK_CHECK_MODE_STRONG) elseif(CONFIG_COMPILER_STACK_CHECK_MODE_STRONG)
+15
View File
@@ -576,6 +576,20 @@ mainmenu "Espressif IoT Development Framework Configuration"
distribution is more uniform across libraries. On downside, it may increase distribution is more uniform across libraries. On downside, it may increase
the binary size and hence should be used during development phase only. the binary size and hence should be used during development phase only.
config COMPILER_ENABLE_TEXT_SECTION_LITERALS
bool
depends on IDF_TOOLCHAIN_GCC
depends on IDF_TARGET_ARCH_XTENSA
default y if ESPTOOLPY_FAST_REFLASHING
help
Intersperse Xtensa literals within the text section to keep
them as close as possible to their references. This prevents
literals from being placed into a separate section in the
output file and prevents the linker from combining literal
pools from different object files. Enabling this is necessary
for fast reflashing to prevent mixing code from mutable and
immutable libraries.
config COMPILER_WARN_WRITE_STRINGS config COMPILER_WARN_WRITE_STRINGS
bool "Enable -Wwrite-strings warning flag" bool "Enable -Wwrite-strings warning flag"
default "n" default "n"
@@ -784,3 +798,4 @@ mainmenu "Espressif IoT Development Framework Configuration"
- CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION - CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
- CONFIG_I3C_MASTER_ENABLED - CONFIG_I3C_MASTER_ENABLED
- CONFIG_MBEDTLS_ESP_IDF_USE_PSA_CRYPTO - CONFIG_MBEDTLS_ESP_IDF_USE_PSA_CRYPTO
- CONFIG_ESPTOOLPY_FAST_REFLASHING
@@ -21,6 +21,10 @@ SECTIONS
mapping[rtc_text] mapping[rtc_text]
/* mutable libs begin */
mutable[rtc_text]
/* mutable libs end */
*rtc_wake_stub*.*(.literal .text .literal.* .text.*) *rtc_wake_stub*.*(.literal .text .literal.* .text.*)
_rtc_text_end = ABSOLUTE(.); _rtc_text_end = ABSOLUTE(.);
@@ -51,6 +55,10 @@ SECTIONS
mapping[rtc_force_fast] mapping[rtc_force_fast]
/* mutable libs begin */
mutable[rtc_force_fast]
/* mutable libs end */
*(.rtc.force_fast .rtc.force_fast.*) *(.rtc.force_fast .rtc.force_fast.*)
ALIGNED_SYMBOL(4, _rtc_force_fast_end) ALIGNED_SYMBOL(4, _rtc_force_fast_end)
@@ -70,6 +78,10 @@ SECTIONS
mapping[rtc_data] mapping[rtc_data]
/* mutable libs begin */
mutable[rtc_data]
/* mutable libs end */
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*)
_rtc_data_end = ABSOLUTE(.); _rtc_data_end = ABSOLUTE(.);
@@ -85,6 +97,10 @@ SECTIONS
mapping[rtc_bss] mapping[rtc_bss]
/* mutable libs begin */
mutable[rtc_bss]
/* mutable libs end */
_rtc_bss_end = ABSOLUTE(.); _rtc_bss_end = ABSOLUTE(.);
} > rtc_data_location } > rtc_data_location
@@ -224,6 +240,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > iram0_0_seg } > iram0_0_seg
.dram0.data : .dram0.data :
@@ -239,6 +260,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > dram0_0_seg } > dram0_0_seg
@@ -277,6 +303,10 @@ SECTIONS
mapping[extern_ram] mapping[extern_ram]
/* mutable libs begin */
mutable[extern_ram]
/* mutable libs end */
ALIGNED_SYMBOL(4, _ext_ram_bss_end) ALIGNED_SYMBOL(4, _ext_ram_bss_end)
} > extern_ram_seg } > extern_ram_seg
@@ -289,8 +319,13 @@ SECTIONS
* ldgen places all bss-related data to mapping[dram0_bss] * ldgen places all bss-related data to mapping[dram0_bss]
* (See components/esp_system/app.lf). * (See components/esp_system/app.lf).
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > dram0_0_seg } > dram0_0_seg
@@ -377,6 +412,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */ /* Literals are also RO data. */
@@ -411,6 +451,10 @@ SECTIONS
_rodata_reserved_end = ABSOLUTE(.); _rodata_reserved_end = ABSOLUTE(.);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
.flash.text : .flash.text :
@@ -425,6 +469,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.warning) *(.gnu.warning)
*(.gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
@@ -466,6 +515,10 @@ SECTIONS
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
_iram_data_end = ABSOLUTE(.); _iram_data_end = ABSOLUTE(.);
} > iram0_0_seg } > iram0_0_seg
@@ -475,6 +528,10 @@ SECTIONS
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
ALIGNED_SYMBOL(4, _iram_end) ALIGNED_SYMBOL(4, _iram_end)
} > iram0_0_seg } > iram0_0_seg
@@ -24,6 +24,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > iram0_0_seg } > iram0_0_seg
/** /**
@@ -42,7 +47,12 @@ SECTIONS
.dram0.bt.data : .dram0.bt.data :
{ {
_data_start = ABSOLUTE(.); _data_start = ABSOLUTE(.);
mapping[dram0_bt_data] mapping[dram0_bt_data]
/* mutable libs begin */
mutable[dram0_bt_data]
/* mutable libs end */
} > dram0_0_seg } > dram0_0_seg
.dram0.bt.bss (NOLOAD) : .dram0.bt.bss (NOLOAD) :
@@ -51,6 +61,10 @@ SECTIONS
mapping[dram0_bt_bss] mapping[dram0_bt_bss]
/* mutable libs begin */
mutable[dram0_bt_bss]
/* mutable libs end */
_bss_bt_end = ABSOLUTE(.); _bss_bt_end = ABSOLUTE(.);
} > dram0_0_seg } > dram0_0_seg
@@ -67,6 +81,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > dram0_0_seg } > dram0_0_seg
@@ -94,8 +113,13 @@ SECTIONS
* ldgen places all bss-related data to mapping[dram0_bss] * ldgen places all bss-related data to mapping[dram0_bss]
* (See components/esp_system/app.lf). * (See components/esp_system/app.lf).
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > dram0_0_seg } > dram0_0_seg
@@ -114,6 +138,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.linkonce.t.*) *(.gnu.linkonce.t.*)
*(.gnu.warning) *(.gnu.warning)
@@ -216,6 +245,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
. = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA));
} > default_rodata_seg } > default_rodata_seg
@@ -287,6 +321,10 @@ SECTIONS
_rodata_reserved_end = ADDR(.flash.tbss); _rodata_reserved_end = ADDR(.flash.tbss);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
/* Marks the end of IRAM code segment */ /* Marks the end of IRAM code segment */
@@ -301,6 +339,10 @@ SECTIONS
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
_iram_data_end = ABSOLUTE(.); _iram_data_end = ABSOLUTE(.);
} > iram0_0_seg } > iram0_0_seg
@@ -310,6 +352,10 @@ SECTIONS
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
} > iram0_0_seg } > iram0_0_seg
@@ -324,6 +370,10 @@ SECTIONS
mapping[iram0_bt_text] mapping[iram0_bt_text]
/* mutable libs begin */
mutable[iram0_bt_text]
/* mutable libs end */
ALIGNED_SYMBOL(16, _iram_end) ALIGNED_SYMBOL(16, _iram_end)
} > iram0_0_seg } > iram0_0_seg
@@ -23,6 +23,10 @@ SECTIONS
mapping[rtc_text] mapping[rtc_text]
/* mutable libs begin */
mutable[rtc_text]
/* mutable libs end */
*rtc_wake_stub*.*(.text .text.*) *rtc_wake_stub*.*(.text .text.*)
*(.rtc_text_end_test) *(.rtc_text_end_test)
@@ -46,6 +50,10 @@ SECTIONS
mapping[rtc_force_fast] mapping[rtc_force_fast]
/* mutable libs begin */
mutable[rtc_force_fast]
/* mutable libs end */
*(.rtc.force_fast .rtc.force_fast.*) *(.rtc.force_fast .rtc.force_fast.*)
ALIGNED_SYMBOL(4, _rtc_force_fast_end) ALIGNED_SYMBOL(4, _rtc_force_fast_end)
@@ -63,6 +71,10 @@ SECTIONS
mapping[rtc_data] mapping[rtc_data]
/* mutable libs begin */
mutable[rtc_data]
/* mutable libs end */
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.); _rtc_data_end = ABSOLUTE(.);
@@ -78,6 +90,10 @@ SECTIONS
mapping[rtc_bss] mapping[rtc_bss]
/* mutable libs begin */
mutable[rtc_bss]
/* mutable libs end */
_rtc_bss_end = ABSOLUTE(.); _rtc_bss_end = ABSOLUTE(.);
} > rtc_data_location } > rtc_data_location
@@ -164,6 +180,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > iram0_0_seg } > iram0_0_seg
/** /**
@@ -189,6 +210,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > dram0_0_seg } > dram0_0_seg
@@ -216,8 +242,13 @@ SECTIONS
* ldgen places all bss-related data to mapping[dram0_bss] * ldgen places all bss-related data to mapping[dram0_bss]
* (See components/esp_system/app.lf). * (See components/esp_system/app.lf).
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > dram0_0_seg } > dram0_0_seg
@@ -236,6 +267,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.linkonce.t.*) *(.gnu.linkonce.t.*)
*(.gnu.warning) *(.gnu.warning)
@@ -338,6 +374,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
. = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA));
} > default_rodata_seg } > default_rodata_seg
@@ -409,6 +450,10 @@ SECTIONS
_rodata_reserved_end = ADDR(.flash.tbss); _rodata_reserved_end = ADDR(.flash.tbss);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
/* Marks the end of IRAM code segment */ /* Marks the end of IRAM code segment */
@@ -430,6 +475,10 @@ SECTIONS
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
_iram_data_end = ABSOLUTE(.); _iram_data_end = ABSOLUTE(.);
} > iram0_0_seg } > iram0_0_seg
@@ -439,6 +488,10 @@ SECTIONS
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
ALIGNED_SYMBOL(16, _iram_end) ALIGNED_SYMBOL(16, _iram_end)
} > iram0_0_seg } > iram0_0_seg
@@ -28,6 +28,10 @@ SECTIONS
mapping[rtc_text] mapping[rtc_text]
/* mutable libs begin */
mutable[rtc_text]
/* mutable libs end */
*rtc_wake_stub*.*(.text .text.*) *rtc_wake_stub*.*(.text .text.*)
*(.rtc_text_end_test) *(.rtc_text_end_test)
@@ -48,6 +52,10 @@ SECTIONS
mapping[rtc_force_fast] mapping[rtc_force_fast]
/* mutable libs begin */
mutable[rtc_force_fast]
/* mutable libs end */
*(.rtc.force_fast .rtc.force_fast.*) *(.rtc.force_fast .rtc.force_fast.*)
ALIGNED_SYMBOL(4, _rtc_force_fast_end) ALIGNED_SYMBOL(4, _rtc_force_fast_end)
@@ -65,6 +73,10 @@ SECTIONS
mapping[rtc_data] mapping[rtc_data]
/* mutable libs begin */
mutable[rtc_data]
/* mutable libs end */
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.); _rtc_data_end = ABSOLUTE(.);
@@ -80,6 +92,10 @@ SECTIONS
mapping[rtc_bss] mapping[rtc_bss]
/* mutable libs begin */
mutable[rtc_bss]
/* mutable libs end */
_rtc_bss_end = ABSOLUTE(.); _rtc_bss_end = ABSOLUTE(.);
} > lp_ram_seg } > lp_ram_seg
@@ -179,6 +195,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > sram_seg } > sram_seg
/* Marks the end of IRAM code segment */ /* Marks the end of IRAM code segment */
@@ -196,6 +217,10 @@ SECTIONS
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
_iram_data_end = ABSOLUTE(.); _iram_data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -205,6 +230,10 @@ SECTIONS
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
ALIGNED_SYMBOL(16, _iram_end) ALIGNED_SYMBOL(16, _iram_end)
} > sram_seg } > sram_seg
@@ -232,6 +261,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -261,6 +295,10 @@ SECTIONS
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > sram_seg } > sram_seg
@@ -278,6 +316,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.linkonce.t.*) *(.gnu.linkonce.t.*)
*(.gnu.warning) *(.gnu.warning)
@@ -387,6 +430,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
. = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA));
} > default_rodata_seg } > default_rodata_seg
@@ -466,6 +514,10 @@ SECTIONS
_rodata_reserved_end = ADDR(.flash.tbss); _rodata_reserved_end = ADDR(.flash.tbss);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
/* Marks the end of data, bss and possibly rodata */ /* Marks the end of data, bss and possibly rodata */
@@ -494,6 +546,10 @@ SECTIONS
mapping[extern_ram] mapping[extern_ram]
/* mutable libs begin */
mutable[extern_ram]
/* mutable libs end */
ALIGNED_SYMBOL(4, _ext_ram_bss_end) ALIGNED_SYMBOL(4, _ext_ram_bss_end)
} > extern_ram_seg } > extern_ram_seg
#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY #endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
@@ -28,6 +28,10 @@ SECTIONS
mapping[rtc_text] mapping[rtc_text]
/* mutable libs begin */
mutable[rtc_text]
/* mutable libs end */
*rtc_wake_stub*.*(.text .text.*) *rtc_wake_stub*.*(.text .text.*)
*(.rtc_text_end_test) *(.rtc_text_end_test)
@@ -48,6 +52,10 @@ SECTIONS
mapping[rtc_force_fast] mapping[rtc_force_fast]
/* mutable libs begin */
mutable[rtc_force_fast]
/* mutable libs end */
*(.rtc.force_fast .rtc.force_fast.*) *(.rtc.force_fast .rtc.force_fast.*)
ALIGNED_SYMBOL(4, _rtc_force_fast_end) ALIGNED_SYMBOL(4, _rtc_force_fast_end)
@@ -65,6 +73,10 @@ SECTIONS
mapping[rtc_data] mapping[rtc_data]
/* mutable libs begin */
mutable[rtc_data]
/* mutable libs end */
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.); _rtc_data_end = ABSOLUTE(.);
@@ -80,6 +92,10 @@ SECTIONS
mapping[rtc_bss] mapping[rtc_bss]
/* mutable libs begin */
mutable[rtc_bss]
/* mutable libs end */
_rtc_bss_end = ABSOLUTE(.); _rtc_bss_end = ABSOLUTE(.);
} > lp_ram_seg } > lp_ram_seg
@@ -192,6 +208,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > sram_seg } > sram_seg
/* Marks the end of IRAM code segment */ /* Marks the end of IRAM code segment */
@@ -209,6 +230,10 @@ SECTIONS
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
_iram_data_end = ABSOLUTE(.); _iram_data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -218,6 +243,10 @@ SECTIONS
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
ALIGNED_SYMBOL(16, _iram_end) ALIGNED_SYMBOL(16, _iram_end)
@@ -237,6 +266,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -266,6 +300,10 @@ SECTIONS
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > sram_seg } > sram_seg
@@ -281,6 +319,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.linkonce.t.*) *(.gnu.linkonce.t.*)
*(.gnu.warning) *(.gnu.warning)
@@ -383,6 +426,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
. = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA));
} > default_rodata_seg } > default_rodata_seg
@@ -454,6 +502,10 @@ SECTIONS
_rodata_reserved_end = ADDR(.flash.tbss); _rodata_reserved_end = ADDR(.flash.tbss);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
/* Marks the end of data, bss and possibly rodata */ /* Marks the end of data, bss and possibly rodata */
@@ -37,6 +37,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > sram_seg } > sram_seg
/* Marks the end of IRAM code segment */ /* Marks the end of IRAM code segment */
@@ -54,6 +59,10 @@ SECTIONS
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
_iram_data_end = ABSOLUTE(.); _iram_data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -63,6 +72,10 @@ SECTIONS
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
ALIGNED_SYMBOL(16, _iram_end) ALIGNED_SYMBOL(16, _iram_end)
} > sram_seg } > sram_seg
@@ -90,6 +103,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -119,6 +137,10 @@ SECTIONS
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > sram_seg } > sram_seg
@@ -136,6 +158,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.linkonce.t.*) *(.gnu.linkonce.t.*)
*(.gnu.warning) *(.gnu.warning)
@@ -246,6 +273,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
. = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA));
} > default_rodata_seg } > default_rodata_seg
@@ -325,6 +357,10 @@ SECTIONS
_rodata_reserved_end = ADDR(.flash.tbss); _rodata_reserved_end = ADDR(.flash.tbss);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
/* Marks the end of data, bss and possibly rodata */ /* Marks the end of data, bss and possibly rodata */
@@ -353,6 +389,10 @@ SECTIONS
mapping[extern_ram] mapping[extern_ram]
/* mutable libs begin */
mutable[extern_ram]
/* mutable libs end */
ALIGNED_SYMBOL(4, _ext_ram_bss_end) ALIGNED_SYMBOL(4, _ext_ram_bss_end)
} > extern_ram_seg } > extern_ram_seg
#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY #endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
@@ -28,6 +28,10 @@ SECTIONS
mapping[rtc_text] mapping[rtc_text]
/* mutable libs begin */
mutable[rtc_text]
/* mutable libs end */
*rtc_wake_stub*.*(.text .text.*) *rtc_wake_stub*.*(.text .text.*)
*(.rtc_text_end_test) *(.rtc_text_end_test)
@@ -48,6 +52,10 @@ SECTIONS
mapping[rtc_force_fast] mapping[rtc_force_fast]
/* mutable libs begin */
mutable[rtc_force_fast]
/* mutable libs end */
*(.rtc.force_fast .rtc.force_fast.*) *(.rtc.force_fast .rtc.force_fast.*)
ALIGNED_SYMBOL(4, _rtc_force_fast_end) ALIGNED_SYMBOL(4, _rtc_force_fast_end)
@@ -65,6 +73,10 @@ SECTIONS
mapping[rtc_data] mapping[rtc_data]
/* mutable libs begin */
mutable[rtc_data]
/* mutable libs end */
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.); _rtc_data_end = ABSOLUTE(.);
@@ -80,6 +92,10 @@ SECTIONS
mapping[rtc_bss] mapping[rtc_bss]
/* mutable libs begin */
mutable[rtc_bss]
/* mutable libs end */
_rtc_bss_end = ABSOLUTE(.); _rtc_bss_end = ABSOLUTE(.);
} > lp_ram_seg } > lp_ram_seg
@@ -194,6 +210,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > sram_seg } > sram_seg
/* Marks the end of IRAM code segment */ /* Marks the end of IRAM code segment */
@@ -211,6 +232,10 @@ SECTIONS
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
_iram_data_end = ABSOLUTE(.); _iram_data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -220,6 +245,10 @@ SECTIONS
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
ALIGNED_SYMBOL(16, _iram_end) ALIGNED_SYMBOL(16, _iram_end)
@@ -239,6 +268,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -268,6 +302,10 @@ SECTIONS
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > sram_seg } > sram_seg
@@ -283,6 +321,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.linkonce.t.*) *(.gnu.linkonce.t.*)
*(.gnu.warning) *(.gnu.warning)
@@ -385,6 +428,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
. = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA));
} > default_rodata_seg } > default_rodata_seg
@@ -456,6 +504,10 @@ SECTIONS
_rodata_reserved_end = ADDR(.flash.tbss); _rodata_reserved_end = ADDR(.flash.tbss);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
/* Marks the end of data, bss and possibly rodata */ /* Marks the end of data, bss and possibly rodata */
@@ -30,6 +30,10 @@ SECTIONS
mapping[rtc_text] mapping[rtc_text]
/* mutable libs begin */
mutable[rtc_text]
/* mutable libs end */
*rtc_wake_stub*.*(.text .text.*) *rtc_wake_stub*.*(.text .text.*)
*(.rtc_text_end_test) *(.rtc_text_end_test)
@@ -50,6 +54,10 @@ SECTIONS
mapping[rtc_force_fast] mapping[rtc_force_fast]
/* mutable libs begin */
mutable[rtc_force_fast]
/* mutable libs end */
*(.rtc.force_fast .rtc.force_fast.*) *(.rtc.force_fast .rtc.force_fast.*)
ALIGNED_SYMBOL(4, _rtc_force_fast_end) ALIGNED_SYMBOL(4, _rtc_force_fast_end)
@@ -67,6 +75,10 @@ SECTIONS
mapping[rtc_data] mapping[rtc_data]
/* mutable libs begin */
mutable[rtc_data]
/* mutable libs end */
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.); _rtc_data_end = ABSOLUTE(.);
@@ -82,6 +94,10 @@ SECTIONS
mapping[rtc_bss] mapping[rtc_bss]
/* mutable libs begin */
mutable[rtc_bss]
/* mutable libs end */
_rtc_bss_end = ABSOLUTE(.); _rtc_bss_end = ABSOLUTE(.);
} > lp_ram_seg } > lp_ram_seg
@@ -183,6 +199,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > sram_seg } > sram_seg
/* Marks the end of IRAM code segment */ /* Marks the end of IRAM code segment */
@@ -200,6 +221,10 @@ SECTIONS
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
_iram_data_end = ABSOLUTE(.); _iram_data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -209,6 +234,10 @@ SECTIONS
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
ALIGNED_SYMBOL(16, _iram_end) ALIGNED_SYMBOL(16, _iram_end)
@@ -228,6 +257,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -257,6 +291,10 @@ SECTIONS
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > sram_seg } > sram_seg
@@ -272,6 +310,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.linkonce.t.*) *(.gnu.linkonce.t.*)
*(.gnu.warning) *(.gnu.warning)
@@ -374,6 +417,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
. = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA));
} > default_rodata_seg } > default_rodata_seg
@@ -445,6 +493,10 @@ SECTIONS
_rodata_reserved_end = ADDR(.flash.tbss); _rodata_reserved_end = ADDR(.flash.tbss);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
/* Marks the end of data, bss and possibly rodata */ /* Marks the end of data, bss and possibly rodata */
@@ -27,6 +27,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > sram_seg } > sram_seg
/* Marks the end of IRAM code segment */ /* Marks the end of IRAM code segment */
@@ -44,6 +49,10 @@ SECTIONS
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
_iram_data_end = ABSOLUTE(.); _iram_data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -53,6 +62,10 @@ SECTIONS
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
ALIGNED_SYMBOL(16, _iram_end) ALIGNED_SYMBOL(16, _iram_end)
} > sram_seg } > sram_seg
@@ -71,6 +84,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > sram_seg } > sram_seg
@@ -100,6 +118,10 @@ SECTIONS
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > sram_seg } > sram_seg
@@ -117,6 +139,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.linkonce.t.*) *(.gnu.linkonce.t.*)
*(.gnu.warning) *(.gnu.warning)
@@ -219,6 +246,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
. = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA));
} > default_rodata_seg } > default_rodata_seg
@@ -290,6 +322,10 @@ SECTIONS
_rodata_reserved_end = ADDR(.flash.tbss); _rodata_reserved_end = ADDR(.flash.tbss);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
/* Marks the end of data, bss and possibly rodata */ /* Marks the end of data, bss and possibly rodata */
@@ -26,8 +26,13 @@ SECTIONS
ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_text_start) ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_text_start)
arrays[rtc_text] arrays[rtc_text]
mapping[rtc_text] mapping[rtc_text]
/* mutable libs begin */
mutable[rtc_text]
/* mutable libs end */
*rtc_wake_stub*.*(.text .text.*) *rtc_wake_stub*.*(.text .text.*)
*(.rtc_text_end_test) *(.rtc_text_end_test)
@@ -47,8 +52,13 @@ SECTIONS
ALIGNED_SYMBOL(4, _rtc_force_fast_start) ALIGNED_SYMBOL(4, _rtc_force_fast_start)
arrays[rtc_force_fast] arrays[rtc_force_fast]
mapping[rtc_force_fast] mapping[rtc_force_fast]
/* mutable libs begin */
mutable[rtc_force_fast]
/* mutable libs end */
*(.rtc.force_fast .rtc.force_fast.*) *(.rtc.force_fast .rtc.force_fast.*)
ALIGNED_SYMBOL(4, _rtc_force_fast_end) ALIGNED_SYMBOL(4, _rtc_force_fast_end)
@@ -65,8 +75,13 @@ SECTIONS
_rtc_data_start = ABSOLUTE(.); _rtc_data_start = ABSOLUTE(.);
arrays[rtc_data] arrays[rtc_data]
mapping[rtc_data] mapping[rtc_data]
/* mutable libs begin */
mutable[rtc_data]
/* mutable libs end */
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.); _rtc_data_end = ABSOLUTE(.);
@@ -81,8 +96,13 @@ SECTIONS
*rtc_wake_stub*.*(COMMON) *rtc_wake_stub*.*(COMMON)
arrays[rtc_bss] arrays[rtc_bss]
mapping[rtc_bss] mapping[rtc_bss]
/* mutable libs begin */
mutable[rtc_bss]
/* mutable libs end */
_rtc_bss_end = ABSOLUTE(.); _rtc_bss_end = ABSOLUTE(.);
} > lp_ram_seg } > lp_ram_seg
@@ -163,8 +183,13 @@ SECTIONS
_tcm_text_start = ABSOLUTE(.); _tcm_text_start = ABSOLUTE(.);
arrays[tcm_text] arrays[tcm_text]
mapping[tcm_text] mapping[tcm_text]
/* mutable libs begin */
mutable[tcm_text]
/* mutable libs end */
_tcm_text_end = ABSOLUTE(.); _tcm_text_end = ABSOLUTE(.);
} > tcm_idram_seg } > tcm_idram_seg
@@ -173,8 +198,13 @@ SECTIONS
_tcm_data_start = ABSOLUTE(.); _tcm_data_start = ABSOLUTE(.);
arrays[tcm_data] arrays[tcm_data]
mapping[tcm_data] mapping[tcm_data]
/* mutable libs begin */
mutable[tcm_data]
/* mutable libs end */
_tcm_data_end = ABSOLUTE(.); _tcm_data_end = ABSOLUTE(.);
} > tcm_idram_seg } > tcm_idram_seg
@@ -190,8 +220,14 @@ SECTIONS
_iram_text_start = ABSOLUTE(.); _iram_text_start = ABSOLUTE(.);
arrays[iram0_text] arrays[iram0_text]
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > sram_low } > sram_low
/* Marks the end of IRAM code segment */ /* Marks the end of IRAM code segment */
@@ -208,8 +244,13 @@ SECTIONS
ALIGNED_SYMBOL(16, _iram_data_start) ALIGNED_SYMBOL(16, _iram_data_start)
arrays[iram0_data] arrays[iram0_data]
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
_iram_data_end = ABSOLUTE(.); _iram_data_end = ABSOLUTE(.);
} > sram_low } > sram_low
@@ -218,8 +259,13 @@ SECTIONS
ALIGNED_SYMBOL(16, _iram_bss_start) ALIGNED_SYMBOL(16, _iram_bss_start)
arrays[iram0_bss] arrays[iram0_bss]
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
ALIGNED_SYMBOL(16, _iram_end) ALIGNED_SYMBOL(16, _iram_end)
@@ -238,8 +284,14 @@ SECTIONS
*(.jcr) *(.jcr)
arrays[dram0_data] arrays[dram0_data]
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end_low = ABSOLUTE(.); _data_end_low = ABSOLUTE(.);
} > sram_low } > sram_low
@@ -249,6 +301,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end_high = ABSOLUTE(.); _data_end_high = ABSOLUTE(.);
} > sram_high } > sram_high
@@ -278,8 +335,14 @@ SECTIONS
_text_start = ABSOLUTE(.); _text_start = ABSOLUTE(.);
arrays[flash_text] arrays[flash_text]
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.linkonce.t.*) *(.gnu.linkonce.t.*)
*(.gnu.warning) *(.gnu.warning)
@@ -360,6 +423,7 @@ SECTIONS
_flash_rodata_start = ABSOLUTE(.); _flash_rodata_start = ABSOLUTE(.);
arrays[flash_rodata] arrays[flash_rodata]
mapping[flash_rodata] mapping[flash_rodata]
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
@@ -396,6 +460,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
. = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA));
} > rodata_seg_low } > rodata_seg_low
@@ -475,7 +544,13 @@ SECTIONS
_rodata_reserved_end = ADDR(.flash.tbss); _rodata_reserved_end = ADDR(.flash.tbss);
arrays[rodata_noload] arrays[rodata_noload]
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > rodata_seg_low } > rodata_seg_low
#if CONFIG_SPIRAM_XIP_FROM_PSRAM #if CONFIG_SPIRAM_XIP_FROM_PSRAM
@@ -495,8 +570,15 @@ SECTIONS
.ext_ram.bss (NOLOAD) : .ext_ram.bss (NOLOAD) :
{ {
_ext_ram_bss_start = ABSOLUTE(.); _ext_ram_bss_start = ABSOLUTE(.);
arrays[extern_ram] arrays[extern_ram]
mapping[extern_ram] mapping[extern_ram]
/* mutable libs begin */
mutable[extern_ram]
/* mutable libs end */
ALIGNED_SYMBOL(4, _ext_ram_bss_end) ALIGNED_SYMBOL(4, _ext_ram_bss_end)
} > ext_ram_seg } > ext_ram_seg
#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY #endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
@@ -525,8 +607,13 @@ SECTIONS
* (See components/esp_system/app.lf). * (See components/esp_system/app.lf).
*/ */
arrays[dram0_bss] arrays[dram0_bss]
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(4, _bss_end_low) ALIGNED_SYMBOL(4, _bss_end_low)
} > sram_low } > sram_low
@@ -540,6 +627,10 @@ SECTIONS
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(4, _bss_end_high) ALIGNED_SYMBOL(4, _bss_end_high)
} > sram_high } > sram_high
@@ -30,6 +30,10 @@ SECTIONS
mapping[rtc_text] mapping[rtc_text]
/* mutable libs begin */
mutable[rtc_text]
/* mutable libs end */
*rtc_wake_stub*.*(.literal .text .literal.* .text.*) *rtc_wake_stub*.*(.literal .text .literal.* .text.*)
HIDDEN(_rtc_code_end = .); HIDDEN(_rtc_code_end = .);
@@ -65,6 +69,10 @@ SECTIONS
mapping[rtc_force_fast] mapping[rtc_force_fast]
/* mutable libs begin */
mutable[rtc_force_fast]
/* mutable libs end */
*(.rtc.force_fast .rtc.force_fast.*) *(.rtc.force_fast .rtc.force_fast.*)
ALIGNED_SYMBOL(4, _rtc_force_fast_end) ALIGNED_SYMBOL(4, _rtc_force_fast_end)
@@ -84,6 +92,10 @@ SECTIONS
mapping[rtc_data] mapping[rtc_data]
/* mutable libs begin */
mutable[rtc_data]
/* mutable libs end */
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*)
_rtc_data_end = ABSOLUTE(.); _rtc_data_end = ABSOLUTE(.);
@@ -99,6 +111,10 @@ SECTIONS
mapping[rtc_bss] mapping[rtc_bss]
/* mutable libs begin */
mutable[rtc_bss]
/* mutable libs end */
_rtc_bss_end = ABSOLUTE(.); _rtc_bss_end = ABSOLUTE(.);
} > rtc_data_location } > rtc_data_location
@@ -213,6 +229,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
/* Padding for possible CPU prefetch + alignment for PMS split lines */ /* Padding for possible CPU prefetch + alignment for PMS split lines */
. += _esp_memprot_prefetch_pad_size; . += _esp_memprot_prefetch_pad_size;
. = ALIGN(_esp_memprot_align_size); . = ALIGN(_esp_memprot_align_size);
@@ -241,6 +262,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > dram0_0_seg } > dram0_0_seg
@@ -267,6 +293,10 @@ SECTIONS
mapping[extern_ram] mapping[extern_ram]
/* mutable libs begin */
mutable[extern_ram]
/* mutable libs end */
ALIGNED_SYMBOL(4, _ext_ram_bss_end) ALIGNED_SYMBOL(4, _ext_ram_bss_end)
} > extern_ram_seg } > extern_ram_seg
#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY #endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
@@ -297,6 +327,10 @@ SECTIONS
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > dram0_0_seg } > dram0_0_seg
@@ -380,6 +414,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */ /* Literals are also RO data. */
@@ -414,6 +453,10 @@ SECTIONS
_rodata_reserved_end = ABSOLUTE(.); _rodata_reserved_end = ABSOLUTE(.);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
.flash.text : .flash.text :
@@ -428,6 +471,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.warning) *(.gnu.warning)
*(.gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
@@ -26,6 +26,10 @@ SECTIONS
mapping[rtc_text] mapping[rtc_text]
/* mutable libs begin */
mutable[rtc_text]
/* mutable libs end */
*rtc_wake_stub*.*(.literal .text .literal.* .text.*) *rtc_wake_stub*.*(.literal .text .literal.* .text.*)
*(.rtc_text_end_test) *(.rtc_text_end_test)
@@ -49,6 +53,10 @@ SECTIONS
mapping[rtc_force_fast] mapping[rtc_force_fast]
/* mutable libs begin */
mutable[rtc_force_fast]
/* mutable libs end */
*(.rtc.force_fast .rtc.force_fast.*) *(.rtc.force_fast .rtc.force_fast.*)
ALIGNED_SYMBOL(4, _rtc_force_fast_end) ALIGNED_SYMBOL(4, _rtc_force_fast_end)
@@ -68,6 +76,10 @@ SECTIONS
mapping[rtc_data] mapping[rtc_data]
/* mutable libs begin */
mutable[rtc_data]
/* mutable libs end */
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*)
_rtc_data_end = ABSOLUTE(.); _rtc_data_end = ABSOLUTE(.);
@@ -83,6 +95,10 @@ SECTIONS
mapping[rtc_bss] mapping[rtc_bss]
/* mutable libs begin */
mutable[rtc_bss]
/* mutable libs end */
_rtc_bss_end = ABSOLUTE(.); _rtc_bss_end = ABSOLUTE(.);
} > rtc_data_location } > rtc_data_location
@@ -197,6 +213,11 @@ SECTIONS
mapping[iram0_text] mapping[iram0_text]
/* mutable libs begin */
mutable[iram0_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
} > iram0_0_seg } > iram0_0_seg
/** /**
@@ -221,6 +242,11 @@ SECTIONS
mapping[dram0_data] mapping[dram0_data]
/* mutable libs begin */
mutable[dram0_data]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_data_end = ABSOLUTE(.); _data_end = ABSOLUTE(.);
} > dram0_0_seg } > dram0_0_seg
@@ -250,6 +276,10 @@ SECTIONS
*/ */
mapping[dram0_bss] mapping[dram0_bss]
/* mutable libs begin */
mutable[dram0_bss]
/* mutable libs end */
ALIGNED_SYMBOL(8, _bss_end) ALIGNED_SYMBOL(8, _bss_end)
} > dram0_0_seg } > dram0_0_seg
@@ -268,6 +298,11 @@ SECTIONS
mapping[flash_text] mapping[flash_text]
/* mutable libs begin */
mutable[flash_text]
FAST_REFLASHING_PADDING;
/* mutable libs end */
*(.stub) *(.stub)
*(.gnu.warning) *(.gnu.warning)
*(.gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
@@ -391,6 +426,11 @@ SECTIONS
KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
_esp_system_init_fn_array_end = ABSOLUTE(.); _esp_system_init_fn_array_end = ABSOLUTE(.);
/* mutable libs begin */
mutable[flash_rodata]
FAST_REFLASHING_PADDING;
/* mutable libs end */
_rodata_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */ /* Literals are also RO data. */
@@ -425,6 +465,10 @@ SECTIONS
_rodata_reserved_end = ABSOLUTE(.); _rodata_reserved_end = ABSOLUTE(.);
mapping[rodata_noload] mapping[rodata_noload]
/* mutable libs begin */
mutable[rodata_noload]
/* mutable libs end */
} > default_rodata_seg } > default_rodata_seg
/** /**
@@ -446,6 +490,10 @@ SECTIONS
mapping[extern_ram] mapping[extern_ram]
/* mutable libs begin */
mutable[extern_ram]
/* mutable libs end */
ALIGNED_SYMBOL(4, _ext_ram_bss_end) ALIGNED_SYMBOL(4, _ext_ram_bss_end)
} > extern_ram_seg } > extern_ram_seg
#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY #endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
@@ -484,6 +532,10 @@ SECTIONS
mapping[iram0_data] mapping[iram0_data]
/* mutable libs begin */
mutable[iram0_data]
/* mutable libs end */
ALIGNED_SYMBOL(4, _iram_data_end) ALIGNED_SYMBOL(4, _iram_data_end)
} > iram0_0_seg } > iram0_0_seg
@@ -493,6 +545,10 @@ SECTIONS
mapping[iram0_bss] mapping[iram0_bss]
/* mutable libs begin */
mutable[iram0_bss]
/* mutable libs end */
_iram_bss_end = ABSOLUTE(.); _iram_bss_end = ABSOLUTE(.);
ALIGNED_SYMBOL(4, _iram_end) ALIGNED_SYMBOL(4, _iram_end)
} > iram0_0_seg } > iram0_0_seg
+20
View File
@@ -94,3 +94,23 @@ ASSERT((ADDR(NEXT_SECTION) == ADDR(PREV_SECTION) + SIZEOF(PREV_SECTION)), \
#else #else
#define SECTION_AFTER_FLASH_RODATA .flash.tdata #define SECTION_AFTER_FLASH_RODATA .flash.tdata
#endif #endif
/*
* FAST_REFLASHING_PADDING
*
* Aligns the current location (.) to CONFIG_ESPTOOLPY_FAST_REFLASHING_PADDING.
* If more than half of the alignment block is already consumed,
* extra padding is applied to skip to the next boundary.
* For example, if the current location (.) is 0x1900 and the padding is 4 KB,
* the location will be moved to 0x3000 instead of 0x2000 because less than
* half of the current 4 KB block remains (0x2000 - 0x1900 < 2 KB).
*/
#if CONFIG_ESPTOOLPY_FAST_REFLASHING
#define FAST_REFLASHING_PADDING \
. = ALIGN((. + ( \
(CONFIG_ESPTOOLPY_FAST_REFLASHING_PADDING - (ALIGN(CONFIG_ESPTOOLPY_FAST_REFLASHING_PADDING) - .)) + \
(CONFIG_ESPTOOLPY_FAST_REFLASHING_PADDING / 2) \
)), CONFIG_ESPTOOLPY_FAST_REFLASHING_PADDING)
#else
#define FAST_REFLASHING_PADDING
#endif
+61
View File
@@ -202,4 +202,65 @@ menu "Serial flasher config"
int int
default ESP_CONSOLE_UART_BAUDRATE if ESP_CONSOLE_UART default ESP_CONSOLE_UART_BAUDRATE if ESP_CONSOLE_UART
default 115200 if !ESP_CONSOLE_UART default 115200 if !ESP_CONSOLE_UART
menu "Fast Reflashing"
config ESPTOOLPY_FAST_REFLASHING
bool "Enable fast reflashing (Experimental)"
depends on IDF_EXPERIMENTAL_FEATURES
select COMPILER_NO_MERGE_CONSTANTS if IDF_TOOLCHAIN_GCC
help
Enabling this option classifies component libraries into two
categories: mutable and immutable. Mutable libraries are
expected to change frequently during development, while
immutable libraries are considered stable. All project
component libraries are treated as mutable; all other libraries
are treated as immutable.
In the generated linker script, input sections from immutable
libraries are placed before those from mutable libraries. This
layout helps localize changes in the output sections of the ELF
file, so that recompilation primarily affects a confined area
associated with the mutable libraries.
This enables the generation of binary images with large
unmodified regions across recompilations, allowing to flash
only the parts that have changed.
To support this, some compiler optimizations, such as constant
merging, are disabled, which helps minimize differences in the
binary image between builds. However, this may increase the
overall image size and flash usage.
Additionally, this option inserts a padding, defined by the
ESPTOOLPY_FAST_REFLASHING_PADDING option, after the input
sections of mutable libraries. This allows further isolate
changes but also increases the size of the binary image and
flash consumption.
choice ESPTOOLPY_FAST_REFLASHING_PADDING_SIZE
prompt "Padding size"
default ESPTOOLPY_FAST_REFLASHING_PADDING_4KB
depends on ESPTOOLPY_FAST_REFLASHING
help
Selects the amount of padding (in kilobytes) to add after input
sections of mutable libraries when fast reflashing is enabled.
config ESPTOOLPY_FAST_REFLASHING_PADDING_2KB
bool "2 KB"
config ESPTOOLPY_FAST_REFLASHING_PADDING_4KB
bool "4 KB"
config ESPTOOLPY_FAST_REFLASHING_PADDING_8KB
bool "8 KB"
endchoice
config ESPTOOLPY_FAST_REFLASHING_PADDING
int
depends on ESPTOOLPY_FAST_REFLASHING
default 2048 if ESPTOOLPY_FAST_REFLASHING_PADDING_2KB
default 4096 if ESPTOOLPY_FAST_REFLASHING_PADDING_4KB
default 8192 if ESPTOOLPY_FAST_REFLASHING_PADDING_8KB
endmenu
endmenu endmenu
+38
View File
@@ -88,6 +88,32 @@ function(__ldgen_get_lib_deps_of_target target out_list_var)
set(${out_list_var} ${out_list} PARENT_SCOPE) set(${out_list_var} ${out_list} PARENT_SCOPE)
endfunction() endfunction()
# __ldgen_get_mutable_libs
#
# Helper function to get the list of library file name generator expressions
# for project components. These libraries are placed by ldgen into a separate
# location in the linker script, allowing the fast reflashing feature.
#
function(__ldgen_get_mutable_libs out_list_var)
set(mutable_libs)
idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
foreach(component_target ${build_component_targets})
__component_get_property(component_source ${component_target} COMPONENT_SOURCE)
__component_get_property(component_lib ${component_target} COMPONENT_LIB)
__component_get_property(component_type ${component_target} COMPONENT_TYPE)
if("${component_type}" STREQUAL "CONFIG_ONLY")
# Configuration only component interface target without a library.
continue()
endif()
if(NOT "${component_source}" STREQUAL "project_components")
# Add only project components as mutable.
continue()
endif()
set(unstable_lib "$<TARGET_LINKER_FILE_NAME:${component_lib}>")
list(APPEND mutable_libs "${unstable_lib}")
endforeach()
set(${out_list_var} ${mutable_libs} PARENT_SCOPE)
endfunction()
# __ldgen_create_target # __ldgen_create_target
# #
@@ -177,6 +203,17 @@ function(__ldgen_create_target exe_target)
message(STATUS "Mapping check enabled in ldgen") message(STATUS "Mapping check enabled in ldgen")
endif() endif()
if(CONFIG_ESPTOOLPY_FAST_REFLASHING)
# Create a file containing a list of mutable libraries used by ldgen
# for fast reflashing.
set(mutable_libs_path "${build_dir}/ldgen_mutable_libraries")
__ldgen_get_mutable_libs(mutable_libs)
list(JOIN mutable_libs "\n" mutable_libs_str)
file(GENERATE OUTPUT "${mutable_libs_path}"
CONTENT "${mutable_libs_str}")
set(mutable_libs_option "--mutable-libraries-file" "${mutable_libs_path}")
endif()
add_custom_command( add_custom_command(
OUTPUT ${output} OUTPUT ${output}
COMMAND ${python} "${idf_path}/tools/ldgen/ldgen.py" COMMAND ${python} "${idf_path}/tools/ldgen/ldgen.py"
@@ -189,6 +226,7 @@ function(__ldgen_create_target exe_target)
--libraries-file "${build_dir}/ldgen_libraries" --libraries-file "${build_dir}/ldgen_libraries"
--objdump "${CMAKE_OBJDUMP}" --objdump "${CMAKE_OBJDUMP}"
${ldgen_check} ${ldgen_check}
${mutable_libs_option}
DEPENDS ${template} ${ldgen_fragment_files} ${ldgen_deps} ${SDKCONFIG} DEPENDS ${template} ${ldgen_fragment_files} ${ldgen_deps} ${SDKCONFIG}
VERBATIM VERBATIM
) )
+44 -48
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# #
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
import argparse import argparse
@@ -23,7 +23,7 @@ from pyparsing import ParseFatalException
def _update_environment(args): def _update_environment(args):
env = [(name, value) for (name,value) in (e.split('=',1) for e in args.env)] env = [(name, value) for (name, value) in (e.split('=', 1) for e in args.env)]
for name, value in env: for name, value in env:
value = ' '.join(value.split()) value = ' '.join(value.split())
os.environ[name] = value os.environ[name] = value
@@ -34,76 +34,69 @@ def _update_environment(args):
def main(): def main():
argparser = argparse.ArgumentParser(description='ESP-IDF linker script generator') argparser = argparse.ArgumentParser(description='ESP-IDF linker script generator')
argparser.add_argument( argparser.add_argument('--input', '-i', help='Linker template file', type=argparse.FileType('r'))
'--input', '-i',
help='Linker template file',
type=argparse.FileType('r'))
fragments_group = argparser.add_mutually_exclusive_group() fragments_group = argparser.add_mutually_exclusive_group()
fragments_group.add_argument( fragments_group.add_argument(
'--fragments', '-f', '--fragments', '-f', type=argparse.FileType('r'), help='Input fragment files', nargs='+'
type=argparse.FileType('r'),
help='Input fragment files',
nargs='+'
) )
fragments_group.add_argument( fragments_group.add_argument(
'--fragments-list', '--fragments-list', help='Input fragment files as a semicolon-separated list', type=str
help='Input fragment files as a semicolon-separated list',
type=str
) )
argparser.add_argument( argparser.add_argument(
'--libraries-file', '--libraries-file', type=argparse.FileType('r'), help='File that contains the list of libraries in the build'
)
argparser.add_argument(
'--mutable-libraries-file',
type=argparse.FileType('r'), type=argparse.FileType('r'),
help='File that contains the list of libraries in the build') help='File that contains the list of mutable libraries in the build',
)
argparser.add_argument('--output', '-o', help='Output linker script', type=str)
argparser.add_argument('--config', '-c', help='Project configuration')
argparser.add_argument('--kconfig', '-k', help='IDF Kconfig file')
argparser.add_argument( argparser.add_argument(
'--output', '-o', '--check-mapping', help='Perform a check if a mapping (archive, obj, symbol) exists', action='store_true'
help='Output linker script',
type=str)
argparser.add_argument(
'--config', '-c',
help='Project configuration')
argparser.add_argument(
'--kconfig', '-k',
help='IDF Kconfig file')
argparser.add_argument(
'--check-mapping',
help='Perform a check if a mapping (archive, obj, symbol) exists',
action='store_true'
) )
argparser.add_argument( argparser.add_argument(
'--check-mapping-exceptions', '--check-mapping-exceptions', help='Mappings exempted from check', type=argparse.FileType('r')
help='Mappings exempted from check',
type=argparse.FileType('r')
) )
argparser.add_argument( argparser.add_argument(
'--env', '-e', '--env',
action='append', default=[], '-e',
help='Environment to set when evaluating the config file', metavar='NAME=VAL') action='append',
default=[],
argparser.add_argument('--env-file', type=argparse.FileType('r'), help='Environment to set when evaluating the config file',
help='Optional file to load environment variables from. Contents ' metavar='NAME=VAL',
'should be a JSON object where each key/value pair is a variable.') )
argparser.add_argument( argparser.add_argument(
'--objdump', '--env-file',
help='Path to toolchain objdump') type=argparse.FileType('r'),
help='Optional file to load environment variables from. Contents '
'should be a JSON object where each key/value pair is a variable.',
)
argparser.add_argument('--objdump', help='Path to toolchain objdump')
argparser.add_argument('--debug', '-d', help='Print debugging information.', action='store_true')
args = argparser.parse_args() args = argparser.parse_args()
input_file = args.input input_file = args.input
libraries_file = args.libraries_file libraries_file = args.libraries_file
mutable_libraries_file = args.mutable_libraries_file or []
config_file = args.config config_file = args.config
output_path = args.output output_path = args.output
kconfig_file = args.kconfig kconfig_file = args.kconfig
@@ -132,7 +125,8 @@ def main():
dump.name = library dump.name = library
sections_infos.add_sections_info(dump) sections_infos.add_sections_info(dump)
generation_model = Generation(check_mapping, check_mapping_exceptions) mutable_libs = [lib.strip() for lib in mutable_libraries_file]
generation_model = Generation(check_mapping, check_mapping_exceptions, mutable_libs, args.debug)
_update_environment(args) # assign args.env and args.env_file to os.environ _update_environment(args) # assign args.env and args.env_file to os.environ
@@ -145,7 +139,7 @@ def main():
# ParseException is raised on incorrect grammar # ParseException is raised on incorrect grammar
# ParseFatalException is raised on correct grammar, but inconsistent contents (ex. duplicate # ParseFatalException is raised on correct grammar, but inconsistent contents (ex. duplicate
# keys, key unsupported by fragment, unexpected number of values, etc.) # keys, key unsupported by fragment, unexpected number of values, etc.)
raise LdGenFailure('failed to parse %s\n%s' % (fragment_file, str(e))) raise LdGenFailure(f'failed to parse {fragment_file}\n{e}')
generation_model.add_fragments_from_file(fragment_file) generation_model.add_fragments_from_file(fragment_file)
non_contiguous_sram = sdkconfig.evaluate_expression('SOC_MEM_NON_CONTIGUOUS_SRAM') non_contiguous_sram = sdkconfig.evaluate_expression('SOC_MEM_NON_CONTIGUOUS_SRAM')
@@ -165,10 +159,12 @@ def main():
if exc.errno != errno.EEXIST: if exc.errno != errno.EEXIST:
raise raise
with open(output_path, 'w', encoding='utf-8') as f: # only create output file after generation has succeeded with open(
output_path, 'w', encoding='utf-8'
) as f: # only create output file after generation has succeeded
f.write(output.read()) f.write(output.read())
except LdGenFailure as e: except LdGenFailure as e:
print('linker script generation failed for %s\nERROR: %s' % (input_file.name, e)) print(f'linker script generation failed for {input_file.name}\nERROR: {e}')
sys.exit(1) sys.exit(1)
+150 -55
View File
@@ -41,7 +41,7 @@ class Placement:
for details). for details).
""" """
def __init__(self, node, sections, target, flags, explicit, force=False, dryrun=False): def __init__(self, node, sections, target, flags, explicit, force=False, dryrun=False, mutable=False):
self.node = node self.node = node
self.sections = sections self.sections = sections
self.target = target self.target = target
@@ -57,6 +57,10 @@ class Placement:
# fragment entry. # fragment entry.
self.explicit = explicit self.explicit = explicit
# This placement is designated as mutable and should be assigned to a
# mutable target.
self.mutable = mutable
# Find basis placement. # Find basis placement.
parent = node.parent parent = node.parent
candidate = None candidate = None
@@ -83,11 +87,19 @@ class Placement:
# #
# Placement can also be a basis if it has flags # Placement can also be a basis if it has flags
# (self.flags) or its basis has flags (self.basis.flags) # (self.flags) or its basis has flags (self.basis.flags)
significant = (not self.basis or #
self.target != self.basis.target or # The mutable placement mark is used to place the placement within a
(self.flags and not self.basis.flags) or # designated area (MutableMarker) in the linker script. If the basis is
(not self.flags and self.basis.flags) or # also mutable, the placement is deemed insignificant to prevent adding
self.force) # unnecessary EXCLUDE_FILE and placement rules to the linker script.
significant = (
not self.basis
or self.target != self.basis.target
or (self.flags and not self.basis.flags)
or (not self.flags and self.basis.flags)
or (self.mutable and not self.basis.mutable)
or self.force
)
if significant and not self.explicit and not self.sections: if significant and not self.explicit and not self.sections:
# The placement is significant, but it is an intermediate placement # The placement is significant, but it is an intermediate placement
@@ -112,6 +124,15 @@ class Placement:
def add_subplacement(self, subplacement): def add_subplacement(self, subplacement):
self.subplacements.add(subplacement) self.subplacements.add(subplacement)
def __str__(self):
sections_str = ', '.join(self.sections)
basis_str = self.basis.node.name if self.basis else 'NONE'
return (
f'({sections_str} -> {self.target}), basis: {basis_str}, '
f'force: {self.force}, stable: {self.stable}, '
f'explicit: {self.explicit}, flags: {self.flags}'
)
class EntityNode: class EntityNode:
""" """
@@ -155,7 +176,7 @@ class EntityNode:
assert name and name != Entity.ALL assert name and name != Entity.ALL
child = [c for c in self.children if c.name == name] child = [c for c in self.children if c.name == name]
assert (len(child) <= 1) assert len(child) <= 1
if not child: if not child:
child = self.child_t(self, name) child = self.child_t(self, name)
@@ -169,7 +190,7 @@ class EntityNode:
commands = collections.defaultdict(list) commands = collections.defaultdict(list)
def process_commands(cmds): def process_commands(cmds):
for (target, commands_list) in cmds.items(): for target, commands_list in cmds.items():
commands[target].extend(commands_list) commands[target].extend(commands_list)
# Process the commands generated from this node # Process the commands generated from this node
@@ -196,6 +217,7 @@ class EntityNode:
keep = False keep = False
sort = None sort = None
surround_type = [] surround_type = []
mutable = placement.mutable
placement_flags = placement.flags if placement.flags is not None else [] placement_flags = placement.flags if placement.flags is not None else []
@@ -212,52 +234,70 @@ class EntityNode:
for flag in surround_type: for flag in surround_type:
if flag.pre: if flag.pre:
if isinstance(flag, Surround): if isinstance(flag, Surround):
commands[placement.target].append(SymbolAtAddress(f'_{flag.symbol}_start', tied)) commands[placement.target].append(
SymbolAtAddress(f'_{flag.symbol}_start', tied, mutable=mutable)
)
else: # ALIGN else: # ALIGN
commands[placement.target].append(AlignAtAddress(flag.alignment, tied)) commands[placement.target].append(AlignAtAddress(flag.alignment, tied, mutable=mutable))
# This is for expanded object node and symbol node placements without checking for # This is for expanded object node and symbol node placements without checking for
# the type. # the type.
placement_sections = frozenset(placement.sections) placement_sections = frozenset(placement.sections)
command_sections = sections if sections == placement_sections else placement_sections command_sections = sections if sections == placement_sections else placement_sections
command = InputSectionDesc(placement.node.entity, command_sections, command = InputSectionDesc(
[e.node.entity for e in placement.exclusions], keep, sort, tied) placement.node.entity,
command_sections,
[e.node.entity for e in placement.exclusions],
keep,
sort,
tied,
mutable=mutable,
)
commands[placement.target].append(command) commands[placement.target].append(command)
# Generate commands for intermediate, non-explicit exclusion placements here, # Generate commands for intermediate, non-explicit exclusion placements here,
# so that they can be enclosed by flags that affect the parent placement. # so that they can be enclosed by flags that affect the parent placement.
for subplacement in placement.subplacements: for subplacement in placement.subplacements:
if not subplacement.flags and not subplacement.explicit: if not subplacement.flags and not subplacement.explicit:
command = InputSectionDesc(subplacement.node.entity, subplacement.sections, command = InputSectionDesc(
[e.node.entity for e in subplacement.exclusions], keep, sort, tied) subplacement.node.entity,
subplacement.sections,
[e.node.entity for e in subplacement.exclusions],
keep,
sort,
tied,
mutable=mutable,
)
commands[placement.target].append(command) commands[placement.target].append(command)
for flag in surround_type: for flag in surround_type:
if flag.post: if flag.post:
if isinstance(flag, Surround): if isinstance(flag, Surround):
commands[placement.target].append(SymbolAtAddress(f'_{flag.symbol}_end', tied)) commands[placement.target].append(
SymbolAtAddress(f'_{flag.symbol}_end', tied, mutable=mutable)
)
else: # ALIGN else: # ALIGN
commands[placement.target].append(AlignAtAddress(flag.alignment, tied)) commands[placement.target].append(AlignAtAddress(flag.alignment, tied, mutable=mutable))
return commands return commands
def self_placement(self, sections, target, flags, explicit=True, force=False): def self_placement(self, sections, target, flags, explicit=True, force=False, mutable=False):
placement = Placement(self, sections, target, flags, explicit, force) placement = Placement(self, sections, target, flags, explicit, force=force, mutable=mutable)
self.placements[sections] = placement self.placements[sections] = placement
return placement return placement
def child_placement(self, entity, sections, target, flags, sections_db): def child_placement(self, entity, sections, target, flags, mutable, sections_db):
child = self.add_child(entity) child = self.add_child(entity)
child.insert(entity, sections, target, flags, sections_db) child.insert(entity, sections, target, flags, mutable, sections_db)
def insert(self, entity, sections, target, flags, sections_db): def insert(self, entity, sections, target, flags, mutable, sections_db):
if self.entity.specificity == entity.specificity: if self.entity.specificity == entity.specificity:
# Since specificities match, create the placement in this node. # Since specificities match, create the placement in this node.
self.self_placement(sections, target, flags) self.self_placement(sections, target, flags, mutable=mutable)
else: else:
# If not, create a child node and try to create the placement there. # If not, create a child node and try to create the placement there.
self.child_placement(entity, sections, target, flags, sections_db) self.child_placement(entity, sections, target, flags, mutable, sections_db)
def get_output_sections(self): def get_output_sections(self):
return sorted(self.placements.keys(), key=lambda x: sorted(x)) # pylint: disable=W0108 return sorted(self.placements.keys(), key=lambda x: sorted(x)) # pylint: disable=W0108
@@ -298,9 +338,9 @@ class ObjectNode(EntityNode):
self.entity = Entity(self.parent.name, self.name) self.entity = Entity(self.parent.name, self.name)
self.subplacements = list() self.subplacements = list()
def child_placement(self, entity, sections, target, flags, sections_db): def child_placement(self, entity, sections, target, flags, mutable, sections_db):
child = self.add_child(entity) child = self.add_child(entity)
sym_placement = Placement(child, sections, target, flags, True, dryrun=True) sym_placement = Placement(child, sections, target, flags, True, dryrun=True, mutable=mutable)
# The basis placement for sym_placement can either be # The basis placement for sym_placement can either be
# an existing placement on this node, or nonexistent. # an existing placement on this node, or nonexistent.
@@ -319,7 +359,7 @@ class ObjectNode(EntityNode):
if obj_sections: if obj_sections:
symbol = entity.symbol symbol = entity.symbol
remove_sections = [s.replace('.*', '.%s' % symbol) for s in sections if '.*' in s] remove_sections = [s.replace('.*', f'.{symbol}') for s in sections if '.*' in s]
filtered_sections = [s for s in obj_sections if s not in remove_sections] filtered_sections = [s for s in obj_sections if s not in remove_sections]
if set(filtered_sections) != set(obj_sections): if set(filtered_sections) != set(obj_sections):
@@ -331,7 +371,9 @@ class ObjectNode(EntityNode):
obj_placement = self.placements[sections] obj_placement = self.placements[sections]
except KeyError: except KeyError:
# Create intermediate placement. # Create intermediate placement.
obj_placement = self.self_placement(sections, sym_placement.basis.target, None, False) obj_placement = self.self_placement(
sections, sym_placement.basis.target, None, False, mutable=mutable
)
if obj_placement.basis.flags: if obj_placement.basis.flags:
subplace = True subplace = True
@@ -383,12 +425,13 @@ class Generation:
""" """
# Processed mapping, scheme and section entries # Processed mapping, scheme and section entries
EntityMapping = namedtuple('EntityMapping', 'entity sections_group target flags') EntityMapping = namedtuple('EntityMapping', 'entity sections_group target flags mutable')
def __init__(self, check_mappings=False, check_mapping_exceptions=None): def __init__(self, check_mappings=False, check_mapping_exceptions=None, mutable_libs=None, debug=False):
self.schemes = {} self.schemes = {}
self.placements = {} self.placements = {}
self.mappings = {} self.mappings = {}
self.debug = debug
self.check_mappings = check_mappings self.check_mappings = check_mappings
@@ -397,6 +440,11 @@ class Generation:
else: else:
self.check_mapping_exceptions = [] self.check_mapping_exceptions = []
if mutable_libs is None:
self.mutable_libs = []
else:
self.mutable_libs = mutable_libs
def _prepare_scheme_dictionary(self): def _prepare_scheme_dictionary(self):
scheme_dictionary = collections.defaultdict(dict) scheme_dictionary = collections.defaultdict(dict)
@@ -404,7 +452,7 @@ class Generation:
for scheme in self.schemes.values(): for scheme in self.schemes.values():
sections_bucket = collections.defaultdict(list) sections_bucket = collections.defaultdict(list)
for (sections_name, target_name) in scheme.entries: for sections_name, target_name in scheme.entries:
# Get the sections under the bucket 'target_name'. If this bucket does not exist # Get the sections under the bucket 'target_name'. If this bucket does not exist
# is created automatically # is created automatically
sections_in_bucket = sections_bucket[target_name] sections_in_bucket = sections_bucket[target_name]
@@ -420,7 +468,7 @@ class Generation:
scheme_dictionary[scheme.name] = sections_bucket scheme_dictionary[scheme.name] = sections_bucket
# Search for and raise exception on first instance of sections mapped to multiple targets # Search for and raise exception on first instance of sections mapped to multiple targets
for (scheme_name, sections_bucket) in scheme_dictionary.items(): for scheme_name, sections_bucket in scheme_dictionary.items():
for sections_a, sections_b in itertools.combinations(sections_bucket.values(), 2): for sections_a, sections_b in itertools.combinations(sections_bucket.values(), 2):
set_a = set() set_a = set()
set_b = set() set_b = set()
@@ -442,26 +490,59 @@ class Generation:
return scheme_dictionary return scheme_dictionary
def _get_section_strs(self, section):
s_list = [Sections.get_section_data_from_entry(s) for s in section.entries]
return frozenset([item for sublist in s_list for item in sublist])
def _prepare_mutable_entity_mappings(self, entity_mappings, scheme_dictionary, entities):
# Go through all mutable libraries, if any, and add entity mapping for
# each "default" section set for which the entity mapping does not yet
# exist. This adds mapping for every mutable library as if specified in
# the mapping fragment. All newly added or existing entity mappings
# related to mutable libraries are marked as mutable. This flag is used
# when the placement for it is created in the entity tree, ensuring the
# placement is forced to be emitted in the linker script and not
# considered non-significant.
for archive in self.mutable_libs:
entity = Entity(archive, '*')
for target, sections in scheme_dictionary['default'].items():
for section in sections:
sections_str = self._get_section_strs(section)
key = (entity, sections_str)
if entity_mappings.get(key):
# Mutable library already has entity mapping.
continue
entity_mappings[key] = Generation.EntityMapping(entity, sections_str, target, [], True)
for key, mapping in entity_mappings.items():
(entity, sections, target, flags, mutable) = mapping
if entity.archive not in self.mutable_libs or mutable:
# The entity either does not belong to a mutable library or is
# an archive entity that has already been marked as mutable.
continue
# Set entity as mutable.
entity_mappings[key] = Generation.EntityMapping(entity, sections, target, flags, True)
def _prepare_entity_mappings(self, scheme_dictionary, entities): def _prepare_entity_mappings(self, scheme_dictionary, entities):
# Prepare entity mappings processed from mapping fragment entries. # Prepare entity mappings processed from mapping fragment entries.
def get_section_strs(section):
s_list = [Sections.get_section_data_from_entry(s) for s in section.entries]
return frozenset([item for sublist in s_list for item in sublist])
entity_mappings = dict() entity_mappings = dict()
for mapping in self.mappings.values(): for mapping in self.mappings.values():
archive = mapping.archive archive = mapping.archive
for (obj, symbol, scheme_name) in mapping.entries: for obj, symbol, scheme_name in mapping.entries:
entity = Entity(archive, obj, symbol) entity = Entity(archive, obj, symbol)
# Check the entity exists # Check the entity exists
if (self.check_mappings if (
and entity.specificity.value > Entity.Specificity.ARCHIVE.value self.check_mappings
and mapping.name not in self.check_mapping_exceptions): and entity.specificity.value > Entity.Specificity.ARCHIVE.value
and mapping.name not in self.check_mapping_exceptions
):
if not entities.check_exists(entity): if not entities.check_exists(entity):
message = "'%s' not found" % str(entity) message = f"'{entity}' not found"
raise GenerationException(message, mapping) raise GenerationException(message, mapping)
if (obj, symbol, scheme_name) in mapping.flags.keys(): if (obj, symbol, scheme_name) in mapping.flags.keys():
@@ -469,16 +550,16 @@ class Generation:
# Check if all section->target defined in the current # Check if all section->target defined in the current
# scheme. # scheme.
for flag in flags: for flag in flags:
if (flag.target not in scheme_dictionary[scheme_name].keys() if flag.target not in scheme_dictionary[scheme_name].keys() or flag.section not in [
or flag.section not in _s.name for _s in scheme_dictionary[scheme_name][flag.target]
[_s.name for _s in scheme_dictionary[scheme_name][flag.target]]): ]:
message = "%s->%s not defined in scheme '%s'" % (flag.section, flag.target, scheme_name) message = f"{flag.section}->{flag.target} not defined in scheme '{scheme_name}'"
raise GenerationException(message, mapping) raise GenerationException(message, mapping)
else: else:
flags = None flags = None
# Create placement for each 'section -> target' in the scheme. # Create placement for each 'section -> target' in the scheme.
for (target, sections) in scheme_dictionary[scheme_name].items(): for target, sections in scheme_dictionary[scheme_name].items():
for section in sections: for section in sections:
# Find the applicable flags # Find the applicable flags
_flags = [] _flags = []
@@ -488,7 +569,7 @@ class Generation:
if (flag.section, flag.target) == (section.name, target): if (flag.section, flag.target) == (section.name, target):
_flags.extend(flag.flags) _flags.extend(flag.flags)
sections_str = get_section_strs(section) sections_str = self._get_section_strs(section)
key = (entity, sections_str) key = (entity, sections_str)
@@ -498,7 +579,7 @@ class Generation:
existing = None existing = None
if not existing: if not existing:
entity_mappings[key] = Generation.EntityMapping(entity, sections_str, target, _flags) entity_mappings[key] = Generation.EntityMapping(entity, sections_str, target, _flags, False)
else: else:
# Check for conflicts. # Check for conflicts.
if target != existing.target: if target != existing.target:
@@ -509,31 +590,46 @@ class Generation:
if _flags or existing.flags: if _flags or existing.flags:
if (_flags and not existing.flags) or (not _flags and existing.flags): if (_flags and not existing.flags) or (not _flags and existing.flags):
_flags.extend(existing.flags) _flags.extend(existing.flags)
entity_mappings[key] = Generation.EntityMapping(entity, entity_mappings[key] = Generation.EntityMapping(
sections_str, entity, sections_str, target, _flags, False
target, _flags) )
elif _flags == existing.flags: elif _flags == existing.flags:
pass pass
else: else:
raise GenerationException('Conflicting flags specified.', mapping) raise GenerationException('Conflicting flags specified.', mapping)
# Add new mappings for mutable libraries and modify existing ones if
# they pertain to them.
self._prepare_mutable_entity_mappings(entity_mappings, scheme_dictionary, entities)
# Sort the mappings by specificity, so as to simplify # Sort the mappings by specificity, so as to simplify
# insertion logic. # insertion logic.
res = list(entity_mappings.values()) res = list(entity_mappings.values())
res.sort(key=lambda m: m.entity) res.sort(key=lambda m: m.entity)
return res return res
def _dump_entity_tree(self, node, indent=''):
print(f'{indent}-> {node.name}')
for placement in node.placements.values():
print(f'{indent} {placement}')
print()
for child in node.children:
self._dump_entity_tree(child, ' ' * 8 + indent)
def generate(self, entities, non_contiguous_sram): def generate(self, entities, non_contiguous_sram):
scheme_dictionary = self._prepare_scheme_dictionary() scheme_dictionary = self._prepare_scheme_dictionary()
entity_mappings = self._prepare_entity_mappings(scheme_dictionary, entities) entity_mappings = self._prepare_entity_mappings(scheme_dictionary, entities)
root_node = RootNode() root_node = RootNode()
for mapping in entity_mappings: for mapping in entity_mappings:
(entity, sections, target, flags) = mapping (entity, sections, target, flags, mutable) = mapping
try: try:
root_node.insert(entity, sections, target, flags, entities) root_node.insert(entity, sections, target, flags, mutable, entities)
except ValueError as e: except ValueError as e:
raise GenerationException(str(e)) raise GenerationException(str(e))
if self.debug:
self._dump_entity_tree(root_node)
# Traverse the tree, creating the placements # Traverse the tree, creating the placements
commands = root_node.get_output_commands(non_contiguous_sram) commands = root_node.get_output_commands(non_contiguous_sram)
@@ -552,8 +648,7 @@ class Generation:
if fragment.name in dict_to_append_to: if fragment.name in dict_to_append_to:
stored = dict_to_append_to[fragment.name].path stored = dict_to_append_to[fragment.name].path
new = fragment.path new = fragment.path
message = "Duplicate definition of fragment '%s' found in %s and %s." % ( message = f"Duplicate definition of fragment '{fragment.name}' found in {stored} and {new}."
fragment.name, stored, new)
raise GenerationException(message) raise GenerationException(message)
dict_to_append_to[fragment.name] = fragment dict_to_append_to[fragment.name] = fragment
@@ -573,6 +668,6 @@ class GenerationException(LdGenFailure):
def __str__(self): def __str__(self):
if self.fragment: if self.fragment:
return "%s\nIn fragment '%s' defined in '%s'." % (self.message, self.fragment.name, self.fragment.path) return f"{self.message}\nIn fragment '{self.fragment.name}' defined in '{self.fragment.path}'."
else: else:
return self.message return self.message
+9 -3
View File
@@ -24,6 +24,7 @@ class LinkerScript:
MappingMarker = collections.namedtuple('MappingMarker', 'target indent rules') MappingMarker = collections.namedtuple('MappingMarker', 'target indent rules')
ArraysMarker = collections.namedtuple('ArraysMarker', 'target indent rules') ArraysMarker = collections.namedtuple('ArraysMarker', 'target indent rules')
MutableMarker = collections.namedtuple('MutableMarker', 'target indent rules')
def __init__(self, template_file): def __init__(self, template_file):
self.members = [] self.members = []
@@ -37,16 +38,19 @@ class LinkerScript:
target = Fragment.IDENTIFIER target = Fragment.IDENTIFIER
pattern_mapping = White(' \t') + Suppress('mapping') + Suppress('[') + target + Suppress(']') pattern_mapping = White(' \t') + Suppress('mapping') + Suppress('[') + target + Suppress(']')
pattern_arrays = White(' \t') + Suppress('arrays') + Suppress('[') + target + Suppress(']') pattern_arrays = White(' \t') + Suppress('arrays') + Suppress('[') + target + Suppress(']')
pattern_mutable = White(' \t') + Suppress('mutable') + Suppress('[') + target + Suppress(']')
# Find the markers in the template file line by line. If line does not match marker grammar, # 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. # set it as a literal to be copied as is to the output file.
for line in lines: for line in lines:
parsed = False parsed = False
for pattern in (pattern_arrays, pattern_mapping): for pattern in (pattern_arrays, pattern_mapping, pattern_mutable):
try: try:
indent, target = pattern.parse_string(line) indent, target = pattern.parse_string(line)
if pattern is pattern_arrays: if pattern is pattern_arrays:
marker = LinkerScript.ArraysMarker(target, indent, []) marker = LinkerScript.ArraysMarker(target, indent, [])
elif pattern is pattern_mutable:
marker = LinkerScript.MutableMarker(target, indent, [])
else: else:
marker = LinkerScript.MappingMarker(target, indent, []) marker = LinkerScript.MappingMarker(target, indent, [])
self.members.append(marker) self.members.append(marker)
@@ -65,8 +69,10 @@ class LinkerScript:
if isinstance(member, self.ArraysMarker): if isinstance(member, self.ArraysMarker):
rules = [x for x in mapping_rules[target] if x.tied] rules = [x for x in mapping_rules[target] if x.tied]
elif isinstance(member, self.MutableMarker):
rules = [x for x in mapping_rules[target] if x.mutable and not x.tied]
else: else:
rules = [x for x in mapping_rules[target] if not x.tied] rules = [x for x in mapping_rules[target] if not x.tied and not x.mutable]
member.rules.extend(rules) member.rules.extend(rules)
except KeyError: except KeyError:
message = GenerationException.UNDEFINED_REFERENCE + " to target '" + target + "'." message = GenerationException.UNDEFINED_REFERENCE + " to target '" + target + "'."
@@ -78,7 +84,7 @@ class LinkerScript:
# Add information that this is a generated file. # Add information that this is a generated file.
output_file.write('/* Automatically generated file; DO NOT EDIT */\n') output_file.write('/* Automatically generated file; DO NOT EDIT */\n')
output_file.write('/* Espressif IoT Development Framework Linker Script */\n') output_file.write('/* Espressif IoT Development Framework Linker Script */\n')
output_file.write('/* Generated from: %s */\n' % self.file) output_file.write(f'/* Generated from: {self.file} */\n')
output_file.write('\n') output_file.write('\n')
# Do the text replacement # Do the text replacement
+42 -36
View File
@@ -1,5 +1,5 @@
# #
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
from .entity import Entity from .entity import Entity
@@ -19,16 +19,16 @@ class AlignAtAddress:
command to be emitted. command to be emitted.
""" """
def __init__(self, alignment, tied=False): def __init__(self, alignment, tied=False, mutable=False):
self.alignment = alignment self.alignment = alignment
self.tied = tied self.tied = tied
self.mutable = mutable
def __str__(self): def __str__(self):
return ('. = ALIGN(%d);' % self.alignment) return f'. = ALIGN({self.alignment});'
def __eq__(self, other): def __eq__(self, other):
return (isinstance(other, AlignAtAddress) and return isinstance(other, AlignAtAddress) and self.alignment == other.alignment
self.alignment == other.alignment)
class SymbolAtAddress: class SymbolAtAddress:
@@ -43,16 +43,16 @@ class SymbolAtAddress:
an InputSectionDesc. an InputSectionDesc.
""" """
def __init__(self, symbol, tied=False): def __init__(self, symbol, tied=False, mutable=False):
self.symbol = symbol self.symbol = symbol
self.tied = tied self.tied = tied
self.mutable = mutable
def __str__(self): def __str__(self):
return ('%s = ABSOLUTE(.);' % self.symbol) return f'{self.symbol} = ABSOLUTE(.);'
def __eq__(self, other): def __eq__(self, other):
return (isinstance(other, SymbolAtAddress) and return isinstance(other, SymbolAtAddress) and self.symbol == other.symbol
self.symbol == other.symbol)
class InputSectionDesc: class InputSectionDesc:
@@ -65,7 +65,7 @@ class InputSectionDesc:
the emitted input section description. the emitted input section description.
""" """
def __init__(self, entity, sections, exclusions=None, keep=False, sort=None, tied=False): def __init__(self, entity, sections, exclusions=None, keep=False, sort=None, tied=False, mutable=False):
assert entity.specificity != Entity.Specificity.SYMBOL assert entity.specificity != Entity.Specificity.SYMBOL
self.entity = entity self.entity = entity
@@ -74,8 +74,11 @@ class InputSectionDesc:
self.exclusions = set() self.exclusions = set()
if exclusions: if exclusions:
assert not [e for e in exclusions if e.specificity == Entity.Specificity.SYMBOL or assert not [
e.specificity == Entity.Specificity.NONE] e
for e in exclusions
if e.specificity == Entity.Specificity.SYMBOL or e.specificity == Entity.Specificity.NONE
]
self.exclusions = set(exclusions) self.exclusions = set(exclusions)
else: else:
self.exclusions = set() self.exclusions = set()
@@ -83,6 +86,7 @@ class InputSectionDesc:
self.keep = keep self.keep = keep
self.sort = sort self.sort = sort
self.tied = tied self.tied = tied
self.mutable = mutable
def __str__(self): def __str__(self):
sections_string = '' sections_string = ''
@@ -93,65 +97,67 @@ class InputSectionDesc:
for exc in sorted(self.exclusions): for exc in sorted(self.exclusions):
if exc.specificity == Entity.Specificity.ARCHIVE: if exc.specificity == Entity.Specificity.ARCHIVE:
exc_string = '*%s' % (exc.archive) exc_string = f'*{exc.archive}'
else: else:
exc_string = '*%s:%s.*' % (exc.archive, exc.obj) exc_string = f'*{exc.archive}:{exc.obj}.*'
exclusion_strings.append(exc_string) exclusion_strings.append(exc_string)
section_strings = [] section_strings = []
if exclusion_strings: if exclusion_strings:
exclusion_string = 'EXCLUDE_FILE(%s)' % ' '.join(exclusion_strings) exclusion_string = 'EXCLUDE_FILE({})'.format(' '.join(exclusion_strings))
for section in sorted(self.sections): for section in sorted(self.sections):
section_strings.append('%s %s' % (exclusion_string, section)) section_strings.append(f'{exclusion_string} {section}')
else: else:
for section in sorted(self.sections): for section in sorted(self.sections):
section_strings.append(section) section_strings.append(section)
if self.sort: if self.sort:
if self.sort == (None, None): if self.sort == (None, None):
pattern = 'SORT(%s)' pattern = 'SORT({})'
elif self.sort == ('name', None): elif self.sort == ('name', None):
pattern = 'SORT_BY_NAME(%s)' pattern = 'SORT_BY_NAME({})'
elif self.sort == ('alignment', None): elif self.sort == ('alignment', None):
pattern = 'SORT_BY_ALIGNMENT(%s)' pattern = 'SORT_BY_ALIGNMENT({})'
elif self.sort == ('init_priority', None): elif self.sort == ('init_priority', None):
pattern = 'SORT_BY_INIT_PRIORITY(%s)' pattern = 'SORT_BY_INIT_PRIORITY({})'
elif self.sort == ('name', 'alignment'): elif self.sort == ('name', 'alignment'):
pattern = 'SORT_BY_NAME(SORT_BY_ALIGNMENT(%s))' pattern = 'SORT_BY_NAME(SORT_BY_ALIGNMENT({}))'
elif self.sort == ('alignment', 'name'): elif self.sort == ('alignment', 'name'):
pattern = 'SORT_BY_ALIGNMENT(SORT_BY_NAME(%s))' pattern = 'SORT_BY_ALIGNMENT(SORT_BY_NAME({}))'
elif self.sort == ('name', 'name'): elif self.sort == ('name', 'name'):
pattern = 'SORT_BY_NAME(SORT_BY_NAME(%s))' pattern = 'SORT_BY_NAME(SORT_BY_NAME({}))'
elif self.sort == ('alignment', 'alignment'): elif self.sort == ('alignment', 'alignment'):
pattern = 'SORT_BY_ALIGNMENT(SORT_BY_ALIGNMENT(%s))' pattern = 'SORT_BY_ALIGNMENT(SORT_BY_ALIGNMENT({}))'
else: else:
raise Exception('Invalid sort arguments') raise Exception('Invalid sort arguments')
section_strings = [(pattern % s) for s in section_strings] section_strings = [pattern.format(s) for s in section_strings]
sections_string = '(%s)' % ' '.join(section_strings) sections_string = '({})'.format(' '.join(section_strings))
if self.entity.specificity == Entity.Specificity.NONE: if self.entity.specificity == Entity.Specificity.NONE:
entry = '*%s' % (sections_string) entry = f'*{sections_string}'
elif self.entity.specificity == Entity.Specificity.ARCHIVE: elif self.entity.specificity == Entity.Specificity.ARCHIVE:
entry = '*%s:%s' % (self.entity.archive, sections_string) entry = f'*{self.entity.archive}:{sections_string}'
else: else:
entry = '*%s:%s.*%s' % (self.entity.archive, self.entity.obj, sections_string) entry = f'*{self.entity.archive}:{self.entity.obj}.*{sections_string}'
if self.keep: if self.keep:
res = 'KEEP(%s)' % entry res = f'KEEP({entry})'
else: else:
res = entry res = entry
return res return res
def __eq__(self, other): def __eq__(self, other):
return (isinstance(other, InputSectionDesc) and return (
self.entity == other.entity and isinstance(other, InputSectionDesc)
self.sections == other.sections and and self.entity == other.entity
self.exclusions == other.exclusions and and self.sections == other.sections
self.keep == other.keep and and self.exclusions == other.exclusions
self.sort == other.sort) and self.keep == other.keep
and self.sort == other.sort
)
+222 -100
View File
@@ -12,19 +12,27 @@ import unittest
from io import StringIO from io import StringIO
try: try:
from ldgen.entity import Entity, EntityDB from ldgen.entity import Entity
from ldgen.entity import EntityDB
from ldgen.fragments import parse_fragment_file from ldgen.fragments import parse_fragment_file
from ldgen.generation import Generation, GenerationException from ldgen.generation import Generation
from ldgen.generation import GenerationException
from ldgen.linker_script import LinkerScript from ldgen.linker_script import LinkerScript
from ldgen.output_commands import AlignAtAddress, InputSectionDesc, SymbolAtAddress from ldgen.output_commands import AlignAtAddress
from ldgen.output_commands import InputSectionDesc
from ldgen.output_commands import SymbolAtAddress
from ldgen.sdkconfig import SDKConfig from ldgen.sdkconfig import SDKConfig
except ImportError: except ImportError:
sys.path.append(os.path.dirname(os.path.dirname(__file__))) sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from ldgen.entity import Entity, EntityDB from ldgen.entity import Entity
from ldgen.entity import EntityDB
from ldgen.fragments import parse_fragment_file from ldgen.fragments import parse_fragment_file
from ldgen.generation import Generation, GenerationException from ldgen.generation import Generation
from ldgen.generation import GenerationException
from ldgen.linker_script import LinkerScript from ldgen.linker_script import LinkerScript
from ldgen.output_commands import AlignAtAddress, InputSectionDesc, SymbolAtAddress from ldgen.output_commands import AlignAtAddress
from ldgen.output_commands import InputSectionDesc
from ldgen.output_commands import SymbolAtAddress
from ldgen.sdkconfig import SDKConfig from ldgen.sdkconfig import SDKConfig
ROOT = Entity('*') ROOT = Entity('*')
@@ -38,7 +46,6 @@ FREERTOS2 = Entity('libfreertos2.a')
class GenerationTest(unittest.TestCase): class GenerationTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.generation = Generation() self.generation = Generation()
self.entities = None self.entities = None
@@ -121,7 +128,6 @@ class GenerationTest(unittest.TestCase):
class DefaultMappingTest(GenerationTest): class DefaultMappingTest(GenerationTest):
def test_rule_generation_default(self): def test_rule_generation_default(self):
# Checks that default rules are generated from # Checks that default rules are generated from
# the default scheme properly and even if no mappings # the default scheme properly and even if no mappings
@@ -134,7 +140,7 @@ class DefaultMappingTest(GenerationTest):
def test_default_mapping_lib(self): def test_default_mapping_lib(self):
# Mapping a library with default mapping. This should not emit additional rules, # Mapping a library with default mapping. This should not emit additional rules,
# other than the default ones. # other than the default ones.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -146,7 +152,7 @@ entries:
def test_default_mapping_obj(self): def test_default_mapping_obj(self):
# Mapping an object with default mapping. This should not emit additional rules, # Mapping an object with default mapping. This should not emit additional rules,
# other than the default ones. # other than the default ones.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -158,7 +164,7 @@ entries:
def test_default_mapping_symbol(self): def test_default_mapping_symbol(self):
# Mapping a symbol with default mapping. This should not emit additional rules, # Mapping a symbol with default mapping. This should not emit additional rules,
# other than the default ones. # other than the default ones.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -170,7 +176,7 @@ entries:
def test_default_mapping_all(self): def test_default_mapping_all(self):
# Mapping a library, object, and symbol with default mapping. This should not emit additional rules, # Mapping a library, object, and symbol with default mapping. This should not emit additional rules,
# other than the default ones. # other than the default ones.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -187,7 +193,7 @@ entries:
# #
# This is a check needed to make sure generation does not generate # This is a check needed to make sure generation does not generate
# intermediate commands due to presence of symbol mapping. # intermediate commands due to presence of symbol mapping.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -203,7 +209,7 @@ entries:
# #
# This is a check needed to make sure generation does not generate # This is a check needed to make sure generation does not generate
# intermediate commands due to presence of symbol mapping. # intermediate commands due to presence of symbol mapping.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -214,6 +220,90 @@ entries:
self.test_rule_generation_default() self.test_rule_generation_default()
class MutableMappingTest(GenerationTest):
# Collection of tests for mutable library mappings
def dump_rules(self, rules):
# A simple helper for displaying the rules. It can be used to manually
# compare the actual and expected rules to identify any issues while
# preparing tests.
print()
for target, section_descs in rules.items():
print(f'target: {target}')
for section_desc in section_descs:
print(f' {section_desc.entity}: {section_desc.sections}')
for exclusion in section_desc.exclusions:
print(f' {exclusion}')
def add_mutable_libs_to_rules(self, libs, default_rules):
# Insert mutable lib rules and exclusions into default test rules.
rules = collections.defaultdict(list)
for target, section_descs in default_rules.items():
for section_desc in section_descs:
# Duplicate the current section description.
section_desc_copy = InputSectionDesc(section_desc.entity, section_desc.sections)
for lib in libs:
# Exclude each mutable library from ROOT entity rule.
section_desc_copy.exclusions.add(Entity(lib))
rules[target].append(section_desc_copy)
# Add a rule for each mutable library and each ROOT entity rule section.
# This is done separately because the order is important.
for lib in libs:
for section_desc in section_descs:
rules[target].append(InputSectionDesc(Entity(lib), section_desc.sections))
return rules
def test_rule_generation_default(self):
# Verifies that the default rules are correctly generated from the
# default scheme and that mutable libraries are included in the
# generated rules.
mutable_libs = ['libmutable.a', 'libmutable2.a']
self.generation.mutable_libs = mutable_libs
actual = self.generation.generate(self.entities, False)
default_rules = self.generate_default_rules()
expected = self.add_mutable_libs_to_rules(mutable_libs, default_rules)
self.compare_rules(expected, actual)
self.generation.mutable_libs = []
def test_default_mapping_obj(self):
# Verifies that libfreertos.a:croutine entity is correctly excluded
# from the libfreertos.a entity and moved to iram and dram.
mapping = """
[mapping:test]
archive: libfreertos.a
entries:
croutine (noflash)
"""
mutable_libs = ['libfreertos.a']
self.generation.mutable_libs = mutable_libs
self.add_fragments(mapping)
actual = self.generation.generate(self.entities, False)
default_rules = self.generate_default_rules()
expected = self.add_mutable_libs_to_rules(mutable_libs, default_rules)
flash_text = expected['flash_text']
flash_rodata = expected['flash_rodata']
iram0_text = expected['iram0_text']
dram0_data = expected['dram0_data']
# Add exclusions for the libfreertos.a:croutine entity into
# libfreertos.a entity in test and rodata.
flash_text[1].exclusions.add(CROUTINE)
flash_rodata[1].exclusions.add(CROUTINE)
# Add rules for the libfreertos.a:croutine entity in iram and dram.
iram0_text.append(InputSectionDesc(CROUTINE, flash_text[1].sections))
dram0_data.append(InputSectionDesc(CROUTINE, flash_rodata[1].sections))
self.compare_rules(expected, actual)
class BasicTest(GenerationTest): class BasicTest(GenerationTest):
# Test basic and fundamental interactions between typical # Test basic and fundamental interactions between typical
# entries. # entries.
@@ -230,7 +320,7 @@ class BasicTest(GenerationTest):
# iram0_text # iram0_text
# *(.iram ...) # *(.iram ...)
# *libfreertos.a(.literal ...) B # *libfreertos.a(.literal ...) B
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -260,14 +350,14 @@ entries:
# There should be exclusions in the default commands for flash_text and flash_rodata: # There should be exclusions in the default commands for flash_text and flash_rodata:
# #
# flash_text # flash_text
# *((EXCLUDE_FILE(libfreertos.a:croutine)) .literal ...) A # *((EXCLUDE_FILE(libfreertos.a:croutine)) .literal ...) A
# #
# Commands placing the entire library in iram, dram should be generated: # Commands placing the entire library in iram, dram should be generated:
# #
# iram0_text # iram0_text
# *(.iram ...) # *(.iram ...)
# *libfreertos.a:croutine(.literal ...) B # *libfreertos.a:croutine(.literal ...) B
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -295,19 +385,20 @@ entries:
def test_nondefault_mapping_symbol(self): def test_nondefault_mapping_symbol(self):
# Test mapping entry different from default for symbol. # Test mapping entry different from default for symbol.
# There should be exclusions in the default commands for flash_text, as well as the implicit intermediate object command # There should be exclusions in the default commands for flash_text, as
# well as the implicit intermediate object command
# with an exclusion from default: # with an exclusion from default:
# #
# flash_text # flash_text
# *((EXCLUDE_FILE(libfreertos.a:croutine)) .literal ...) A # *((EXCLUDE_FILE(libfreertos.a:croutine)) .literal ...) A
# *libfreertos.a:croutine(.literal .literal.prvCheckDelayedList ...) B # *libfreertos.a:croutine(.literal .literal.prvCheckDelayedList ...) B
# #
# Commands placing the entire library in iram should be generated: # Commands placing the entire library in iram should be generated:
# #
# iram0_text # iram0_text
# *(.iram ...) # *(.iram ...)
# *libfreertos.a:croutine(.text.prvCheckPendingReadyList .literal.prvCheckPendingReadyList) C # *libfreertos.a:croutine(.text.prvCheckPendingReadyList .literal.prvCheckPendingReadyList) C
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -336,7 +427,9 @@ entries:
flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), [])) flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), []))
# Input section commands in iram_text for #1 C # Input section commands in iram_text for #1 C
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) iram0_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
@@ -351,14 +444,14 @@ entries:
# object file, including .debug, .comment and other input section. # object file, including .debug, .comment and other input section.
# #
# flash.rodata # flash.rodata
# *((EXCLUDE_FILE(*libsoc.a:temperature_sensor_periph.*)) .rodata.* ...) A # *((EXCLUDE_FILE(*libsoc.a:temperature_sensor_periph.*)) .rodata.* ...) A
# # *libsoc.a:temperature_sensor_periph.* X # # *libsoc.a:temperature_sensor_periph.* X
# #
# Commands placing the entire library in iram should be generated: # Commands placing the entire library in iram should be generated:
# #
# dram0_data # dram0_data
# *libsoc.a:temperature_sensor_periph.*(.rodata.temperature_sensor_attribute) B # *libsoc.a:temperature_sensor_periph.*(.rodata.temperature_sensor_attribute) B
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libsoc.a archive: libsoc.a
entries: entries:
@@ -376,14 +469,15 @@ entries:
flash_rodata[0].exclusions.add(TEMPERATURE_SENSOR_PERIPH) flash_rodata[0].exclusions.add(TEMPERATURE_SENSOR_PERIPH)
# Input section commands in dram0_data for #1 B # Input section commands in dram0_data for #1 B
dram0_data.append(InputSectionDesc(TEMPERATURE_SENSOR_PERIPH, dram0_data.append(
set(['.rodata.temperature_sensor_attributes']), InputSectionDesc(TEMPERATURE_SENSOR_PERIPH, set(['.rodata.temperature_sensor_attributes']), [])
[])) )
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
def test_default_symbol_nondefault_lib(self): def test_default_symbol_nondefault_lib(self):
# Test default symbol mapping with different lib mapping. This should create an implicit intermediate object command. # Test default symbol mapping with different lib mapping. This should
# create an implicit intermediate object command.
# The significant targets are flash_text, flash_rodata, iram0_text, dram0_data. # The significant targets are flash_text, flash_rodata, iram0_text, dram0_data.
# #
# flash_text # flash_text
@@ -403,7 +497,7 @@ entries:
# libfreertos.a ( .rodata ...) C.2 # libfreertos.a ( .rodata ...) C.2
# #
# Only default commands are in the other targets. # Only default commands are in the other targets.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -440,7 +534,9 @@ entries:
iram0_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), [])) iram0_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), []))
# Command for #2 B # Command for #2 B
flash_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) flash_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
@@ -465,7 +561,7 @@ entries:
# *libfreertos.a:croutine(.rodata ....) C.2 # *libfreertos.a:croutine(.rodata ....) C.2
# #
# Only default commands are in the other targets # Only default commands are in the other targets
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -499,7 +595,9 @@ entries:
dram0_data.append(InputSectionDesc(CROUTINE, flash_rodata[0].sections, [])) dram0_data.append(InputSectionDesc(CROUTINE, flash_rodata[0].sections, []))
# Command for #2 B # Command for #2 B
flash_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) flash_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
@@ -532,7 +630,7 @@ entries:
# libfreertos.a (EXCLUDE_FILE(libfreertos:croutine) .rodata ...) C # libfreertos.a (EXCLUDE_FILE(libfreertos:croutine) .rodata ...) C
# #
# For the other targets only the default commands should be present. # For the other targets only the default commands should be present.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -575,14 +673,16 @@ entries:
flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), [])) flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), []))
# Command for #3 D # Command for #3 D
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) iram0_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
def test_nondefault_but_same_lib_and_obj(self): def test_nondefault_but_same_lib_and_obj(self):
# Extension of DefaultMappingTest. Commands should not be generated for #2, since it does similar mapping # Extension of DefaultMappingTest. Commands should not be generated for #2, since it does similar mapping
# to #1. Output is similar to test_different_mapping_lib. # to #1. Output is similar to test_different_mapping_lib.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -594,7 +694,7 @@ entries:
def test_nondefault_but_same_lib_and_sym(self): def test_nondefault_but_same_lib_and_sym(self):
# Extension of DefaultMappingTest. Commands should not be generated for #2, since it does similar mapping # Extension of DefaultMappingTest. Commands should not be generated for #2, since it does similar mapping
# to #1. Output is similar to test_different_mapping_lib. # to #1. Output is similar to test_different_mapping_lib.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -606,7 +706,7 @@ entries:
def test_nondefault_but_same_obj_and_sym(self): def test_nondefault_but_same_obj_and_sym(self):
# Commands should not be generated for #2, since it does similar mapping # Commands should not be generated for #2, since it does similar mapping
# to #1. Output is similar to test_different_mapping_obj. # to #1. Output is similar to test_different_mapping_obj.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -627,7 +727,7 @@ entries:
# iram0_text # iram0_text
# #
# #
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -659,8 +759,12 @@ entries:
flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), [])) flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), []))
# Commands for #1 & 2 # Commands for #1 & 2
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckDelayedList', '.literal.prvCheckDelayedList']), [])) iram0_text.append(
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) InputSectionDesc(CROUTINE, set(['.text.prvCheckDelayedList', '.literal.prvCheckDelayedList']), [])
)
iram0_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
@@ -671,7 +775,7 @@ entries:
# iram0_text # iram0_text
# * (.custom_section) A # * (.custom_section) A
# * (.iram .iram.*) # * (.iram .iram.*)
mapping = u""" mapping = """
[sections:custom_section] [sections:custom_section]
entries: entries:
.custom_section .custom_section
@@ -700,7 +804,6 @@ entries:
class AdvancedTest(GenerationTest): class AdvancedTest(GenerationTest):
# Test valid but quirky cases, corner cases, failure cases, and # Test valid but quirky cases, corner cases, failure cases, and
# cases involving interaction between schemes, other mapping # cases involving interaction between schemes, other mapping
# fragments. # fragments.
@@ -727,7 +830,7 @@ class AdvancedTest(GenerationTest):
# *(.data ..) # *(.data ..)
# *(.dram ...) # *(.dram ...)
# *libfreertos.a:croutine(.rodata .rodata.*) D # *libfreertos.a:croutine(.rodata .rodata.*) D
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -768,20 +871,20 @@ entries:
# This operation should succeed with the following commands: # This operation should succeed with the following commands:
# #
# flash_text # flash_text
# *(EXCLUDE_FILE(libfreertos.a:croutine) .text ...) A # *(EXCLUDE_FILE(libfreertos.a:croutine) .text ...) A
# #
# flash_rodata # flash_rodata
# *(EXCLUDE_FILE(libfreertos.a:croutine) .rodata ...) B # *(EXCLUDE_FILE(libfreertos.a:croutine) .rodata ...) B
# #
# iram0_text # iram0_text
# *(.iram ...) # *(.iram ...)
# *libfreertos.a:croutine(.text .text.* ...) C # *libfreertos.a:croutine(.text .text.* ...) C
# #
# dram0_data # dram0_data
# *(.data ..) # *(.data ..)
# *(.dram ...) # *(.dram ...)
# *libfreertos.a:croutine(.rodata .rodata.*) D # *libfreertos.a:croutine(.rodata .rodata.*) D
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -818,7 +921,7 @@ entries:
# noflash = text -> iram0_text, rodata -> dram0_data # noflash = text -> iram0_text, rodata -> dram0_data
# #
# This operation should fail. # This operation should fail.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -837,7 +940,7 @@ entries:
# noflash = .text -> iram0_text, .rodata -> dram0_data # noflash = .text -> iram0_text, .rodata -> dram0_data
# #
# This operation should fail. # This operation should fail.
mapping = u""" mapping = """
[sections:custom_text] [sections:custom_text]
entries: entries:
.text+ .text+
@@ -861,42 +964,42 @@ entries:
# using another. Another object and symbol is mapped the other way around. # using another. Another object and symbol is mapped the other way around.
# #
# flash_text # flash_text
# *(EXCLUDE_FILE(libfreertos.a:croutine libfreertos.a:timers) .text ...) A, B # *(EXCLUDE_FILE(libfreertos.a:croutine libfreertos.a:timers) .text ...) A, B
# #
# flash_rodata # flash_rodata
# *(EXCLUDE_FILE(libfreertos.a:croutine libfreertos.a:timers) .rodata ...) A, B # *(EXCLUDE_FILE(libfreertos.a:croutine libfreertos.a:timers) .rodata ...) A, B
# #
# dram0_data # dram0_data
# *(EXCLUDE_FILES(libfreertos.a:timers) .data ..) B # *(EXCLUDE_FILES(libfreertos.a:timers) .data ..) B
# *(.dram ...) # *(.dram ...)
# *libfreertos.a:croutine(.rodata .rodata.*) C # *libfreertos.a:croutine(.rodata .rodata.*) C
# *libfreertos.a:timers(.rodata.prvProcessReceivedCommands ...) E # *libfreertos.a:timers(.rodata.prvProcessReceivedCommands ...) E
# #
# dram0_bss # dram0_bss
# *(EXCLUDE_FILE(libfreertos.a:timers) .bss .bss.* ...) B # *(EXCLUDE_FILE(libfreertos.a:timers) .bss .bss.* ...) B
# *(EXCLUDE_FILE(libfreertos.a:timers) COMMON) B # *(EXCLUDE_FILE(libfreertos.a:timers) COMMON) B
# #
# iram0_text # iram0_text
# *(.iram ...) # *(.iram ...)
# *libfreertos.a:croutine(.literal .literal.prvCheckDelayedList ...) C # *libfreertos.a:croutine(.literal .literal.prvCheckDelayedList ...) C
# *libfreertos.a:timers(.literal .literal.prvProcessReceivedCommands ...) E # *libfreertos.a:timers(.literal .literal.prvProcessReceivedCommands ...) E
# #
# rtc_text # rtc_text
# *(rtc.text .rtc.literal) # *(rtc.text .rtc.literal)
# libfreertos.a:croutine (.text.prvCheckPendingReadyList .literal.prvCheckPendingReadyList) F # libfreertos.a:croutine (.text.prvCheckPendingReadyList .literal.prvCheckPendingReadyList) F
# libfreertos.a:timers (.text .text.prvCheckForValidListAndQueue ...) D.2 # libfreertos.a:timers (.text .text.prvCheckForValidListAndQueue ...) D.2
# #
# rtc_data # rtc_data
# *(rtc.data) # *(rtc.data)
# *(rtc.rodata) # *(rtc.rodata)
# libfreertos.a:timers (.data .data.*) D # libfreertos.a:timers (.data .data.*) D
# libfreertos.a:timers (.rodata ...) D.2 # libfreertos.a:timers (.rodata ...) D.2
# #
# rtc_bss # rtc_bss
# *(rtc.bss .rtc.bss) # *(rtc.bss .rtc.bss)
# libfreertos.a:timers (.bss .bss.*) D # libfreertos.a:timers (.bss .bss.*) D
# libfreertos.a:timers (COMMON) D # libfreertos.a:timers (COMMON) D
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -944,7 +1047,9 @@ entries:
# Commands for #4 F # Commands for #4 F
# Processed first due to alphabetical ordering # Processed first due to alphabetical ordering
rtc_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) rtc_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
# Commands for #2 D # Commands for #2 D
# List all relevant sections excluding #3 for text -> rtc_text and D.2 # List all relevant sections excluding #3 for text -> rtc_text and D.2
@@ -966,7 +1071,11 @@ entries:
rtc_bss.append(InputSectionDesc(TIMERS, dram0_bss[1].sections, [])) rtc_bss.append(InputSectionDesc(TIMERS, dram0_bss[1].sections, []))
# Commands for #3 E # Commands for #3 E
iram0_text.append(InputSectionDesc(TIMERS, set(['.text.prvProcessReceivedCommands', '.literal.prvProcessReceivedCommands']), [])) iram0_text.append(
InputSectionDesc(
TIMERS, set(['.text.prvProcessReceivedCommands', '.literal.prvProcessReceivedCommands']), []
)
)
dram0_data.append(InputSectionDesc(TIMERS, set(['.rodata.prvProcessReceivedCommands']), [])) dram0_data.append(InputSectionDesc(TIMERS, set(['.rodata.prvProcessReceivedCommands']), []))
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
@@ -983,7 +1092,7 @@ entries:
# * (EXCLUDE_FILE(libfreertos.a libfreertos.a:croutine) .text ...) # * (EXCLUDE_FILE(libfreertos.a libfreertos.a:croutine) .text ...)
# #
# iram0_text # iram0_text
mapping = u""" mapping = """
[mapping:test_1] [mapping:test_1]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -1028,7 +1137,7 @@ entries:
# #
# Uses the same entries as C_05 but spreads them across # Uses the same entries as C_05 but spreads them across
# two fragments. The output should still be the same. # two fragments. The output should still be the same.
mapping = u""" mapping = """
[mapping:test_1] [mapping:test_1]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -1046,7 +1155,7 @@ entries:
def test_mapping_same_lib_in_multiple_fragments_conflict(self): def test_mapping_same_lib_in_multiple_fragments_conflict(self):
# Test mapping fragments operating on the same archive # Test mapping fragments operating on the same archive
# with conflicting mappings. # with conflicting mappings.
mapping = u""" mapping = """
[mapping:test_1] [mapping:test_1]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -1078,7 +1187,7 @@ entries:
# libfreertos:croutine(.text.prvCheckPendingReadyList .literal.prvCheckPendingReadyList) G # libfreertos:croutine(.text.prvCheckPendingReadyList .literal.prvCheckPendingReadyList) G
# libfreertos2:croutine(.text .literal ...) D # libfreertos2:croutine(.text .literal ...) D
# libfreertos2:croutine2(.text .literal ...) E # libfreertos2:croutine2(.text .literal ...) E
mapping = u""" mapping = """
[mapping:freertos2] [mapping:freertos2]
archive: libfreertos2.a archive: libfreertos2.a
entries: entries:
@@ -1116,8 +1225,12 @@ entries:
flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), [])) flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), []))
# Command for # Command for
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckDelayedList', '.literal.prvCheckDelayedList']), [])) iram0_text.append(
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) InputSectionDesc(CROUTINE, set(['.text.prvCheckDelayedList', '.literal.prvCheckDelayedList']), [])
)
iram0_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
iram0_text.append(InputSectionDesc(Entity(FREERTOS2.archive, 'croutine'), flash_text[0].sections, [])) iram0_text.append(InputSectionDesc(Entity(FREERTOS2.archive, 'croutine'), flash_text[0].sections, []))
iram0_text.append(InputSectionDesc(Entity(FREERTOS2.archive, 'croutine2'), flash_text[0].sections, [])) iram0_text.append(InputSectionDesc(Entity(FREERTOS2.archive, 'croutine2'), flash_text[0].sections, []))
@@ -1126,7 +1239,7 @@ entries:
def test_ambigious_obj(self): def test_ambigious_obj(self):
# Command generation for ambiguous entry should fail. # Command generation for ambiguous entry should fail.
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -1143,7 +1256,7 @@ entries:
# #
# 'custom_scheme' entries conflict the 'default' scheme # 'custom_scheme' entries conflict the 'default' scheme
# entries. # entries.
mapping = u""" mapping = """
[scheme:custom_scheme] [scheme:custom_scheme]
entries: entries:
flash_text -> iram0_text flash_text -> iram0_text
@@ -1163,7 +1276,7 @@ entries:
# #
# custom_scheme has the 'iram -> iram0_text' in common with # custom_scheme has the 'iram -> iram0_text' in common with
# default scheme # default scheme
mapping = u""" mapping = """
[sections:custom_section] [sections:custom_section]
entries: entries:
.custom_section .custom_section
@@ -1198,7 +1311,7 @@ class ConfigTest(GenerationTest):
def _test_conditional_on_scheme(self, perf, alt=None): def _test_conditional_on_scheme(self, perf, alt=None):
# Test that proper commands are generated if using # Test that proper commands are generated if using
# schemes with conditional entries. # schemes with conditional entries.
scheme = u""" scheme = """
[sections:cond_text_data] [sections:cond_text_data]
entries: entries:
if PERFORMANCE_LEVEL >= 1: if PERFORMANCE_LEVEL >= 1:
@@ -1215,7 +1328,7 @@ entries:
cond_text_data -> dram0_data cond_text_data -> dram0_data
""" """
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: lib.a archive: lib.a
entries: entries:
@@ -1250,7 +1363,7 @@ entries:
def test_conditional_mapping(self, alt=None): def test_conditional_mapping(self, alt=None):
# Test that proper commands are generated # Test that proper commands are generated
# in conditional mapping entries. # in conditional mapping entries.
mapping = u""" mapping = """
[mapping:default] [mapping:default]
archive: * archive: *
entries: entries:
@@ -1299,7 +1412,7 @@ entries:
def test_multiple_fragment_same_lib_conditional(self): def test_multiple_fragment_same_lib_conditional(self):
# Test conditional entries on new mapping fragment grammar. # Test conditional entries on new mapping fragment grammar.
# across multiple fragments. # across multiple fragments.
mapping = u""" mapping = """
[mapping:default] [mapping:default]
archive: * archive: *
entries: entries:
@@ -1331,7 +1444,6 @@ entries:
class FlagTest(GenerationTest): class FlagTest(GenerationTest):
# Test correct generation of mapping fragment entries # Test correct generation of mapping fragment entries
# with flags. # with flags.
@@ -1362,7 +1474,7 @@ class FlagTest(GenerationTest):
# libfreertos.a:croutine(.text .literal ...) I # libfreertos.a:croutine(.text .literal ...) I
# . = ALIGN(4) G.2 # . = ALIGN(4) G.2
# _sym1_end H.2 # _sym1_end H.2
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -1422,7 +1534,7 @@ entries:
# iram0_text # iram0_text
# *(.iram .iram.*) # *(.iram .iram.*)
# libfreertos.a:croutine(.text.prvCheckPendingReadyList ...) D # libfreertos.a:croutine(.text.prvCheckPendingReadyList ...) D
mapping = u""" mapping = """
[mapping:default] [mapping:default]
archive: * archive: *
entries: entries:
@@ -1466,7 +1578,9 @@ entries:
flash_text.append(SymbolAtAddress('_sym1_end')) flash_text.append(SymbolAtAddress('_sym1_end'))
# Command for #3 D # Command for #3 D
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) iram0_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
@@ -1484,7 +1598,7 @@ entries:
# iram0_text # iram0_text
# *(.iram .iram.*) # *(.iram .iram.*)
# libfreertos.a:croutine(.text.prvCheckPendingReadyList ...) D # libfreertos.a:croutine(.text.prvCheckPendingReadyList ...) D
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -1523,7 +1637,9 @@ entries:
flash_text.append(SymbolAtAddress('_sym1_end')) flash_text.append(SymbolAtAddress('_sym1_end'))
# Command for #3 C # Command for #3 C
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) iram0_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
@@ -1540,7 +1656,7 @@ entries:
# iram0_text # iram0_text
# *(.iram .iram.*) # *(.iram .iram.*)
# libfreertos.a:croutine(.text.prvCheckPendingReadyList ...) C # libfreertos.a:croutine(.text.prvCheckPendingReadyList ...) C
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -1575,7 +1691,9 @@ entries:
flash_text.append(SymbolAtAddress('_sym1_end')) flash_text.append(SymbolAtAddress('_sym1_end'))
# Command for #3 C # Command for #3 C
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) iram0_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
@@ -1591,7 +1709,7 @@ entries:
# iram0_text # iram0_text
# *(.iram .iram.*) # *(.iram .iram.*)
# libfreertos.a:croutine(.text.prvCheckPendingReadyList ...) D # libfreertos.a:croutine(.text.prvCheckPendingReadyList ...) D
mapping = u""" mapping = """
[mapping:default] [mapping:default]
archive: * archive: *
entries: entries:
@@ -1636,7 +1754,9 @@ entries:
flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), [])) flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), []))
# Command for #4 D # Command for #4 D
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) iram0_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
@@ -1653,7 +1773,7 @@ entries:
# iram0_text # iram0_text
# *(.iram .iram.*) # *(.iram .iram.*)
# libfreertos.a:croutine(.text.prvCheckPendingReadyList ...) D # libfreertos.a:croutine(.text.prvCheckPendingReadyList ...) D
mapping = u""" mapping = """
[mapping:test] [mapping:test]
archive: libfreertos.a archive: libfreertos.a
entries: entries:
@@ -1693,14 +1813,16 @@ entries:
flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), [])) flash_text.append(InputSectionDesc(CROUTINE, set(filtered_sections), []))
# Command for #3 C # Command for #3 C
iram0_text.append(InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])) iram0_text.append(
InputSectionDesc(CROUTINE, set(['.text.prvCheckPendingReadyList', '.literal.prvCheckPendingReadyList']), [])
)
self.compare_rules(expected, actual) self.compare_rules(expected, actual)
def test_flag_additions(self): def test_flag_additions(self):
# Test ability to add flags as long as no other mapping fragments # Test ability to add flags as long as no other mapping fragments
# does the same thing. # does the same thing.
mapping = u""" mapping = """
[mapping:default_add_flag] [mapping:default_add_flag]
archive: * archive: *
entries: entries:
@@ -1721,7 +1843,7 @@ entries:
def test_flags_flag_additions_duplicate(self): def test_flags_flag_additions_duplicate(self):
# Test same flags added to same entity - these # Test same flags added to same entity - these
# are ignored. # are ignored.
mapping = u""" mapping = """
[mapping:default_add_flag_1] [mapping:default_add_flag_1]
archive: * archive: *
entries: entries:
@@ -1748,7 +1870,7 @@ entries:
def test_flags_flag_additions_conflict(self): def test_flags_flag_additions_conflict(self):
# Test condition where multiple fragments specifies flags # Test condition where multiple fragments specifies flags
# to same entity - should generate exception. # to same entity - should generate exception.
mapping = u""" mapping = """
[mapping:default_add_flag_1] [mapping:default_add_flag_1]
archive: * archive: *
entries: entries: