forked from espressif/esp-idf
feat(cache): supported cache panic on p4
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -20,19 +20,24 @@
|
|||||||
|
|
||||||
static const char *TAG = "CACHE_ERR";
|
static const char *TAG = "CACHE_ERR";
|
||||||
|
|
||||||
//TODO: IDF-7515
|
const char cache_error_msg[] = "Cache access error";
|
||||||
|
|
||||||
const char *esp_cache_err_panic_string(void)
|
const char *esp_cache_err_panic_string(void)
|
||||||
{
|
{
|
||||||
return NULL;
|
uint32_t access_err_status = cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK) | cache_ll_l2_get_access_error_intr_status(0, CACHE_LL_L2_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: IDF-7515
|
|
||||||
bool esp_cache_err_has_active_err(void)
|
bool esp_cache_err_has_active_err(void)
|
||||||
{
|
{
|
||||||
return false;
|
bool has_active_err = cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK) | cache_ll_l2_get_access_error_intr_status(0, CACHE_LL_L2_ACCESS_EVENT_MASK);
|
||||||
|
return has_active_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: IDF-7515
|
|
||||||
void esp_cache_err_int_init(void)
|
void esp_cache_err_int_init(void)
|
||||||
{
|
{
|
||||||
const uint32_t core_id = 0;
|
const uint32_t core_id = 0;
|
||||||
@@ -56,10 +61,13 @@ void esp_cache_err_int_init(void)
|
|||||||
esprv_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
|
esprv_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
|
||||||
|
|
||||||
ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
|
ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
|
||||||
/* On the hardware side, start by clearing all the bits reponsible for cache access error */
|
/* On the hardware side, start by clearing all the bits responsible for cache access error */
|
||||||
cache_ll_l1_clear_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
|
cache_ll_l1_clear_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
|
||||||
|
cache_ll_l2_clear_access_error_intr(0, CACHE_LL_L2_ACCESS_EVENT_MASK);
|
||||||
|
|
||||||
/* Then enable cache access error interrupts. */
|
/* Then enable cache access error interrupts. */
|
||||||
cache_ll_l1_enable_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
|
cache_ll_l1_enable_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
|
||||||
|
cache_ll_l2_enable_access_error_intr(0, CACHE_LL_L2_ACCESS_EVENT_MASK);
|
||||||
|
|
||||||
/* Enable the interrupts for cache error. */
|
/* Enable the interrupts for cache error. */
|
||||||
ESP_INTR_ENABLE(ETS_CACHEERR_INUM);
|
ESP_INTR_ENABLE(ETS_CACHEERR_INUM);
|
||||||
@@ -67,7 +75,11 @@ void esp_cache_err_int_init(void)
|
|||||||
|
|
||||||
int esp_cache_err_get_cpuid(void)
|
int esp_cache_err_get_cpuid(void)
|
||||||
{
|
{
|
||||||
//TODO: IDF-7515
|
if (cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_CORE0_EVENT_MASK)) {
|
||||||
//Should return hart ID according to the cache error
|
return 0;
|
||||||
return 0;
|
} else if (cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_CORE1_EVENT_MASK)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "soc/cache_reg.h"
|
#include "soc/cache_reg.h"
|
||||||
|
#include "soc/cache_struct.h"
|
||||||
#include "soc/ext_mem_defs.h"
|
#include "soc/ext_mem_defs.h"
|
||||||
#include "hal/cache_types.h"
|
#include "hal/cache_types.h"
|
||||||
#include "hal/assert.h"
|
#include "hal/assert.h"
|
||||||
@@ -47,8 +48,10 @@ extern "C" {
|
|||||||
#define CACHE_LL_DEFAULT_IBUS_MASK (CACHE_BUS_IBUS0 | CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2)
|
#define CACHE_LL_DEFAULT_IBUS_MASK (CACHE_BUS_IBUS0 | CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2)
|
||||||
#define CACHE_LL_DEFAULT_DBUS_MASK (CACHE_BUS_DBUS0 | CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)
|
#define CACHE_LL_DEFAULT_DBUS_MASK (CACHE_BUS_DBUS0 | CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)
|
||||||
|
|
||||||
//TODO: IDF-7515
|
#define CACHE_LL_L1_ACCESS_EVENT_MASK (0x1f)
|
||||||
#define CACHE_LL_L1_ACCESS_EVENT_MASK (0x3f)
|
#define CACHE_LL_L2_ACCESS_EVENT_MASK (1<<6)
|
||||||
|
#define CACHE_LL_L1_CORE0_EVENT_MASK (1<<0)
|
||||||
|
#define CACHE_LL_L1_CORE1_EVENT_MASK (1<<1)
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
* Autoload
|
* Autoload
|
||||||
@@ -1019,27 +1022,29 @@ static inline bool cache_ll_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32
|
|||||||
* Interrupt
|
* Interrupt
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* @brief Enable Cache access error interrupt
|
* @brief Enable L1 Cache access error interrupt
|
||||||
*
|
*
|
||||||
* @param cache_id Cache ID
|
* @param cache_id Cache ID
|
||||||
* @param mask Interrupt mask
|
* @param mask Interrupt mask
|
||||||
*/
|
*/
|
||||||
static inline void cache_ll_l1_enable_access_error_intr(uint32_t cache_id, uint32_t mask)
|
static inline void cache_ll_l1_enable_access_error_intr(uint32_t cache_id, uint32_t mask)
|
||||||
{
|
{
|
||||||
|
CACHE.l1_cache_acs_fail_int_ena.val |= mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Clear Cache access error interrupt status
|
* @brief Clear L1 Cache access error interrupt status
|
||||||
*
|
*
|
||||||
* @param cache_id Cache ID
|
* @param cache_id Cache ID
|
||||||
* @param mask Interrupt mask
|
* @param mask Interrupt mask
|
||||||
*/
|
*/
|
||||||
static inline void cache_ll_l1_clear_access_error_intr(uint32_t cache_id, uint32_t mask)
|
static inline void cache_ll_l1_clear_access_error_intr(uint32_t cache_id, uint32_t mask)
|
||||||
{
|
{
|
||||||
|
CACHE.l1_cache_acs_fail_int_clr.val = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get Cache access error interrupt status
|
* @brief Get L1 Cache access error interrupt status
|
||||||
*
|
*
|
||||||
* @param cache_id Cache ID
|
* @param cache_id Cache ID
|
||||||
* @param mask Interrupt mask
|
* @param mask Interrupt mask
|
||||||
@@ -1048,7 +1053,42 @@ static inline void cache_ll_l1_clear_access_error_intr(uint32_t cache_id, uint32
|
|||||||
*/
|
*/
|
||||||
static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_id, uint32_t mask)
|
static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_id, uint32_t mask)
|
||||||
{
|
{
|
||||||
return 0;
|
return CACHE.l1_cache_acs_fail_int_st.val & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable L2 Cache access error interrupt
|
||||||
|
*
|
||||||
|
* @param cache_id Cache ID
|
||||||
|
* @param mask Interrupt mask
|
||||||
|
*/
|
||||||
|
static inline void cache_ll_l2_enable_access_error_intr(uint32_t cache_id, uint32_t mask)
|
||||||
|
{
|
||||||
|
CACHE.l2_cache_acs_fail_int_ena.val |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear L2 Cache access error interrupt status
|
||||||
|
*
|
||||||
|
* @param cache_id Cache ID
|
||||||
|
* @param mask Interrupt mask
|
||||||
|
*/
|
||||||
|
static inline void cache_ll_l2_clear_access_error_intr(uint32_t cache_id, uint32_t mask)
|
||||||
|
{
|
||||||
|
CACHE.l2_cache_acs_fail_int_clr.val = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get L2 Cache access error interrupt status
|
||||||
|
*
|
||||||
|
* @param cache_id Cache ID
|
||||||
|
* @param mask Interrupt mask
|
||||||
|
*
|
||||||
|
* @return Status mask
|
||||||
|
*/
|
||||||
|
static inline uint32_t cache_ll_l2_get_access_error_intr_status(uint32_t cache_id, uint32_t mask)
|
||||||
|
{
|
||||||
|
return CACHE.l2_cache_acs_fail_int_st.val & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -5269,12 +5269,12 @@ typedef union {
|
|||||||
struct {
|
struct {
|
||||||
/** l1_icache0_unalloc_clr : R/W; bitpos: [0]; default: 0;
|
/** l1_icache0_unalloc_clr : R/W; bitpos: [0]; default: 0;
|
||||||
* The bit is used to clear the unallocate request buffer of l1 icache0 where the
|
* The bit is used to clear the unallocate request buffer of l1 icache0 where the
|
||||||
* unallocate request is responsed but not completed.
|
* unallocate request is responded but not completed.
|
||||||
*/
|
*/
|
||||||
uint32_t l1_icache0_unalloc_clr:1;
|
uint32_t l1_icache0_unalloc_clr:1;
|
||||||
/** l1_icache1_unalloc_clr : R/W; bitpos: [1]; default: 0;
|
/** l1_icache1_unalloc_clr : R/W; bitpos: [1]; default: 0;
|
||||||
* The bit is used to clear the unallocate request buffer of l1 icache1 where the
|
* The bit is used to clear the unallocate request buffer of l1 icache1 where the
|
||||||
* unallocate request is responsed but not completed.
|
* unallocate request is responded but not completed.
|
||||||
*/
|
*/
|
||||||
uint32_t l1_icache1_unalloc_clr:1;
|
uint32_t l1_icache1_unalloc_clr:1;
|
||||||
/** l1_icache2_unalloc_clr : HRO; bitpos: [2]; default: 0;
|
/** l1_icache2_unalloc_clr : HRO; bitpos: [2]; default: 0;
|
||||||
@@ -5287,7 +5287,7 @@ typedef union {
|
|||||||
uint32_t l1_icache3_unalloc_clr:1;
|
uint32_t l1_icache3_unalloc_clr:1;
|
||||||
/** l1_dcache_unalloc_clr : R/W; bitpos: [4]; default: 0;
|
/** l1_dcache_unalloc_clr : R/W; bitpos: [4]; default: 0;
|
||||||
* The bit is used to clear the unallocate request buffer of l1 dcache where the
|
* The bit is used to clear the unallocate request buffer of l1 dcache where the
|
||||||
* unallocate request is responsed but not completed.
|
* unallocate request is responded but not completed.
|
||||||
*/
|
*/
|
||||||
uint32_t l1_dcache_unalloc_clr:1;
|
uint32_t l1_dcache_unalloc_clr:1;
|
||||||
uint32_t reserved_5:27;
|
uint32_t reserved_5:27;
|
||||||
@@ -5303,7 +5303,7 @@ typedef union {
|
|||||||
uint32_t reserved_0:5;
|
uint32_t reserved_0:5;
|
||||||
/** l2_cache_unalloc_clr : R/W; bitpos: [5]; default: 0;
|
/** l2_cache_unalloc_clr : R/W; bitpos: [5]; default: 0;
|
||||||
* The bit is used to clear the unallocate request buffer of l2 icache where the
|
* The bit is used to clear the unallocate request buffer of l2 icache where the
|
||||||
* unallocate request is responsed but not completed.
|
* unallocate request is responded but not completed.
|
||||||
*/
|
*/
|
||||||
uint32_t l2_cache_unalloc_clr:1;
|
uint32_t l2_cache_unalloc_clr:1;
|
||||||
uint32_t reserved_6:26;
|
uint32_t reserved_6:26;
|
||||||
@@ -5548,7 +5548,7 @@ typedef union {
|
|||||||
} cache_date_reg_t;
|
} cache_date_reg_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct cache_dev_t {
|
||||||
volatile cache_l1_icache_ctrl_reg_t l1_icache_ctrl;
|
volatile cache_l1_icache_ctrl_reg_t l1_icache_ctrl;
|
||||||
volatile cache_l1_dcache_ctrl_reg_t l1_dcache_ctrl;
|
volatile cache_l1_dcache_ctrl_reg_t l1_dcache_ctrl;
|
||||||
volatile cache_l1_bypass_cache_conf_reg_t l1_bypass_cache_conf;
|
volatile cache_l1_bypass_cache_conf_reg_t l1_bypass_cache_conf;
|
||||||
@@ -5799,6 +5799,7 @@ typedef struct {
|
|||||||
volatile cache_date_reg_t date;
|
volatile cache_date_reg_t date;
|
||||||
} cache_dev_t;
|
} cache_dev_t;
|
||||||
|
|
||||||
|
extern cache_dev_t CACHE;
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
_Static_assert(sizeof(cache_dev_t) == 0x400, "Invalid size of cache_dev_t structure");
|
_Static_assert(sizeof(cache_dev_t) == 0x400, "Invalid size of cache_dev_t structure");
|
||||||
|
@@ -120,3 +120,5 @@ PROVIDE ( USB_UTMI = 0x5009C000 );
|
|||||||
|
|
||||||
PROVIDE ( EMAC_MAC = 0x50098000 );
|
PROVIDE ( EMAC_MAC = 0x50098000 );
|
||||||
PROVIDE ( EMAC_DMA = 0x50099000 );
|
PROVIDE ( EMAC_DMA = 0x50099000 );
|
||||||
|
|
||||||
|
PROVIDE ( CACHE = 0x3FF10000);
|
||||||
|
@@ -267,14 +267,12 @@ def test_cache_error(dut: PanicTestDut, config: str, test_func_name: str) -> Non
|
|||||||
if dut.target in ['esp32c3', 'esp32c2']:
|
if dut.target in ['esp32c3', 'esp32c2']:
|
||||||
dut.expect_gme('Cache error')
|
dut.expect_gme('Cache error')
|
||||||
dut.expect_exact('Cached memory region accessed while ibus or cache is disabled')
|
dut.expect_exact('Cached memory region accessed while ibus or cache is disabled')
|
||||||
elif dut.target in ['esp32c6', 'esp32h2']:
|
elif dut.target in ['esp32c6', 'esp32h2', 'esp32p4']:
|
||||||
dut.expect_gme('Cache error')
|
dut.expect_gme('Cache error')
|
||||||
dut.expect_exact('Cache access error')
|
dut.expect_exact('Cache access error')
|
||||||
elif dut.target in ['esp32s2']:
|
elif dut.target in ['esp32s2']:
|
||||||
# Cache error interrupt is not enabled, IDF-1558
|
# Cache error interrupt is not enabled, IDF-1558
|
||||||
dut.expect_gme('IllegalInstruction')
|
dut.expect_gme('IllegalInstruction')
|
||||||
elif dut.target in ['esp32p4']: # TODO IDF-7515
|
|
||||||
dut.expect_gme('Instruction access fault')
|
|
||||||
else:
|
else:
|
||||||
dut.expect_gme('Cache disabled but cached memory region accessed')
|
dut.expect_gme('Cache disabled but cached memory region accessed')
|
||||||
dut.expect_reg_dump(0)
|
dut.expect_reg_dump(0)
|
||||||
|
Reference in New Issue
Block a user