mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'fix/s3_memprot_panic_report' into 'master'
Report ESP32-S3 PMS violations as memory protection faults See merge request espressif/esp-idf!52109
This commit is contained in:
@@ -90,6 +90,10 @@ void panic_prepare_frame_from_ctx(void* frame);
|
||||
|
||||
void panic_clear_active_interrupts(const void* frame);
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMS && !CONFIG_IDF_TARGET_ESP32S2
|
||||
bool panic_memprot_fill_info(panic_info_t *info);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Disable all watchdog timers
|
||||
*
|
||||
|
||||
@@ -45,6 +45,10 @@ elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
|
||||
"arch/riscv/debug_stubs.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_ESP_SYSTEM_MEMPROT AND CONFIG_ESP_SYSTEM_MEMPROT_PMS AND NOT CONFIG_IDF_TARGET_ESP32S2)
|
||||
list(APPEND srcs "panic_memprot.c")
|
||||
endif()
|
||||
|
||||
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
|
||||
|
||||
target_sources(${COMPONENT_LIB} PRIVATE ${srcs})
|
||||
|
||||
@@ -13,11 +13,6 @@
|
||||
#include "riscv/rv_utils.h"
|
||||
#include "esp_private/cache_err_int.h"
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMS
|
||||
#include "esp_private/esp_memprot_internal.h"
|
||||
#include "esp_memprot.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_USE_EH_FRAME
|
||||
#include "esp_private/eh_frame_parser.h"
|
||||
#include "esp_private/cache_utils.h"
|
||||
@@ -83,75 +78,6 @@ static inline void print_assist_debug_details(const void *frame)
|
||||
}
|
||||
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
|
||||
/**
|
||||
* Function called when a memory protection error occurs (PMS). It prints details such as the
|
||||
* explanation of why the panic occurred.
|
||||
*/
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMS
|
||||
|
||||
static esp_memp_intr_source_t s_memp_intr = {MEMPROT_TYPE_INVALID, -1};
|
||||
|
||||
#define PRINT_MEMPROT_ERROR(err) \
|
||||
do { \
|
||||
panic_print_str("N/A (error "); \
|
||||
panic_print_str(esp_err_to_name(err)); \
|
||||
panic_print_str(")"); \
|
||||
} while(0)
|
||||
|
||||
static inline void print_memprot_err_details(const void *frame __attribute__((unused)))
|
||||
{
|
||||
if (s_memp_intr.mem_type == MEMPROT_TYPE_INVALID && s_memp_intr.core == -1) {
|
||||
panic_print_str(" - no details available -\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//common memprot fault info
|
||||
panic_print_str(" memory type: ");
|
||||
panic_print_str(esp_mprot_mem_type_to_str(s_memp_intr.mem_type));
|
||||
|
||||
panic_print_str("\r\n faulting address: ");
|
||||
void *faulting_addr;
|
||||
esp_err_t res = esp_mprot_get_violate_addr(s_memp_intr.mem_type, &faulting_addr, s_memp_intr.core);
|
||||
if (res == ESP_OK) {
|
||||
panic_print_str("0x");
|
||||
panic_print_hex((int)faulting_addr);
|
||||
} else {
|
||||
PRINT_MEMPROT_ERROR(res);
|
||||
}
|
||||
|
||||
panic_print_str("\r\n world: ");
|
||||
esp_mprot_pms_world_t world;
|
||||
res = esp_mprot_get_violate_world(s_memp_intr.mem_type, &world, s_memp_intr.core);
|
||||
if (res == ESP_OK) {
|
||||
panic_print_str(esp_mprot_pms_world_to_str(world));
|
||||
} else {
|
||||
PRINT_MEMPROT_ERROR(res);
|
||||
}
|
||||
|
||||
panic_print_str("\r\n operation type: ");
|
||||
uint32_t operation;
|
||||
res = esp_mprot_get_violate_operation(s_memp_intr.mem_type, &operation, s_memp_intr.core);
|
||||
if (res == ESP_OK) {
|
||||
panic_print_str(esp_mprot_oper_type_to_str(operation));
|
||||
} else {
|
||||
PRINT_MEMPROT_ERROR(res);
|
||||
}
|
||||
|
||||
if (esp_mprot_has_byte_enables(s_memp_intr.mem_type)) {
|
||||
panic_print_str("\r\n byte-enables: ");
|
||||
uint32_t byte_enables;
|
||||
res = esp_mprot_get_violate_byte_enables(s_memp_intr.mem_type, &byte_enables, s_memp_intr.core);
|
||||
if (res == ESP_OK) {
|
||||
panic_print_hex(byte_enables);
|
||||
} else {
|
||||
PRINT_MEMPROT_ERROR(res);
|
||||
}
|
||||
}
|
||||
|
||||
panic_print_str("\r\n");
|
||||
}
|
||||
#endif //CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMS
|
||||
|
||||
static void panic_print_register_array(const char* names[], const uint32_t* regs, int size)
|
||||
{
|
||||
const int regs_per_line = 4;
|
||||
@@ -257,9 +183,7 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
|
||||
#endif
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMS
|
||||
else if (frame->mcause == ETS_MEMPROT_ERR_INUM) {
|
||||
info->reason = "Memory protection fault";
|
||||
info->details = print_memprot_err_details;
|
||||
info->core = esp_mprot_get_active_intr(&s_memp_intr) == ESP_OK ? s_memp_intr.core : -1;
|
||||
panic_memprot_fill_info(info);
|
||||
}
|
||||
#endif //CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMS
|
||||
}
|
||||
|
||||
@@ -20,12 +20,8 @@
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMS
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMS && CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/memprot.h"
|
||||
#else
|
||||
#include "esp_memprot.h"
|
||||
#endif
|
||||
#endif
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
@@ -302,15 +298,20 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
|
||||
info->exception = PANIC_EXCEPTION_DEBUG;
|
||||
}
|
||||
|
||||
//MV note: ESP32S3 PMS handling?
|
||||
if (frame->exccause == PANIC_RSN_CACHEERR) {
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMS && CONFIG_IDF_TARGET_ESP32S2
|
||||
bool memprot_fault = false;
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMS
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
if (esp_memprot_is_intr_ena_any()) {
|
||||
info->details = print_memprot_err_details;
|
||||
info->reason = "Memory protection fault";
|
||||
} else
|
||||
memprot_fault = true;
|
||||
}
|
||||
#else
|
||||
memprot_fault = panic_memprot_fill_info(info);
|
||||
#endif
|
||||
{
|
||||
#endif
|
||||
if (!memprot_fault) {
|
||||
info->details = print_cache_err_details;
|
||||
}
|
||||
}
|
||||
|
||||
97
components/esp_system/port/panic_memprot.c
Normal file
97
components/esp_system/port/panic_memprot.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/panic_internal.h"
|
||||
#include "esp_private/esp_memprot_internal.h"
|
||||
#include "esp_memprot.h"
|
||||
|
||||
static esp_memp_intr_source_t s_memp_intr = {MEMPROT_TYPE_INVALID, -1};
|
||||
|
||||
#define PRINT_MEMPROT_ERROR(err) \
|
||||
do { \
|
||||
panic_print_str("N/A (error "); \
|
||||
panic_print_str(esp_err_to_name(err)); \
|
||||
panic_print_str(")"); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Function called when a memory protection error occurs (PMS). It prints details such as the
|
||||
* explanation of why the panic occurred.
|
||||
*/
|
||||
static void print_memprot_err_details(const void *frame __attribute__((unused)))
|
||||
{
|
||||
if (s_memp_intr.mem_type == MEMPROT_TYPE_INVALID && s_memp_intr.core == -1) {
|
||||
panic_print_str(" - no details available -\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//common memprot fault info
|
||||
panic_print_str(" memory type: ");
|
||||
panic_print_str(esp_mprot_mem_type_to_str(s_memp_intr.mem_type));
|
||||
|
||||
panic_print_str("\r\n faulting address: ");
|
||||
void *faulting_addr;
|
||||
esp_err_t res = esp_mprot_get_violate_addr(s_memp_intr.mem_type, &faulting_addr, s_memp_intr.core);
|
||||
if (res == ESP_OK) {
|
||||
panic_print_str("0x");
|
||||
panic_print_hex((int)faulting_addr);
|
||||
} else {
|
||||
PRINT_MEMPROT_ERROR(res);
|
||||
}
|
||||
|
||||
panic_print_str("\r\n world: ");
|
||||
esp_mprot_pms_world_t world;
|
||||
res = esp_mprot_get_violate_world(s_memp_intr.mem_type, &world, s_memp_intr.core);
|
||||
if (res == ESP_OK) {
|
||||
panic_print_str(esp_mprot_pms_world_to_str(world));
|
||||
} else {
|
||||
PRINT_MEMPROT_ERROR(res);
|
||||
}
|
||||
|
||||
panic_print_str("\r\n operation type: ");
|
||||
uint32_t operation;
|
||||
res = esp_mprot_get_violate_operation(s_memp_intr.mem_type, &operation, s_memp_intr.core);
|
||||
if (res == ESP_OK) {
|
||||
panic_print_str(esp_mprot_oper_type_to_str(operation));
|
||||
} else {
|
||||
PRINT_MEMPROT_ERROR(res);
|
||||
}
|
||||
|
||||
if (esp_mprot_has_byte_enables(s_memp_intr.mem_type)) {
|
||||
panic_print_str("\r\n byte-enables: ");
|
||||
uint32_t byte_enables;
|
||||
res = esp_mprot_get_violate_byte_enables(s_memp_intr.mem_type, &byte_enables, s_memp_intr.core);
|
||||
if (res == ESP_OK) {
|
||||
panic_print_hex(byte_enables);
|
||||
} else {
|
||||
PRINT_MEMPROT_ERROR(res);
|
||||
}
|
||||
}
|
||||
|
||||
panic_print_str("\r\n");
|
||||
}
|
||||
|
||||
bool panic_memprot_fill_info(panic_info_t *info)
|
||||
{
|
||||
const bool violation_pending = esp_mprot_get_active_intr(&s_memp_intr) == ESP_OK &&
|
||||
s_memp_intr.mem_type != MEMPROT_TYPE_NONE &&
|
||||
s_memp_intr.mem_type != MEMPROT_TYPE_INVALID;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
if (!violation_pending) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
info->reason = "Memory protection fault";
|
||||
info->details = print_memprot_err_details;
|
||||
info->core = violation_pending ? s_memp_intr.core : -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -35,11 +35,13 @@ def configs_for_app(app_path: str, configs: Sequence[str]) -> list[tuple[str, st
|
||||
return [(app_path, config) for config in configs]
|
||||
|
||||
|
||||
def configs_with_esp32s2_xfail(
|
||||
configs: Sequence[tuple[str, str] | tuple[str, str, Any]], reason: str
|
||||
def configs_with_xfail(
|
||||
configs: Sequence[tuple[str, str] | tuple[str, str, Any]],
|
||||
reason: str,
|
||||
targets: Sequence[str] = ('esp32s2',),
|
||||
) -> list[tuple[str, str] | tuple[str, str, Any]]:
|
||||
return [
|
||||
(entry[0], entry[1], pytest.mark.xfail(reason=reason, run=False)) if entry[1] == 'esp32s2' else entry
|
||||
(entry[0], entry[1], pytest.mark.xfail(reason=reason, run=False)) if entry[1] in targets else entry
|
||||
for entry in configs
|
||||
]
|
||||
|
||||
@@ -618,7 +620,8 @@ def test_panic_handler_crash1(dut: PanicTestDut, config: str, test_func_name: st
|
||||
#########################
|
||||
|
||||
# Memprot-related tests are supported only on targets with PMS/PMA peripheral;
|
||||
# currently ESP32-S2, ESP32-C3, ESP32-C2, ESP32-H2, ESP32-H21, ESP32-C6, ESP32-P4, ESP32-C5 and ESP32-C61 are supported
|
||||
# currently ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C2, ESP32-H2, ESP32-H21, ESP32-C6, ESP32-P4,
|
||||
# ESP32-C5, ESP32-C61, ESP32-H4 are supported
|
||||
# ESP32-P4 rev < 3.0 runs on a dedicated rev 1.x runner (its binary is built for
|
||||
# and only boots on rev < 3.0 silicon), so its configs carry the esp32p4_rev1 marker.
|
||||
P4_REV_LESS_THAN_V3_MARKER = pytest.mark.esp32p4_rev1
|
||||
@@ -627,6 +630,7 @@ CONFIGS_MEMPROT_IDRAM = list(
|
||||
zip(
|
||||
[
|
||||
'memprot_esp32s2',
|
||||
'memprot_esp32s3',
|
||||
'memprot_esp32c3',
|
||||
'memprot_esp32c2',
|
||||
'memprot_esp32c5',
|
||||
@@ -639,6 +643,7 @@ CONFIGS_MEMPROT_IDRAM = list(
|
||||
],
|
||||
[
|
||||
'esp32s2',
|
||||
'esp32s3',
|
||||
'esp32c3',
|
||||
'esp32c2',
|
||||
'esp32c5',
|
||||
@@ -662,6 +667,7 @@ CONFIGS_MEMPROT_RTC_FAST_MEM = list(
|
||||
zip(
|
||||
[
|
||||
'memprot_esp32s2',
|
||||
'memprot_esp32s3',
|
||||
'memprot_esp32c3',
|
||||
'memprot_esp32c5',
|
||||
'memprot_esp32c6',
|
||||
@@ -670,7 +676,7 @@ CONFIGS_MEMPROT_RTC_FAST_MEM = list(
|
||||
'memprot_esp32h21',
|
||||
'memprot_esp32s31',
|
||||
],
|
||||
['esp32s2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32h21', 'esp32s31'],
|
||||
['esp32s2', 'esp32s3', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32h21', 'esp32s31'],
|
||||
)
|
||||
) + [
|
||||
('memprot_esp32p4_rev_less_than_v3', 'esp32p4', P4_REV_LESS_THAN_V3_MARKER),
|
||||
@@ -792,6 +798,13 @@ def iram_reg1_write_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
dut.expect(r'Write operation at address [0-9xa-f]+ not permitted \((\S+)\)')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace()
|
||||
elif dut.target == 'esp32s3':
|
||||
dut.expect_gme('Memory protection fault')
|
||||
dut.expect(r' memory type: (\S+)')
|
||||
dut.expect(r' faulting address: [0-9xa-f]+')
|
||||
dut.expect(r' operation type: (\S+)')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace()
|
||||
elif dut.target == 'esp32c3':
|
||||
dut.expect_exact(r'Test error: Test function has returned')
|
||||
else:
|
||||
@@ -824,6 +837,13 @@ def iram_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
dut.expect(r'Write operation at address [0-9xa-f]+ not permitted \((\S+)\)')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace()
|
||||
elif dut.target == 'esp32s3':
|
||||
dut.expect_gme('Memory protection fault')
|
||||
dut.expect(r' memory type: (\S+)')
|
||||
dut.expect(r' faulting address: [0-9xa-f]+')
|
||||
dut.expect(r' operation type: (\S+)')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace()
|
||||
elif dut.target == 'esp32c3':
|
||||
dut.expect_gme('Memory protection fault')
|
||||
dut.expect(r' memory type: (\S+)')
|
||||
@@ -915,10 +935,10 @@ def iram_reg4_write_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners')
|
||||
# TODO: IDF-6820: ESP32-S2 -> Fix incorrect panic reason: Unhandled debug exception
|
||||
# TODO: IDF-6820: ESP32-S2 / ESP32-S3 -> Fix incorrect panic reason: Unhandled debug exception
|
||||
@idf_parametrize(
|
||||
'config,target,markers',
|
||||
configs_with_esp32s2_xfail(CONFIGS_MEMPROT_IDRAM, 'Incorrect panic reason may be observed'),
|
||||
configs_with_xfail(CONFIGS_MEMPROT_IDRAM, 'Incorrect panic reason may be observed', targets=('esp32s2', 'esp32s3')),
|
||||
indirect=['config', 'target'],
|
||||
)
|
||||
def test_iram_reg4_write_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
@@ -940,6 +960,11 @@ def dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
dut.expect(r'Unknown operation at address [0-9xa-f]+ not permitted \((\S+)\)')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace(corrupted=True)
|
||||
elif dut.target == 'esp32s3':
|
||||
dut.expect_gme('Cache error', core=None)
|
||||
dut.expect_exact('MMU entry fault error')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace()
|
||||
else:
|
||||
dut.expect_gme('Instruction access fault')
|
||||
dut.expect_reg_dump(0)
|
||||
@@ -953,7 +978,7 @@ def dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
# TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs
|
||||
@idf_parametrize(
|
||||
'config,target,markers',
|
||||
configs_with_esp32s2_xfail(CONFIGS_MEMPROT_IDRAM, 'Multiple panic reasons for the same test may surface'),
|
||||
configs_with_xfail(CONFIGS_MEMPROT_IDRAM, 'Multiple panic reasons for the same test may surface'),
|
||||
indirect=['config', 'target'],
|
||||
)
|
||||
def test_dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
@@ -974,6 +999,11 @@ def dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
dut.expect_gme('InstructionFetchError')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace(corrupted=True)
|
||||
elif dut.target == 'esp32s3':
|
||||
dut.expect_gme('Cache error', core=None)
|
||||
dut.expect_exact('MMU entry fault error')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace(corrupted=True)
|
||||
else:
|
||||
dut.expect_gme('Instruction access fault')
|
||||
dut.expect_reg_dump(0)
|
||||
@@ -987,7 +1017,7 @@ def dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
# TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs
|
||||
@idf_parametrize(
|
||||
'config,target,markers',
|
||||
configs_with_esp32s2_xfail(CONFIGS_MEMPROT_IDRAM, 'Multiple panic reasons for the same test may surface'),
|
||||
configs_with_xfail(CONFIGS_MEMPROT_IDRAM, 'Multiple panic reasons for the same test may surface'),
|
||||
indirect=['config', 'target'],
|
||||
)
|
||||
def test_dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
@@ -1024,6 +1054,12 @@ def test_rtc_fast_reg2_execute_violation(dut: PanicTestDut, test_func_name: str)
|
||||
dut.expect(r'Read operation at address [0-9xa-f]+ not permitted \((\S+)\)')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace()
|
||||
elif dut.target == 'esp32s3':
|
||||
dut.expect(r' memory type: (\S+)')
|
||||
dut.expect(r' faulting address: [0-9xa-f]+')
|
||||
dut.expect(r' operation type: (\S+)')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace()
|
||||
elif dut.target == 'esp32c3':
|
||||
dut.expect(r' memory type: (\S+)')
|
||||
dut.expect(r' faulting address: [0-9xa-f]+')
|
||||
@@ -1039,7 +1075,7 @@ def test_rtc_fast_reg2_execute_violation(dut: PanicTestDut, test_func_name: str)
|
||||
# TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs
|
||||
@idf_parametrize(
|
||||
'config,target,markers',
|
||||
configs_with_esp32s2_xfail(CONFIGS_MEMPROT_RTC_FAST_MEM, 'Multiple panic reasons for the same test may surface'),
|
||||
configs_with_xfail(CONFIGS_MEMPROT_RTC_FAST_MEM, 'Multiple panic reasons for the same test may surface'),
|
||||
indirect=['config', 'target'],
|
||||
)
|
||||
def test_rtc_fast_reg3_execute_violation(dut: PanicTestDut, test_func_name: str) -> None:
|
||||
@@ -1050,6 +1086,13 @@ def test_rtc_fast_reg3_execute_violation(dut: PanicTestDut, test_func_name: str)
|
||||
dut.expect(r'Unknown operation at address [0-9xa-f]+ not permitted \((\S+)\)')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace()
|
||||
elif dut.target == 'esp32s3':
|
||||
dut.expect_gme('Memory protection fault')
|
||||
dut.expect(r' memory type: (\S+)')
|
||||
dut.expect(r' faulting address: [0-9xa-f]+')
|
||||
dut.expect(r' operation type: (\S+)')
|
||||
dut.expect_reg_dump(0)
|
||||
dut.expect_backtrace()
|
||||
elif dut.target == 'esp32c3':
|
||||
dut.expect_gme('Memory protection fault')
|
||||
dut.expect(r' memory type: (\S+)')
|
||||
|
||||
@@ -104,9 +104,16 @@ class PanicTestDut(IdfDut):
|
||||
result = self.expect(pattern, return_what_before_match=True).decode('utf-8')
|
||||
return result.strip()
|
||||
|
||||
def expect_gme(self, reason: str) -> None:
|
||||
"""Expect method for Guru Meditation Errors"""
|
||||
self.expect_exact(f"Guru Meditation Error: Core 0 panic'ed ({reason})")
|
||||
def expect_gme(self, reason: str, core: int | None = 0) -> None:
|
||||
"""Expect method for Guru Meditation Errors
|
||||
|
||||
Pass core=None to accept any core id, including the -1 reported for
|
||||
faults which cannot be attributed to a single core.
|
||||
"""
|
||||
if core is None:
|
||||
self.expect(rf"Guru Meditation Error: Core\s+\S+ panic'ed \({re.escape(reason)}\)")
|
||||
else:
|
||||
self.expect_exact(f"Guru Meditation Error: Core {core} panic'ed ({reason})")
|
||||
|
||||
def expect_reg_dump(self, core: int | None = None) -> None:
|
||||
if core is None:
|
||||
|
||||
Reference in New Issue
Block a user