forked from espressif/esp-idf
Merge branch 'feat/cache_error_c6_h2' into 'master'
fix(panic): fixed cache error being reported as illegal instruction Closes IDF-6398, IDF-5657, IDF-7015, and IDF-6733 See merge request espressif/esp-idf!27430
This commit is contained in:
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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 <stdbool.h>
|
||||
|
||||
#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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -18,3 +18,5 @@
|
||||
#endif
|
||||
|
||||
#define PANIC_RSN_CACHEERR 3
|
||||
|
||||
#define MCAUSE_ILLEGAL_INSTRUCTION 2
|
||||
|
@@ -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;
|
||||
|
@@ -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')
|
||||
|
Reference in New Issue
Block a user