From eb67fea33d4d342dfb59fd75738b0a14a2a1ccbc Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Wed, 28 Jan 2026 22:29:22 +0100 Subject: [PATCH] feat(coredump): add coredump_extram attribute Closes https://github.com/espressif/esp-idf/issues/15429 (cherry picked from commit 5ba3e9df98f707534f509199b605c639af3f16c9) --- components/esp_common/include/esp_attr.h | 6 ++++++ .../include_core_dump/esp_core_dump_common.h | 8 +++++++- components/espcoredump/linker.lf | 14 +++++++++++++- components/espcoredump/src/core_dump_common.c | 14 ++++++++++++++ .../system/panic/main/include/test_panic.h | 4 ++++ .../system/panic/main/test_app_main.c | 4 ++++ .../test_apps/system/panic/main/test_panic.c | 10 ++++++++++ tools/test_apps/system/panic/pytest_panic.py | 19 +++++++++++++++++++ ...config.ci.coredump_flash_extram_attr_esp32 | 12 ++++++++++++ 9 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_attr_esp32 diff --git a/components/esp_common/include/esp_attr.h b/components/esp_common/include/esp_attr.h index 12cbe99d995..9ac789bfc68 100644 --- a/components/esp_common/include/esp_attr.h +++ b/components/esp_common/include/esp_attr.h @@ -142,8 +142,11 @@ extern "C" { #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY // Forces bss variable into external memory. " #define EXT_RAM_BSS_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__) +// Forces data into external memory BSS and maps it to coredump +#define COREDUMP_EXTRAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.coredump", __COUNTER__) #else #define EXT_RAM_BSS_ATTR +#define COREDUMP_EXTRAM_ATTR #endif // Forces data into noinit section to avoid initialization after restart. @@ -152,9 +155,12 @@ extern "C" { #if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY // Forces data into external memory noinit section to avoid initialization after restart. #define EXT_RAM_NOINIT_ATTR _SECTION_ATTR_IMPL(".ext_ram_noinit", __COUNTER__) +// Forces data into external memory noinit section and maps it to coredump +#define COREDUMP_EXTRAM_NOINIT_ATTR _SECTION_ATTR_IMPL(".ext_ram_noinit.coredump", __COUNTER__) #else // Place in internal noinit section #define EXT_RAM_NOINIT_ATTR __NOINIT_ATTR +#define COREDUMP_EXTRAM_NOINIT_ATTR #endif // Forces code into DRAM instead of flash and map it to coredump diff --git a/components/espcoredump/include_core_dump/esp_core_dump_common.h b/components/espcoredump/include_core_dump/esp_core_dump_common.h index 5c23c73dcf4..1db43971653 100644 --- a/components/espcoredump/include_core_dump/esp_core_dump_common.h +++ b/components/espcoredump/include_core_dump/esp_core_dump_common.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -38,6 +38,12 @@ typedef enum { COREDUMP_MEMORY_RTC_FAST, #endif COREDUMP_MEMORY_NOINIT, +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + COREDUMP_MEMORY_EXTRAM, +#endif +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + COREDUMP_MEMORY_EXTRAM_NOINIT, +#endif COREDUMP_MEMORY_MAX, COREDUMP_MEMORY_START = COREDUMP_MEMORY_IRAM } coredump_region_t; diff --git a/components/espcoredump/linker.lf b/components/espcoredump/linker.lf index 9e4f893df72..5e1cae98ce6 100644 --- a/components/espcoredump/linker.lf +++ b/components/espcoredump/linker.lf @@ -25,6 +25,14 @@ entries: entries: .noinit.coredump+ +[sections:extram_coredump] +entries: + .ext_ram.coredump+ + +[sections:extram_noinit_coredump] +entries: + .ext_ram_noinit.coredump+ + [scheme:coredump_default] entries: dram_coredump -> dram0_data @@ -33,6 +41,8 @@ entries: rtc_noinit_coredump -> rtc_noinit noinit_coredump -> noinit iram_coredump -> iram0_data + extram_coredump -> extern_ram + extram_noinit_coredump -> extram_noinit [mapping:coredump_default] archive: * @@ -43,7 +53,9 @@ entries: rtc_noinit_coredump -> rtc_noinit SURROUND(coredump_rtc_noinit), noinit_coredump -> noinit SURROUND(coredump_noinit), dram_coredump -> dram0_data SURROUND(coredump_dram), - iram_coredump -> iram0_data SURROUND(coredump_iram) + iram_coredump -> iram0_data SURROUND(coredump_iram), + extram_coredump -> extern_ram SURROUND(coredump_extram), + extram_noinit_coredump -> extram_noinit SURROUND(coredump_extram_noinit) [mapping:espcoredump] archive: libespcoredump.a diff --git a/components/espcoredump/src/core_dump_common.c b/components/espcoredump/src/core_dump_common.c index 2a12cef5238..3267a277eac 100644 --- a/components/espcoredump/src/core_dump_common.c +++ b/components/espcoredump/src/core_dump_common.c @@ -57,6 +57,14 @@ extern int _coredump_rtc_noinit_end; extern int _coredump_noinit_start; extern int _coredump_noinit_end; #endif +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY +extern int _coredump_extram_start; +extern int _coredump_extram_end; +#endif +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY +extern int _coredump_extram_noinit_start; +extern int _coredump_extram_noinit_end; +#endif static void* s_exc_frame = NULL; static uint32_t s_coredump_sp = 0; @@ -271,6 +279,12 @@ static const struct { #else [COREDUMP_MEMORY_NOINIT] = { &_coredump_noinit_start, &_coredump_noinit_end }, #endif +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + [COREDUMP_MEMORY_EXTRAM] = { &_coredump_extram_start, &_coredump_extram_end }, +#endif +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + [COREDUMP_MEMORY_EXTRAM_NOINIT] = { &_coredump_extram_noinit_start, &_coredump_extram_noinit_end }, +#endif }; int esp_core_dump_get_user_ram_info(coredump_region_t region, uint32_t *start) diff --git a/tools/test_apps/system/panic/main/include/test_panic.h b/tools/test_apps/system/panic/main/include/test_panic.h index b61c70aa758..cc46d3dc782 100644 --- a/tools/test_apps/system/panic/main/include/test_panic.h +++ b/tools/test_apps/system/panic/main/include/test_panic.h @@ -87,6 +87,10 @@ void test_panic_print_backtrace(void); void test_panic_halt(void); #endif /* CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT */ +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY && CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY +void test_panic_extram_attr(void); +#endif + #ifdef __cplusplus } #endif diff --git a/tools/test_apps/system/panic/main/test_app_main.c b/tools/test_apps/system/panic/main/test_app_main.c index 967c97d691d..c0c86d64a98 100644 --- a/tools/test_apps/system/panic/main/test_app_main.c +++ b/tools/test_apps/system/panic/main/test_app_main.c @@ -222,5 +222,9 @@ void app_main(void) #endif #endif +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY && CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + HANDLE_TEST(test_name, test_panic_extram_attr); +#endif + die("Unknown test name"); } diff --git a/tools/test_apps/system/panic/main/test_panic.c b/tools/test_apps/system/panic/main/test_panic.c index 6947146e229..62edf6ef487 100644 --- a/tools/test_apps/system/panic/main/test_panic.c +++ b/tools/test_apps/system/panic/main/test_panic.c @@ -430,6 +430,16 @@ void test_capture_dram(void) } #endif +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY && CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY +COREDUMP_EXTRAM_ATTR uint32_t g_extram_bss_var; +COREDUMP_EXTRAM_NOINIT_ATTR uint32_t g_extram_noinit_var; +void test_panic_extram_attr(void) +{ + g_extram_bss_var = 123456; + g_extram_noinit_var = 789012; + assert(0); +} +#endif #if CONFIG_ESP_SYSTEM_USE_FRAME_POINTER diff --git a/tools/test_apps/system/panic/pytest_panic.py b/tools/test_apps/system/panic/pytest_panic.py index 5b505339d29..8be183c3fb8 100644 --- a/tools/test_apps/system/panic/pytest_panic.py +++ b/tools/test_apps/system/panic/pytest_panic.py @@ -285,6 +285,25 @@ def test_panic_extram_stack(dut: PanicTestDut, config: str) -> None: common_test(dut, config, expected_backtrace=None, expected_coredump=[coredump_pattern]) +@pytest.mark.psram +@idf_parametrize('config, target', [('coredump_flash_extram_attr_esp32', 'esp32')], indirect=['config', 'target']) +def test_panic_extram_attr(dut: PanicTestDut, config: str) -> None: + dut.run_test_func('test_panic_extram_attr') + regex_pattern = rb'assert failed:[\s\w()]*?\s[.\w/]*\.(?:c|cpp|h|hpp):\d.*$' + dut.expect(re.compile(regex_pattern, re.MULTILINE)) + dut.expect_backtrace() + dut.expect_elf_sha256() + dut.expect_none(['Guru Meditation', 'Re-entered core dump']) + + expect_coredump_flash_write_logs(dut, config) + core_elf_file = dut.process_coredump_flash() + + dut.start_gdb_for_coredump(core_elf_file) + + assert dut.gdb_data_eval_expr('g_extram_bss_var') == '123456' + assert dut.gdb_data_eval_expr('g_extram_noinit_var') == '789012' + + @pytest.mark.generic @idf_parametrize('config, target', CONFIGS, indirect=['config', 'target']) def test_int_wdt(dut: PanicTestDut, target: str, config: str, test_func_name: str) -> None: diff --git a/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_attr_esp32 b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_attr_esp32 new file mode 100644 index 00000000000..e08d89715d6 --- /dev/null +++ b/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_extram_attr_esp32 @@ -0,0 +1,12 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y +# We need to have the coredump info log +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +CONFIG_SPIRAM=y +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y +CONFIG_ESP_COREDUMP_USE_STACK_SIZE=y +CONFIG_ESP_COREDUMP_CAPTURE_DRAM=y +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_capture_dram.csv"