Merge branch 'staging/coredump_extram_support' into 'master'

coredump: enable support for stacks in external RAM

Closes IDF-5497 and IDF-2391

See merge request espressif/esp-idf!21067
This commit is contained in:
Omar Chebib
2022-12-26 17:52:41 +08:00
9 changed files with 93 additions and 9 deletions

View File

@@ -14,7 +14,6 @@ menu "Core dump"
config ESP_COREDUMP_ENABLE_TO_FLASH config ESP_COREDUMP_ENABLE_TO_FLASH
bool "Flash" bool "Flash"
depends on !SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
select FREERTOS_ENABLE_TASK_SNAPSHOT select FREERTOS_ENABLE_TASK_SNAPSHOT
select ESP_COREDUMP_ENABLE select ESP_COREDUMP_ENABLE
config ESP_COREDUMP_ENABLE_TO_UART config ESP_COREDUMP_ENABLE_TO_UART
@@ -79,10 +78,21 @@ menu "Core dump"
Config delay (in ms) before printing core dump to UART. Config delay (in ms) before printing core dump to UART.
Delay can be interrupted by pressing Enter key. Delay can be interrupted by pressing Enter key.
config ESP_COREDUMP_USE_STACK_SIZE
bool
default y if ESP_COREDUMP_ENABLE_TO_FLASH && SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
default n
help
Force the use of a custom DRAM stack for coredump when Task stacks can be in PSRAM.
config ESP_COREDUMP_STACK_SIZE config ESP_COREDUMP_STACK_SIZE
int "Reserved stack size" int "Reserved stack size"
depends on ESP_COREDUMP_ENABLE depends on ESP_COREDUMP_ENABLE
default 0 range 0 4096 if !ESP_COREDUMP_USE_STACK_SIZE
range 1280 4096 if ESP_COREDUMP_USE_STACK_SIZE
default 0 if !ESP_COREDUMP_USE_STACK_SIZE
default 1280 if ESP_COREDUMP_USE_STACK_SIZE
help help
Size of the memory to be reserved for core dump stack. If 0 core dump process will run on Size of the memory to be reserved for core dump stack. If 0 core dump process will run on
the stack of crashed task/ISR, otherwise special stack will be allocated. the stack of crashed task/ISR, otherwise special stack will be allocated.

View File

@@ -115,7 +115,13 @@ FORCE_INLINE_ATTR void esp_core_dump_report_stack_usage(void)
esp_core_dump_restore_sp(&s_stack_context); esp_core_dump_restore_sp(&s_stack_context);
} }
#else #else // CONFIG_ESP_COREDUMP_STACK_SIZE > 0
/* Here, we are not going to use a custom stack for coredump. Make sure the current configuration doesn't require one. */
#if CONFIG_ESP_COREDUMP_USE_STACK_SIZE
#pragma error "CONFIG_ESP_COREDUMP_STACK_SIZE must not be 0 in the current configuration"
#endif // ESP_COREDUMP_USE_STACK_SIZE
FORCE_INLINE_ATTR void esp_core_dump_setup_stack(void) FORCE_INLINE_ATTR void esp_core_dump_setup_stack(void)
{ {
/* If we are in ISR set watchpoint to the end of ISR stack */ /* If we are in ISR set watchpoint to the end of ISR stack */
@@ -133,7 +139,7 @@ FORCE_INLINE_ATTR void esp_core_dump_setup_stack(void)
FORCE_INLINE_ATTR void esp_core_dump_report_stack_usage(void) FORCE_INLINE_ATTR void esp_core_dump_report_stack_usage(void)
{ {
} }
#endif #endif // CONFIG_ESP_COREDUMP_STACK_SIZE > 0
static void* s_exc_frame = NULL; static void* s_exc_frame = NULL;

View File

@@ -306,10 +306,10 @@ bool esp_core_dump_check_task(core_dump_task_header_t *task)
*/ */
bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz) bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz)
{ {
//TODO: external SRAM not supported yet
return (esp_ptr_in_dram((void *)addr) && esp_ptr_in_dram((void *)(addr+sz-1))) return (esp_ptr_in_dram((void *)addr) && esp_ptr_in_dram((void *)(addr+sz-1)))
|| (esp_ptr_in_rtc_slow((void *)addr) && esp_ptr_in_rtc_slow((void *)(addr+sz-1))) || (esp_ptr_in_rtc_slow((void *)addr) && esp_ptr_in_rtc_slow((void *)(addr+sz-1)))
|| (esp_ptr_in_rtc_dram_fast((void *)addr) && esp_ptr_in_rtc_dram_fast((void *)(addr+sz-1))) || (esp_ptr_in_rtc_dram_fast((void *)addr) && esp_ptr_in_rtc_dram_fast((void *)(addr+sz-1)))
|| (esp_ptr_external_ram((void *)addr) && esp_ptr_external_ram((void *)(addr+sz-1)))
|| (esp_ptr_in_iram((void *)addr) && esp_ptr_in_iram((void *)(addr+sz-1))); || (esp_ptr_in_iram((void *)addr) && esp_ptr_in_iram((void *)(addr+sz-1)));
} }

View File

@@ -336,10 +336,10 @@ bool esp_core_dump_check_stack(core_dump_task_header_t *task)
*/ */
bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz) bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz)
{ {
//TODO: external SRAM not supported yet
return (esp_ptr_in_dram((void *)addr) && esp_ptr_in_dram((void *)(addr+sz-1))) return (esp_ptr_in_dram((void *)addr) && esp_ptr_in_dram((void *)(addr+sz-1)))
|| (esp_ptr_in_rtc_slow((void *)addr) && esp_ptr_in_rtc_slow((void *)(addr+sz-1))) || (esp_ptr_in_rtc_slow((void *)addr) && esp_ptr_in_rtc_slow((void *)(addr+sz-1)))
|| (esp_ptr_in_rtc_dram_fast((void *)addr) && esp_ptr_in_rtc_dram_fast((void *)(addr+sz-1))) || (esp_ptr_in_rtc_dram_fast((void *)addr) && esp_ptr_in_rtc_dram_fast((void *)(addr+sz-1)))
|| (esp_ptr_external_ram((void *)addr) && esp_ptr_external_ram((void *)(addr+sz-1)))
|| (esp_ptr_in_iram((void *)addr) && esp_ptr_in_iram((void *)(addr+sz-1))); || (esp_ptr_in_iram((void *)addr) && esp_ptr_in_iram((void *)(addr+sz-1)));
} }

View File

@@ -67,8 +67,6 @@ static IRAM_ATTR esp_err_t start(void *arg)
static IRAM_ATTR esp_err_t end(void *arg) static IRAM_ATTR esp_err_t end(void *arg)
{ {
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
Cache_Flush(0);
Cache_Flush(1);
Cache_Read_Enable(0); Cache_Read_Enable(0);
Cache_Read_Enable(1); Cache_Read_Enable(1);
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3

View File

@@ -1,3 +1,3 @@
idf_component_register(SRCS "test_panic_main.c" idf_component_register(SRCS "test_panic_main.c"
INCLUDE_DIRS "." INCLUDE_DIRS "."
REQUIRES spi_flash esp_system esp_partition) REQUIRES spi_flash esp_psram esp_system esp_partition)

View File

@@ -17,6 +17,9 @@ static void test_abort(void);
static void test_abort_cache_disabled(void); static void test_abort_cache_disabled(void);
static void test_int_wdt(void); static void test_int_wdt(void);
static void test_task_wdt_cpu0(void); static void test_task_wdt_cpu0(void);
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
static void test_panic_extram_stack(void);
#endif
#if !CONFIG_FREERTOS_UNICORE #if !CONFIG_FREERTOS_UNICORE
static void test_task_wdt_cpu1(void); static void test_task_wdt_cpu1(void);
static void test_task_wdt_both_cpus(void); static void test_task_wdt_both_cpus(void);
@@ -55,6 +58,9 @@ void app_main(void)
HANDLE_TEST(test_abort_cache_disabled); HANDLE_TEST(test_abort_cache_disabled);
HANDLE_TEST(test_int_wdt); HANDLE_TEST(test_int_wdt);
HANDLE_TEST(test_task_wdt_cpu0); HANDLE_TEST(test_task_wdt_cpu0);
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
HANDLE_TEST(test_panic_extram_stack);
#endif
#if !CONFIG_FREERTOS_UNICORE #if !CONFIG_FREERTOS_UNICORE
HANDLE_TEST(test_task_wdt_cpu1); HANDLE_TEST(test_task_wdt_cpu1);
HANDLE_TEST(test_task_wdt_both_cpus); HANDLE_TEST(test_task_wdt_both_cpus);
@@ -102,6 +108,34 @@ static void test_task_wdt_cpu0(void)
} }
} }
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
static void stack_in_extram(void* arg) {
(void) arg;
/* Abort instead of using a load/store prohibited to prevent a sanitize error */
abort();
}
static void test_panic_extram_stack(void) {
/* Start by initializing a Task which has a stack in external RAM */
StaticTask_t handle;
const uint32_t stack_size = 8192;
void* stack = heap_caps_malloc(stack_size, MALLOC_CAP_SPIRAM);
/* Make sure the stack is in external RAM */
if (!esp_ptr_external_ram(stack)) {
die("Allocated stack is not in external RAM!\n");
}
xTaskCreateStatic(stack_in_extram, "Task_stack_extram", stack_size, NULL, 4, (StackType_t*) stack, &handle);
vTaskDelay(1000);
}
#endif // ESP_COREDUMP_ENABLE_TO_FLASH && SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
#if !CONFIG_FREERTOS_UNICORE #if !CONFIG_FREERTOS_UNICORE
static void infinite_loop(void* arg) { static void infinite_loop(void* arg) {
(void) arg; (void) arg;

View File

@@ -28,6 +28,14 @@ CONFIGS_ESP32 = [
pytest.param('panic', marks=[pytest.mark.esp32]), pytest.param('panic', marks=[pytest.mark.esp32]),
] ]
# IDF-5692: Uncomment the marks related to ESP32-S3 and quad_psram once ESP32-S3 runners are available
CONFIG_EXTRAM_STACK = [
pytest.param('coredump_extram_stack',
marks=[pytest.mark.esp32, pytest.mark.esp32s2, pytest.mark.psram,
# pytest.mark.esp32s3, pytest.mark.quad_psram
])
]
def get_default_backtrace(config: str) -> List[str]: def get_default_backtrace(config: str) -> List[str]:
return [config, 'app_main', 'main_task', 'vPortTaskWrapper'] return [config, 'app_main', 'main_task', 'vPortTaskWrapper']
@@ -142,6 +150,23 @@ def test_task_wdt_both_cpus(dut: PanicTestDut, config: str, test_func_name: str)
common_test(dut, config) common_test(dut, config)
@pytest.mark.parametrize('config', CONFIG_EXTRAM_STACK, indirect=True)
def test_panic_extram_stack(dut: PanicTestDut, config: str, test_func_name: str) -> None:
dut.expect_test_func_name(test_func_name)
dut.expect_none('Allocated stack is not in external RAM')
dut.expect_none('Guru Meditation')
dut.expect_backtrace()
dut.expect_elf_sha256()
# Check that coredump is getting written to flash
dut.expect_exact('Save core dump to flash...')
# And that the stack is replaced and restored
dut.expect_exact('Backing up stack @')
dut.expect_exact('Restoring stack')
# The caller must be accessible after restoring the stack
dut.expect_exact('Core dump has been saved to flash.')
common_test(dut, config)
@pytest.mark.parametrize('config', CONFIGS, indirect=True) @pytest.mark.parametrize('config', CONFIGS, indirect=True)
@pytest.mark.generic @pytest.mark.generic
def test_int_wdt( def test_int_wdt(

View File

@@ -0,0 +1,11 @@
CONFIG_IDF_TARGET="esp32"
CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y
CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y
CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y
# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
# We need to have the coredump info log
CONFIG_LOG_DEFAULT_LEVEL_INFO=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
CONFIG_ESP_COREDUMP_USE_STACK_SIZE=y