diff --git a/components/esp_system/include/esp_private/panic_internal.h b/components/esp_system/include/esp_private/panic_internal.h index 9d35c7524d..203643d069 100644 --- a/components/esp_system/include/esp_private/panic_internal.h +++ b/components/esp_system/include/esp_private/panic_internal.h @@ -75,6 +75,8 @@ void panic_arch_fill_info(void *frame, panic_info_t *info); void panic_soc_fill_info(void *frame, panic_info_t *info); +bool panic_soc_check_pseudo_cause(void *f, panic_info_t *info); + void panic_print_registers(const void *frame, int core); void panic_print_backtrace(const void *frame, int core); diff --git a/components/esp_system/linker.lf b/components/esp_system/linker.lf index e30a7fccec..f512f550a9 100644 --- a/components/esp_system/linker.lf +++ b/components/esp_system/linker.lf @@ -5,7 +5,7 @@ entries: panic (noflash) panic_handler (noflash) panic_arch (noflash) - cache_err_int:esp_cache_err_get_cpuid (noflash) + cache_err_int (noflash) reset_reason:esp_reset_reason_get_hint (noflash) if ESP_SYSTEM_HW_STACK_GUARD = y: hw_stack_guard:esp_hw_stack_guard_get_bounds (noflash) diff --git a/components/esp_system/port/arch/riscv/panic_arch.c b/components/esp_system/port/arch/riscv/panic_arch.c index ce8fe05148..a4f64dbdc7 100644 --- a/components/esp_system/port/arch/riscv/panic_arch.c +++ b/components/esp_system/port/arch/riscv/panic_arch.c @@ -41,124 +41,20 @@ #define DIM(array) (sizeof(array)/sizeof(*array)) -/** - * Structure used to define a flag/bit to test in case of cache error. - * The message describes the cause of the error when the bit is set in - * a given status register. - */ -typedef struct { - const uint32_t bit; - const char *msg; -} register_bit_t; - -/** - * Function to check each bits defined in the array reg_bits in the given - * status register. The first bit from the array to be set in the status - * register will have its associated message printed. This function returns - * true. If not bit was set in the register, it returns false. - * The order of the bits in the array is important as only the first bit to - * be set in the register will have its associated message printed. - */ -static inline bool test_and_print_register_bits(const uint32_t status, - const register_bit_t *reg_bits, - const uint32_t size) -{ - /* Browse the flag/bit array and test each one with the given status - * register. */ - for (int i = 0; i < size; i++) { - const uint32_t bit = reg_bits[i].bit; - if ((status & bit) == bit) { - /* Reason of the panic found, print the reason. */ - panic_print_str(reg_bits[i].msg); - panic_print_str("\r\n"); - - return true; - } - } - - /* Panic cause not found, no message was printed. */ - return false; -} - /** * Function called when a cache error occurs. It prints details such as the * explanation of why the panic occured. */ static inline void print_cache_err_details(const void *frame) { -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 // ESP32P4-TODO, ESP32C6-TODO, ESP32H2-TODO: IDF-5657 - /* Define the array that contains the status (bits) to test on the register - * EXTMEM_CORE0_ACS_CACHE_INT_ST_REG. each bit is accompanied by a small - * message. - * The messages have been pulled from the header file where the status bit - * are defined. */ - const register_bit_t core0_acs_bits[] = { - { - .bit = EXTMEM_CORE0_DBUS_WR_ICACHE_ST, - .msg = "dbus tried to write cache" - }, - { - .bit = EXTMEM_CORE0_DBUS_REJECT_ST, - .msg = "dbus authentication failed" - }, - { - .bit = EXTMEM_CORE0_DBUS_ACS_MSK_ICACHE_ST, - .msg = "access to cache while dbus or cache is disabled" - }, - { - .bit = EXTMEM_CORE0_IBUS_REJECT_ST, - .msg = "ibus authentication failed" - }, - { - .bit = EXTMEM_CORE0_IBUS_WR_ICACHE_ST, - .msg = "ibus tried to write cache" - }, - { - .bit = EXTMEM_CORE0_IBUS_ACS_MSK_ICACHE_ST, - .msg = "access to cache while ibus or cache is disabled" - }, - }; - - /* Same goes for the register EXTMEM_CACHE_ILG_INT_ST_REG and its bits. */ - const register_bit_t cache_ilg_bits[] = { - { - .bit = EXTMEM_MMU_ENTRY_FAULT_ST, - .msg = "MMU entry fault" - }, - { - .bit = EXTMEM_ICACHE_PRELOAD_OP_FAULT_ST, - .msg = "preload configurations fault" - }, - { - .bit = EXTMEM_ICACHE_SYNC_OP_FAULT_ST, - .msg = "sync configurations fault" - }, - }; - - /* Read the status register EXTMEM_CORE0_ACS_CACHE_INT_ST_REG. This status - * register is not equal to 0 when a cache access error occured. */ - const uint32_t core0_status = REG_READ(EXTMEM_CORE0_ACS_CACHE_INT_ST_REG); - - /* If the panic is due to a cache access error, one of the bit of the - * register is set. Thus, this function will return true. */ - bool handled = test_and_print_register_bits(core0_status, core0_acs_bits, DIM(core0_acs_bits)); - - /* If the panic was due to a cache illegal error, the previous call returned false and this - * EXTMEM_CACHE_ILG_INT_ST_REG register should not me equal to 0. - * Check each bit of it and print the message associated if found. */ - if (!handled) { - const uint32_t cache_ilg_status = REG_READ(EXTMEM_CACHE_ILG_INT_ST_REG); - handled = test_and_print_register_bits(cache_ilg_status, cache_ilg_bits, DIM(cache_ilg_bits)); - - /* If the error was not found, print the both registers value */ - if (!handled) { - panic_print_str("EXTMEM_CORE0_ACS_CACHE_INT_ST_REG = 0x"); - panic_print_hex(core0_status); - panic_print_str("\r\nEXTMEM_CACHE_ILG_INT_ST_REG = 0x"); - panic_print_hex(cache_ilg_status); - panic_print_str("\r\n"); - } +#if !CONFIG_IDF_TARGET_ESP32P4 + const char* cache_err_msg = esp_cache_err_panic_string(); + if (cache_err_msg) { + panic_print_str(cache_err_msg); + } else { + panic_print_str("Cache error active, but failed to find a corresponding error message"); } + panic_print_str("\r\n"); #endif } @@ -294,6 +190,27 @@ void panic_print_registers(const void *f, int core) panic_print_register_array(desc, f, DIM(desc)); } +/** + * This function will be called before the SoC-level panic is handled, + * allowing us to check and override the exception cause for certain + * pseudo-causes that do not have their own trigger + */ +bool panic_soc_check_pseudo_cause(void *f, panic_info_t *info) +{ + RvExcFrame *frame = (RvExcFrame *) f; + bool pseudo_cause = false; + + /* Cache errors when reading instructions will result in an illegal instructions, + before any cache error interrupts trigger. We override the exception cause if + any cache errors are active to more accurately report the actual reason */ + if(esp_cache_err_has_active_err() && (frame->mcause == MCAUSE_ILLEGAL_INSTRUCTION) ) { + pseudo_cause = true; + frame->mcause = ETS_CACHEERR_INUM; + } + + return pseudo_cause; +} + /** * This function will be called when a SoC-level panic occurs. * SoC-level panics include cache errors and watchdog interrupts. diff --git a/components/esp_system/port/arch/xtensa/panic_arch.c b/components/esp_system/port/arch/xtensa/panic_arch.c index a2f4addb96..2e66fa1280 100644 --- a/components/esp_system/port/arch/xtensa/panic_arch.c +++ b/components/esp_system/port/arch/xtensa/panic_arch.c @@ -392,6 +392,17 @@ void panic_arch_fill_info(void *f, panic_info_t *info) info->addr = ((void *) ((XtExcFrame *) frame)->pc); } +/** + * This function will be called before the SoC-level panic is handled, + * allowing us to check and override the exception cause for certain + * pseudo-causes that do not have their own trigger + */ +bool panic_soc_check_pseudo_cause(void *f, panic_info_t *info) +{ + // Currently only needed on riscv targets + return false; +} + void panic_soc_fill_info(void *f, panic_info_t *info) { // [refactor-todo] this should be in the common port panic_handler.c, once diff --git a/components/esp_system/port/include/private/esp_private/cache_err_int.h b/components/esp_system/port/include/private/esp_private/cache_err_int.h index 22e1c3ec7c..c070179a5f 100644 --- a/components/esp_system/port/include/private/esp_private/cache_err_int.h +++ b/components/esp_system/port/include/private/esp_private/cache_err_int.h @@ -1,15 +1,18 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once +#include + #ifdef __cplusplus extern "C" { #endif + /** * @brief initialize cache invalid access interrupt * @@ -32,6 +35,22 @@ void esp_cache_err_int_init(void); */ int esp_cache_err_get_cpuid(void); + +/** + * @brief Returns a pointer to the cache error message + * + * @return const char* Pointer to the error message + */ +const char *esp_cache_err_panic_string(void); + +/** + * @brief Checks if any cache errors are active + * + * @return true + * @return false + */ +bool esp_cache_err_has_active_err(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_system/port/panic_handler.c b/components/esp_system/port/panic_handler.c index a936a01b4e..a8ccce4a8c 100644 --- a/components/esp_system/port/panic_handler.c +++ b/components/esp_system/port/panic_handler.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -104,9 +104,10 @@ static void frame_to_panic_info(void *frame, panic_info_t *info, bool pseudo_exc info->exception = PANIC_EXCEPTION_FAULT; info->details = NULL; info->reason = "Unknown"; - info->pseudo_excause = pseudo_excause; - if (pseudo_excause) { + info->pseudo_excause = panic_soc_check_pseudo_cause(frame, info) | pseudo_excause; + + if (info->pseudo_excause) { panic_soc_fill_info(frame, info); } else { panic_arch_fill_info(frame, info); diff --git a/components/esp_system/port/soc/esp32c2/cache_err_int.c b/components/esp_system/port/soc/esp32c2/cache_err_int.c index 4f241e021d..8215353313 100644 --- a/components/esp_system/port/soc/esp32c2/cache_err_int.c +++ b/components/esp_system/port/soc/esp32c2/cache_err_int.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,119 @@ static const char *TAG = "CACHE_ERR"; + +#define DIM(array) (sizeof(array)/sizeof(*array)) + +/** + * Structure used to define a flag/bit to test in case of cache error. + * The message describes the cause of the error when the bit is set in + * a given status register. + */ +typedef struct { + const uint32_t bit; + const char *msg; +} register_bit_t; + +/* Define the array that contains the status (bits) to test on the register + * EXTMEM_CORE0_ACS_CACHE_INT_ST_REG. each bit is accompanied by a small + * message. + * The messages have been pulled from the header file where the status bit + * are defined. */ +const register_bit_t core0_acs_bits[] = { + { + .bit = EXTMEM_CORE0_DBUS_WR_ICACHE_ST, + .msg = "Dbus tried to write cache" + }, + { + .bit = EXTMEM_CORE0_DBUS_REJECT_ST, + .msg = "Dbus authentication failed" + }, + { + .bit = EXTMEM_CORE0_DBUS_ACS_MSK_ICACHE_ST, + .msg = "Cached memory region accessed while dbus or cache is disabled" + }, + { + .bit = EXTMEM_CORE0_IBUS_REJECT_ST, + .msg = "Ibus authentication failed" + }, + { + .bit = EXTMEM_CORE0_IBUS_WR_ICACHE_ST, + .msg = "Ibus tried to write cache" + }, + { + .bit = EXTMEM_CORE0_IBUS_ACS_MSK_ICACHE_ST, + .msg = "Cached memory region accessed while ibus or cache is disabled" + }, +}; + +/* Same goes for the register EXTMEM_CACHE_ILG_INT_ST_REG and its bits. */ +const register_bit_t cache_ilg_bits[] = { + { + .bit = EXTMEM_MMU_ENTRY_FAULT_ST, + .msg = "MMU entry fault" + }, + { + .bit = EXTMEM_ICACHE_PRELOAD_OP_FAULT_ST, + .msg = "Preload configurations fault" + }, + { + .bit = EXTMEM_ICACHE_SYNC_OP_FAULT_ST, + .msg = "Sync configurations fault" + }, +}; + +/** + * Function to check each bits defined in the array reg_bits in the given + * status register. The first bit from the array to be set in the status + * register will have its associated message printed. This function returns + * true. If not bit was set in the register, it returns false. + * The order of the bits in the array is important as only the first bit to + * be set in the register will have its associated message printed. + */ +static inline const char* test_and_print_register_bits(const uint32_t status, + const register_bit_t *reg_bits, + const uint32_t size) +{ + /* Browse the flag/bit array and test each one with the given status + * register. */ + for (int i = 0; i < size; i++) { + const uint32_t bit = reg_bits[i].bit; + if ((status & bit) == bit) { + /* Reason of the panic found, print the reason. */ + return reg_bits[i].msg; + } + } + + /* Panic cause not found, no message was printed. */ + return NULL; +} + +const char *esp_cache_err_panic_string(void) +{ + /* Read the status register EXTMEM_CORE0_ACS_CACHE_INT_ST_REG. This status + * register is not equal to 0 when a cache access error occured. */ + const uint32_t access_err_status = cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK); + + /* If the panic is due to a cache access error, one of the bit of the + * register is set. Thus, this function will return an error string. */ + const char* err_str = test_and_print_register_bits(access_err_status, core0_acs_bits, DIM(core0_acs_bits)); + + /* If the panic was due to a cache illegal error, the previous call returned NULL and this + * EXTMEM_CACHE_ILG_INT_ST_REG register should not be equal to 0. + * Check each bit of it and print the message associated if found. */ + if (err_str == NULL) { + const uint32_t cache_ilg_status = cache_ll_l1_get_illegal_error_intr_status(0, CACHE_LL_L1_ILG_EVENT_MASK); + err_str = test_and_print_register_bits(cache_ilg_status, cache_ilg_bits, DIM(cache_ilg_bits)); + } + + return err_str; +} + +bool esp_cache_err_has_active_err(void) +{ + return cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK) || cache_ll_l1_get_illegal_error_intr_status(0, CACHE_LL_L1_ILG_EVENT_MASK); +} + void esp_cache_err_int_init(void) { const uint32_t core_id = 0; diff --git a/components/esp_system/port/soc/esp32c3/cache_err_int.c b/components/esp_system/port/soc/esp32c3/cache_err_int.c index 05b5d6773c..28f9877cd2 100644 --- a/components/esp_system/port/soc/esp32c3/cache_err_int.c +++ b/components/esp_system/port/soc/esp32c3/cache_err_int.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,118 @@ static const char *TAG = "CACHE_ERR"; +#define DIM(array) (sizeof(array)/sizeof(*array)) + +/** + * Structure used to define a flag/bit to test in case of cache error. + * The message describes the cause of the error when the bit is set in + * a given status register. + */ +typedef struct { + const uint32_t bit; + const char *msg; +} register_bit_t; + +/* Define the array that contains the status (bits) to test on the register + * EXTMEM_CORE0_ACS_CACHE_INT_ST_REG. each bit is accompanied by a small + * message. + * The messages have been pulled from the header file where the status bit + * are defined. */ +const register_bit_t core0_acs_bits[] = { + { + .bit = EXTMEM_CORE0_DBUS_WR_ICACHE_ST, + .msg = "Dbus tried to write cache" + }, + { + .bit = EXTMEM_CORE0_DBUS_REJECT_ST, + .msg = "Dbus authentication failed" + }, + { + .bit = EXTMEM_CORE0_DBUS_ACS_MSK_ICACHE_ST, + .msg = "Cached memory region accessed while dbus or cache is disabled" + }, + { + .bit = EXTMEM_CORE0_IBUS_REJECT_ST, + .msg = "Ibus authentication failed" + }, + { + .bit = EXTMEM_CORE0_IBUS_WR_ICACHE_ST, + .msg = "Ibus tried to write cache" + }, + { + .bit = EXTMEM_CORE0_IBUS_ACS_MSK_ICACHE_ST, + .msg = "Cached memory region accessed while ibus or cache is disabled" + }, +}; + +/* Same goes for the register EXTMEM_CACHE_ILG_INT_ST_REG and its bits. */ +const register_bit_t cache_ilg_bits[] = { + { + .bit = EXTMEM_MMU_ENTRY_FAULT_ST, + .msg = "MMU entry fault" + }, + { + .bit = EXTMEM_ICACHE_PRELOAD_OP_FAULT_ST, + .msg = "Preload configurations fault" + }, + { + .bit = EXTMEM_ICACHE_SYNC_OP_FAULT_ST, + .msg = "Sync configurations fault" + }, +}; + +/** + * Function to check each bits defined in the array reg_bits in the given + * status register. The first bit from the array to be set in the status + * register will have its associated message printed. This function returns + * true. If not bit was set in the register, it returns false. + * The order of the bits in the array is important as only the first bit to + * be set in the register will have its associated message printed. + */ +static inline const char* test_and_print_register_bits(const uint32_t status, + const register_bit_t *reg_bits, + const uint32_t size) +{ + /* Browse the flag/bit array and test each one with the given status + * register. */ + for (int i = 0; i < size; i++) { + const uint32_t bit = reg_bits[i].bit; + if ((status & bit) == bit) { + /* Reason of the panic found, print the reason. */ + return reg_bits[i].msg; + } + } + + /* Panic cause not found, no message was printed. */ + return NULL; +} + +const char *esp_cache_err_panic_string(void) +{ + /* Read the status register EXTMEM_CORE0_ACS_CACHE_INT_ST_REG. This status + * register is not equal to 0 when a cache access error occured. */ + const uint32_t access_err_status = cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK); + + /* If the panic is due to a cache access error, one of the bit of the + * register is set. Thus, this function will return an error string. */ + const char* err_str = test_and_print_register_bits(access_err_status, core0_acs_bits, DIM(core0_acs_bits)); + + /* If the panic was due to a cache illegal error, the previous call returned NULL and this + * EXTMEM_CACHE_ILG_INT_ST_REG register should not be equal to 0. + * Check each bit of it and return the message associated if found. */ + if (err_str == NULL) { + const uint32_t cache_ilg_status = cache_ll_l1_get_illegal_error_intr_status(0, CACHE_LL_L1_ILG_EVENT_MASK); + err_str = test_and_print_register_bits(cache_ilg_status, cache_ilg_bits, DIM(cache_ilg_bits)); + } + + return err_str; +} + +bool esp_cache_err_has_active_err(void) +{ + return cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK) || cache_ll_l1_get_illegal_error_intr_status(0, CACHE_LL_L1_ILG_EVENT_MASK); +} + void esp_cache_err_int_init(void) { const uint32_t core_id = 0; diff --git a/components/esp_system/port/soc/esp32c6/cache_err_int.c b/components/esp_system/port/soc/esp32c6/cache_err_int.c index 82cf3895e4..7f4eda7112 100644 --- a/components/esp_system/port/soc/esp32c6/cache_err_int.c +++ b/components/esp_system/port/soc/esp32c6/cache_err_int.c @@ -20,6 +20,24 @@ static const char *TAG = "CACHE_ERR"; + +const char cache_error_msg[] = "Cache access error"; + +const char *esp_cache_err_panic_string(void) +{ + const uint32_t access_err_status = cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK); + + /* Return the error string if a cache error is active */ + const char* err_str = access_err_status ? cache_error_msg : NULL; + + return err_str; +} + +bool esp_cache_err_has_active_err(void) +{ + return cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK); +} + void esp_cache_err_int_init(void) { const uint32_t core_id = 0; diff --git a/components/esp_system/port/soc/esp32h2/cache_err_int.c b/components/esp_system/port/soc/esp32h2/cache_err_int.c index 1997f547da..e989d69ce0 100644 --- a/components/esp_system/port/soc/esp32h2/cache_err_int.c +++ b/components/esp_system/port/soc/esp32h2/cache_err_int.c @@ -20,6 +20,23 @@ static const char *TAG = "CACHE_ERR"; +const char cache_error_msg[] = "Cache access error"; + +const char *esp_cache_err_panic_string(void) +{ + const uint32_t access_err_status = cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK); + + /* Return the error string if a cache error is active */ + const char* err_str = access_err_status ? cache_error_msg : NULL; + + return err_str; +} + +bool esp_cache_err_has_active_err(void) +{ + return cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK); +} + void esp_cache_err_int_init(void) { const uint32_t core_id = 0; diff --git a/components/esp_system/port/soc/esp32p4/cache_err_int.c b/components/esp_system/port/soc/esp32p4/cache_err_int.c index db57614bb1..5024e47083 100644 --- a/components/esp_system/port/soc/esp32p4/cache_err_int.c +++ b/components/esp_system/port/soc/esp32p4/cache_err_int.c @@ -20,6 +20,18 @@ static const char *TAG = "CACHE_ERR"; +//TODO: IDF-7515 +const char *esp_cache_err_panic_string(void) +{ + return NULL; +} + +//TODO: IDF-7515 +bool esp_cache_err_has_active_err(void) +{ + return false; +} + //TODO: IDF-7515 void esp_cache_err_int_init(void) { diff --git a/components/riscv/include/esp_private/panic_reason.h b/components/riscv/include/esp_private/panic_reason.h index a89f5708f7..252f6de9c0 100644 --- a/components/riscv/include/esp_private/panic_reason.h +++ b/components/riscv/include/esp_private/panic_reason.h @@ -18,3 +18,5 @@ #endif #define PANIC_RSN_CACHEERR 3 + +#define MCAUSE_ILLEGAL_INSTRUCTION 2 diff --git a/tools/test_apps/system/memprot/main/esp32c3/test_panic.c b/tools/test_apps/system/memprot/main/esp32c3/test_panic.c index f75450ef2c..cd28a8b212 100644 --- a/tools/test_apps/system/memprot/main/esp32c3/test_panic.c +++ b/tools/test_apps/system/memprot/main/esp32c3/test_panic.c @@ -6,8 +6,8 @@ #include "riscv/rvruntime-frames.h" #include "esp_private/panic_internal.h" +#include "esp_private/panic_reason.h" -#define MCAUSE_ILLEGAL_INSTRUCTION 2 extern void esp_panic_handler(panic_info_t *info); volatile bool g_override_illegal_instruction = false; diff --git a/tools/test_apps/system/panic/pytest_panic.py b/tools/test_apps/system/panic/pytest_panic.py index 1d00a6b59c..2e24df2d97 100644 --- a/tools/test_apps/system/panic/pytest_panic.py +++ b/tools/test_apps/system/panic/pytest_panic.py @@ -277,9 +277,12 @@ def test_int_wdt_cache_disabled( @pytest.mark.generic def test_cache_error(dut: PanicTestDut, config: str, test_func_name: str) -> None: dut.run_test_func(test_func_name) - if dut.target in ['esp32c3', 'esp32c2', 'esp32c6', 'esp32h2']: - # Cache error interrupt is not raised, IDF-6398 - dut.expect_gme('Illegal instruction') + if dut.target in ['esp32c3', 'esp32c2']: + dut.expect_gme('Cache error') + dut.expect_exact('Cached memory region accessed while ibus or cache is disabled') + elif dut.target in ['esp32c6', 'esp32h2']: + dut.expect_gme('Cache error') + dut.expect_exact('Cache access error') elif dut.target in ['esp32s2']: # Cache error interrupt is not enabled, IDF-1558 dut.expect_gme('IllegalInstruction')