kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'feature/esp32p4-coredump-support' into 'master'
esp32p4: panic tests support Closes IDF-7565, IDF-7861, IDF-9035, and IDF-9075 See merge request espressif/esp-idf!28586pull/13473/head
commit
0e3673a2bd
|
@ -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
|
||||
*/
|
||||
|
@ -15,15 +15,20 @@ ESP_SYSTEM_INIT_FN(esp_hw_stack_guard_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES
|
|||
{
|
||||
uint32_t core_id = esp_cpu_get_core_id();
|
||||
|
||||
if (core_id == 0) {
|
||||
/* initialize the peripheral only when running on core 0 */
|
||||
periph_module_enable(PERIPH_ASSIST_DEBUG_MODULE);
|
||||
periph_module_reset(PERIPH_ASSIST_DEBUG_MODULE);
|
||||
ESP_INTR_DISABLE(ETS_ASSIST_DEBUG_INUM);
|
||||
|
||||
#if SOC_CPU_CORES_NUM > 1
|
||||
PERIPH_RCC_ATOMIC()
|
||||
#endif
|
||||
{
|
||||
assist_debug_ll_enable_bus_clock(true);
|
||||
assist_debug_ll_reset_register();
|
||||
}
|
||||
|
||||
/* just in case, disable the interrupt and clear pending status */
|
||||
assist_debug_hal_sp_int_disable(core_id);
|
||||
assist_debug_hal_sp_int_clear(core_id);
|
||||
/* set interrupt to matrix */
|
||||
esp_rom_route_intr_matrix(core_id, ETS_ASSIST_DEBUG_INTR_SOURCE, ETS_ASSIST_DEBUG_INUM);
|
||||
esprv_int_set_type(ETS_ASSIST_DEBUG_INUM, INTR_TYPE_LEVEL);
|
||||
esprv_int_set_priority(ETS_ASSIST_DEBUG_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
|
||||
|
||||
/*
|
||||
* enable interrupt
|
||||
|
@ -37,12 +42,6 @@ ESP_SYSTEM_INIT_FN(esp_hw_stack_guard_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES
|
|||
*/
|
||||
assist_debug_hal_sp_int_enable(core_id);
|
||||
|
||||
/* enable interrup routine */
|
||||
esp_rom_route_intr_matrix(core_id, ETS_ASSIST_DEBUG_INTR_SOURCE, ETS_ASSIST_DEBUG_INUM);
|
||||
|
||||
esprv_int_set_type(ETS_ASSIST_DEBUG_INUM, INTR_TYPE_LEVEL);
|
||||
esprv_int_set_priority(ETS_ASSIST_DEBUG_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
|
||||
|
||||
ESP_INTR_ENABLE(ETS_ASSIST_DEBUG_INUM);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -72,23 +71,22 @@ void esp_hw_stack_guard_set_bounds(uint32_t sp_min, uint32_t sp_max)
|
|||
assist_debug_hal_set_sp_bounds(core_id, sp_min, sp_max);
|
||||
}
|
||||
|
||||
void esp_hw_stack_guard_get_bounds(uint32_t *sp_min, uint32_t *sp_max)
|
||||
void esp_hw_stack_guard_get_bounds(uint32_t core_id, uint32_t *sp_min, uint32_t *sp_max)
|
||||
{
|
||||
uint32_t core_id = esp_cpu_get_core_id();
|
||||
|
||||
assist_debug_hal_get_sp_bounds(core_id, sp_min, sp_max);
|
||||
}
|
||||
|
||||
bool esp_hw_stack_guard_is_fired(void)
|
||||
uint32_t esp_hw_stack_guard_get_fired_cpu(void)
|
||||
{
|
||||
uint32_t core_id = esp_cpu_get_core_id();
|
||||
|
||||
return assist_debug_hal_is_sp_ovf_fired(core_id);
|
||||
for (uint32_t i = 0; i < SOC_CPU_CORES_NUM; i++) {
|
||||
if (assist_debug_hal_is_sp_ovf_fired(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return ESP_HW_STACK_GUARD_NOT_FIRED;
|
||||
}
|
||||
|
||||
uint32_t esp_hw_stack_guard_get_pc(void)
|
||||
uint32_t esp_hw_stack_guard_get_pc(uint32_t core_id)
|
||||
{
|
||||
uint32_t core_id = esp_cpu_get_core_id();
|
||||
|
||||
return assist_debug_hal_get_sp_ovf_pc(core_id);
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ SECTIONS
|
|||
|
||||
.dram0.data :
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
_data_start_low = ABSOLUTE(.);
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
__global_pointer$ = . + 0x800;
|
||||
|
@ -230,9 +230,18 @@ SECTIONS
|
|||
arrays[dram0_data]
|
||||
mapping[dram0_data]
|
||||
|
||||
_data_end = ABSOLUTE(.);
|
||||
_data_end_low = ABSOLUTE(.);
|
||||
} > sram_low
|
||||
|
||||
.dram1.data :
|
||||
{
|
||||
_data_start_high = ABSOLUTE(.);
|
||||
|
||||
mapping[dram0_data]
|
||||
|
||||
_data_end_high = ABSOLUTE(.);
|
||||
} > sram_high
|
||||
|
||||
/**
|
||||
* This section holds data that should not be initialized at power up.
|
||||
* The section located in Internal SRAM memory region. The macro _NOINIT
|
||||
|
|
|
@ -9,7 +9,7 @@ entries:
|
|||
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)
|
||||
hw_stack_guard:esp_hw_stack_guard_is_fired (noflash)
|
||||
hw_stack_guard:esp_hw_stack_guard_get_fired_cpu (noflash)
|
||||
hw_stack_guard:esp_hw_stack_guard_get_pc (noflash)
|
||||
|
||||
esp_err (noflash)
|
||||
|
|
|
@ -55,20 +55,21 @@ static inline void print_cache_err_details(const void *frame)
|
|||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
static inline void print_assist_debug_details(const void *frame)
|
||||
{
|
||||
uint32_t core_id = esp_cpu_get_core_id();
|
||||
uint32_t core_id = esp_hw_stack_guard_get_fired_cpu();
|
||||
if (core_id == ESP_HW_STACK_GUARD_NOT_FIRED) {
|
||||
panic_print_str("ASSIST_DEBUG is not triggered BUT interrupt occured!\r\n\r\n");
|
||||
core_id = 0;
|
||||
}
|
||||
uint32_t sp_min, sp_max;
|
||||
const char *task_name = pcTaskGetName(xTaskGetCurrentTaskHandleForCore(core_id));
|
||||
esp_hw_stack_guard_get_bounds(&sp_min, &sp_max);
|
||||
esp_hw_stack_guard_get_bounds(core_id, &sp_min, &sp_max);
|
||||
|
||||
panic_print_str("\r\n");
|
||||
if (!esp_hw_stack_guard_is_fired()) {
|
||||
panic_print_str("ASSIST_DEBUG is not triggered BUT interrupt occured!\r\n\r\n");
|
||||
}
|
||||
|
||||
panic_print_str("Detected in task \"");
|
||||
panic_print_str(task_name);
|
||||
panic_print_str("\" at 0x");
|
||||
panic_print_hex((int) esp_hw_stack_guard_get_pc());
|
||||
panic_print_hex((int) esp_hw_stack_guard_get_pc(core_id));
|
||||
panic_print_str("\r\n");
|
||||
panic_print_str("Stack pointer: 0x");
|
||||
panic_print_hex((int)((RvExcFrame *)frame)->sp);
|
||||
|
@ -245,7 +246,10 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
|
|||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
else if (frame->mcause == ETS_ASSIST_DEBUG_INUM) {
|
||||
info->core = esp_cache_err_get_cpuid();
|
||||
info->core = esp_hw_stack_guard_get_fired_cpu();
|
||||
if (info->core == ESP_HW_STACK_GUARD_NOT_FIRED) {
|
||||
info->core = 0;
|
||||
}
|
||||
info->reason = "Stack protection fault";
|
||||
info->details = print_assist_debug_details;
|
||||
}
|
||||
|
|
|
@ -14,15 +14,17 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_HW_STACK_GUARD_NOT_FIRED UINT32_MAX
|
||||
|
||||
/* The functions below are designed to be used in interrupt/panic handler
|
||||
* In case using them in user's code put them into critical section.*/
|
||||
|
||||
void esp_hw_stack_guard_monitor_start(void);
|
||||
void esp_hw_stack_guard_monitor_stop(void);
|
||||
void esp_hw_stack_guard_set_bounds(uint32_t sp_min, uint32_t sp_max);
|
||||
void esp_hw_stack_guard_get_bounds(uint32_t *sp_min, uint32_t *sp_max);
|
||||
bool esp_hw_stack_guard_is_fired(void);
|
||||
uint32_t esp_hw_stack_guard_get_pc(void);
|
||||
void esp_hw_stack_guard_get_bounds(uint32_t core_id, uint32_t *sp_min, uint32_t *sp_max);
|
||||
uint32_t esp_hw_stack_guard_get_fired_cpu(void);
|
||||
uint32_t esp_hw_stack_guard_get_pc(uint32_t core_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
@ -33,8 +35,9 @@ uint32_t esp_hw_stack_guard_get_pc(void);
|
|||
#include "hal/assist_debug_ll.h"
|
||||
|
||||
#define ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM (ASSIST_DEBUG_CORE_0_INTR_ENA_REG >> 12)
|
||||
#define ASSIST_DEBUG_CORE_0_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_0_SP_MIN_REG - ASSIST_DEBUG_CORE_0_INTR_ENA_REG)
|
||||
#define ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_0_SP_MAX_REG - ASSIST_DEBUG_CORE_0_INTR_ENA_REG)
|
||||
#define ASSIST_DEBUG_CORE_0_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_0_SP_MIN_REG - DR_REG_ASSIST_DEBUG_BASE)
|
||||
#define ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_0_SP_MAX_REG - DR_REG_ASSIST_DEBUG_BASE)
|
||||
#define ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET (ASSIST_DEBUG_CORE_0_INTR_ENA_REG - DR_REG_ASSIST_DEBUG_BASE)
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0 reg1
|
||||
lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM
|
||||
|
@ -44,23 +47,24 @@ sw a1, ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET(\reg1)
|
|||
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0 reg1 reg2
|
||||
lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM
|
||||
lw \reg2, 0(\reg1)
|
||||
lw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1)
|
||||
andi \reg2, \reg2, ~ASSIST_DEBUG_SP_SPILL_BITS
|
||||
sw \reg2, 0(\reg1)
|
||||
sw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1)
|
||||
.endm
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_START_CPU0 reg1 reg2
|
||||
lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM
|
||||
lw \reg2, 0(\reg1)
|
||||
lw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1)
|
||||
ori \reg2, \reg2, ASSIST_DEBUG_SP_SPILL_BITS
|
||||
sw \reg2, 0(\reg1)
|
||||
sw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1)
|
||||
.endm
|
||||
|
||||
#if SOC_CPU_CORES_NUM > 1
|
||||
|
||||
#define ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM (ASSIST_DEBUG_CORE_1_INTR_ENA_REG >> 12)
|
||||
#define ASSIST_DEBUG_CORE_1_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_1_SP_MIN_REG - ASSIST_DEBUG_CORE_1_INTR_ENA_REG)
|
||||
#define ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_1_SP_MAX_REG - ASSIST_DEBUG_CORE_1_INTR_ENA_REG)
|
||||
#define ASSIST_DEBUG_CORE_1_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_1_SP_MIN_REG - DR_REG_ASSIST_DEBUG_BASE)
|
||||
#define ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_1_SP_MAX_REG - DR_REG_ASSIST_DEBUG_BASE)
|
||||
#define ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET (ASSIST_DEBUG_CORE_1_INTR_ENA_REG - DR_REG_ASSIST_DEBUG_BASE)
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_SET_BOUNDS_CPU1 reg1
|
||||
lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM
|
||||
|
@ -70,22 +74,22 @@ sw a1, ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET(\reg1)
|
|||
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_STOP_CPU1 reg1 reg2
|
||||
lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM
|
||||
lw \reg2, 0(\reg1)
|
||||
lw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1)
|
||||
andi \reg2, \reg2, ~ASSIST_DEBUG_SP_SPILL_BITS
|
||||
sw \reg2, 0(\reg1)
|
||||
sw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1)
|
||||
.endm
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_MONITOR_START_CPU1 reg1 reg2
|
||||
lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM
|
||||
lw \reg2, 0(\reg1)
|
||||
lw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1)
|
||||
ori \reg2, \reg2, ASSIST_DEBUG_SP_SPILL_BITS
|
||||
sw \reg2, 0(\reg1)
|
||||
sw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1)
|
||||
.endm
|
||||
|
||||
.macro ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE reg1
|
||||
/* Check the current core ID */
|
||||
csrr \reg1, mhartid
|
||||
beqz \reg1, @1f
|
||||
beqz \reg1, 1f
|
||||
/* Core 1 */
|
||||
ESP_HW_STACK_GUARD_SET_BOUNDS_CPU1 \reg1
|
||||
j 2f
|
||||
|
@ -98,7 +102,7 @@ ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0 \reg1
|
|||
.macro ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE reg1 reg2
|
||||
/* Check the current core ID */
|
||||
csrr \reg1, mhartid
|
||||
beqz \reg1, @1f
|
||||
beqz \reg1, 1f
|
||||
/* Core 1 */
|
||||
ESP_HW_STACK_GUARD_MONITOR_START_CPU1 \reg1 \reg2
|
||||
j 2f
|
||||
|
@ -111,7 +115,7 @@ ESP_HW_STACK_GUARD_MONITOR_START_CPU0 \reg1 \reg2
|
|||
.macro ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE reg1 reg2
|
||||
/* Check the current core ID */
|
||||
csrr \reg1, mhartid
|
||||
beqz \reg1, @1f
|
||||
beqz \reg1, 1f
|
||||
/* Core 1 */
|
||||
ESP_HW_STACK_GUARD_MONITOR_STOP_CPU1 \reg1 \reg2
|
||||
j 2f
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -37,6 +37,10 @@
|
|||
#include "hal/wdt_types.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
#include "esp_private/hw_stack_guard.h"
|
||||
#endif
|
||||
|
||||
extern int _invalid_pc_placeholder;
|
||||
|
||||
extern void esp_panic_handler_reconfigure_wdts(uint32_t timeout_ms);
|
||||
|
@ -117,6 +121,14 @@ static void frame_to_panic_info(void *frame, panic_info_t *info, bool pseudo_exc
|
|||
info->frame = frame;
|
||||
}
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
FORCE_INLINE_ATTR __attribute__((__noreturn__))
|
||||
void busy_wait(void)
|
||||
{
|
||||
while (1) {;} // infinite loop
|
||||
}
|
||||
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
|
||||
static void panic_handler(void *frame, bool pseudo_excause)
|
||||
{
|
||||
panic_info_t info = { 0 };
|
||||
|
@ -134,19 +146,24 @@ static void panic_handler(void *frame, bool pseudo_excause)
|
|||
// These are cases where both CPUs both go into panic handler. The following code ensures
|
||||
// only one core proceeds to the system panic handler.
|
||||
if (pseudo_excause) {
|
||||
#define BUSY_WAIT_IF_TRUE(b) { if (b) while(1); }
|
||||
// For WDT expiry, pause the non-offending core - offending core handles panic
|
||||
BUSY_WAIT_IF_TRUE(panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 && core_id == 1);
|
||||
BUSY_WAIT_IF_TRUE(panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1 && core_id == 0);
|
||||
|
||||
// For cache error, pause the non-offending core - offending core handles panic
|
||||
if (panic_get_cause(frame) == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) {
|
||||
// Only print the backtrace for the offending core in case of the cache error
|
||||
g_exc_frames[core_id] = NULL;
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
// For WDT expiry, pause the non-offending core - offending core handles panic
|
||||
if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 && core_id == 1) {
|
||||
busy_wait();
|
||||
} else if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1 && core_id == 0) {
|
||||
busy_wait();
|
||||
} else if (panic_get_cause(frame) == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) {
|
||||
g_exc_frames[core_id] = NULL; // Only print the backtrace for the offending core
|
||||
busy_wait();
|
||||
}
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
else if (panic_get_cause(frame) == ETS_ASSIST_DEBUG_INUM &&
|
||||
esp_hw_stack_guard_get_fired_cpu() != core_id &&
|
||||
esp_hw_stack_guard_get_fired_cpu() != ESP_HW_STACK_GUARD_NOT_FIRED) {
|
||||
g_exc_frames[core_id] = NULL; // Only print the backtrace for the offending core
|
||||
busy_wait();
|
||||
}
|
||||
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
}
|
||||
|
||||
// Need to reconfigure WDTs before we stall any other CPU
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -17,6 +17,7 @@
|
|||
#include <stdint.h>
|
||||
#include "esp_attr.h"
|
||||
#include "hal/assert.h"
|
||||
#include "soc/system_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -54,7 +55,7 @@ extern "C" {
|
|||
* interrupt, instead of "ENA".
|
||||
*/
|
||||
|
||||
/* These functions are optimazed and designed for internal usage.
|
||||
/* These functions are optimized and designed for internal usage.
|
||||
* So, the API may differ from general ll layer pattern */
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id)
|
||||
|
@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused
|
|||
return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
SYSTEM.cpu_peri_clk_en.clk_en_assist_debug = enable;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void)
|
||||
{
|
||||
SYSTEM.cpu_peri_rst_en.rst_en_assist_debug = true;
|
||||
SYSTEM.cpu_peri_rst_en.rst_en_assist_debug = false;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -17,6 +17,7 @@
|
|||
#include <stdint.h>
|
||||
#include "esp_attr.h"
|
||||
#include "hal/assert.h"
|
||||
#include "soc/system_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -54,7 +55,7 @@ extern "C" {
|
|||
* interrupt, instead of "ENA".
|
||||
*/
|
||||
|
||||
/* These functions are optimazed and designed for internal usage.
|
||||
/* These functions are optimized and designed for internal usage.
|
||||
* So, the API may differ from general ll layer pattern */
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id)
|
||||
|
@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused
|
|||
return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
SYSTEM.cpu_peri_clk_en.reg_clk_en_assist_debug = enable;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void)
|
||||
{
|
||||
SYSTEM.cpu_peri_rst_en.reg_rst_en_assist_debug = true;
|
||||
SYSTEM.cpu_peri_rst_en.reg_rst_en_assist_debug = false;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -17,6 +17,7 @@
|
|||
#include <stdint.h>
|
||||
#include "esp_attr.h"
|
||||
#include "hal/assert.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -54,7 +55,7 @@ extern "C" {
|
|||
* interrupt, instead of "ENA".
|
||||
*/
|
||||
|
||||
/* These functions are optimazed and designed for internal usage.
|
||||
/* These functions are optimized and designed for internal usage.
|
||||
* So, the API may differ from general ll layer pattern */
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id)
|
||||
|
@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused
|
|||
return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
PCR.assist_conf.assist_clk_en = enable;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void)
|
||||
{
|
||||
PCR.assist_conf.assist_rst_en = true;
|
||||
PCR.assist_conf.assist_rst_en = false;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -17,6 +17,7 @@
|
|||
#include <stdint.h>
|
||||
#include "esp_attr.h"
|
||||
#include "hal/assert.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -54,7 +55,7 @@ extern "C" {
|
|||
* interrupt, instead of "ENA".
|
||||
*/
|
||||
|
||||
/* These functions are optimazed and designed for internal usage.
|
||||
/* These functions are optimized and designed for internal usage.
|
||||
* So, the API may differ from general ll layer pattern */
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id)
|
||||
|
@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused
|
|||
return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
PCR.assist_conf.assist_clk_en = enable;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void)
|
||||
{
|
||||
PCR.assist_conf.assist_rst_en = true;
|
||||
PCR.assist_conf.assist_rst_en = false;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for DEBUG_ASSIST peripheral
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/assist_debug_reg.h"
|
||||
#define ASSIST_DEBUG_SP_SPILL_BITS (ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_ENA | ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_ENA)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "esp_attr.h"
|
||||
#include "hal/assert.h"
|
||||
#include "soc/hp_sys_clkrst_struct.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Most other peripherals have 4 interrupt-related registers: INT_ENA_REG, INT_CLR_REG, INT_RAW_REG, INT_ST_REG, the
|
||||
* meaning of which is well-understood.
|
||||
*
|
||||
* Assist_debug peripheral uses a different structure of interrupt registers:
|
||||
* INT_ENA_REG, INT_RLS_REG, INT_CLR_REG, INT_RAW_REG.
|
||||
*
|
||||
* Their behavior can be explained using the following (verilog-like) pseudo-code:
|
||||
* reg sp_spill_max_st
|
||||
* assign sp_spill_max = (sp > SP_MAX_REG)
|
||||
* assign SP_SPILL_MAX_RAW = sp_spill_max & SPILL_MAX_ENA
|
||||
* always (@posedge clk) begin
|
||||
* if (reset) then sp_spill_max_st <= 0
|
||||
* elif SP_SPILL_MAX_CLR then sp_spill_max_st <= 0
|
||||
* else sp_spill_max_st <= SP_SPILL_MAX_RAW & SP_SPILL_MAX_RLS
|
||||
* end
|
||||
* // ...same for sp_spill_min and other things dsoc/hp_sys_clkrst_struct.hebug_assist can check.
|
||||
*
|
||||
* // this is the final interrupt line coming out of the peripheral:
|
||||
* assign DEBUG_ASSIST_INT = sp_spill_max_st | sp_spill_min_st | ...
|
||||
*
|
||||
* Basically, there is no "ST" register showing the final (latched) interrupt state, and there is an additional
|
||||
* "RLS" register which just like "ENA" can be used to mask the interrupt.
|
||||
* Note that writing to CLR clears the (internal) latched interrupt state 'sp_spill_max_st',
|
||||
* but doesn't affect the software-readable RAW register.
|
||||
*
|
||||
* In this code, we use "ENA" to enable monitoring of a particular condition, and "RLS" to enable the interrupt.
|
||||
* This allows checking whether the condition (e.g. sp > SP_MAX) has occurred by reading the RAW register, without
|
||||
* actually triggering the interrupt. Hence you will see the somewhat counter-intuitive use of "RLS" to enable the
|
||||
* interrupt, instead of "ENA".
|
||||
*/
|
||||
|
||||
/* These functions are optimized and designed for internal usage.
|
||||
* So, the API may differ from general ll layer pattern */
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(uint32_t core_id)
|
||||
{
|
||||
REG_SET_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_ENA_REG : ASSIST_DEBUG_CORE_0_INTR_ENA_REG, ASSIST_DEBUG_SP_SPILL_BITS);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_disable(uint32_t core_id)
|
||||
{
|
||||
REG_CLR_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_ENA_REG : ASSIST_DEBUG_CORE_0_INTR_ENA_REG, ASSIST_DEBUG_SP_SPILL_BITS);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_interrupt_enable(uint32_t core_id)
|
||||
{
|
||||
REG_SET_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_RLS_REG : ASSIST_DEBUG_CORE_0_INTR_RLS_REG, ASSIST_DEBUG_SP_SPILL_BITS);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_interrupt_disable(uint32_t core_id)
|
||||
{
|
||||
REG_CLR_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_RLS_REG : ASSIST_DEBUG_CORE_0_INTR_RLS_REG, ASSIST_DEBUG_SP_SPILL_BITS);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR bool assist_debug_ll_sp_spill_is_fired(uint32_t core_id)
|
||||
{
|
||||
return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_INTR_RAW_REG : ASSIST_DEBUG_CORE_0_INTR_RAW_REG) & ASSIST_DEBUG_SP_SPILL_BITS;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_interrupt_clear(uint32_t core_id)
|
||||
{
|
||||
REG_WRITE(core_id ? ASSIST_DEBUG_CORE_1_INTR_CLR_REG : ASSIST_DEBUG_CORE_0_INTR_CLR_REG, ASSIST_DEBUG_SP_SPILL_BITS);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_set_min(uint32_t core_id, uint32_t min)
|
||||
{
|
||||
REG_WRITE(core_id ? ASSIST_DEBUG_CORE_1_SP_MIN_REG : ASSIST_DEBUG_CORE_0_SP_MIN_REG, min);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_min(uint32_t core_id)
|
||||
{
|
||||
return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_SP_MIN_REG : ASSIST_DEBUG_CORE_0_SP_MIN_REG);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_set_max(uint32_t core_id, uint32_t max)
|
||||
{
|
||||
REG_WRITE(core_id ? ASSIST_DEBUG_CORE_1_SP_MAX_REG : ASSIST_DEBUG_CORE_0_SP_MAX_REG, max);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_max(uint32_t core_id)
|
||||
{
|
||||
return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_SP_MAX_REG : ASSIST_DEBUG_CORE_0_SP_MAX_REG);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(uint32_t core_id)
|
||||
{
|
||||
return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_SP_PC_REG : ASSIST_DEBUG_CORE_0_SP_PC_REG);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
HP_SYS_CLKRST.soc_clk_ctrl0.reg_busmon_cpu_clk_en = enable;
|
||||
}
|
||||
#define assist_debug_ll_enable_bus_clock(...) \
|
||||
(void)__DECLARE_RCC_ATOMIC_ENV; assist_debug_ll_enable_bus_clock(__VA_ARGS__)
|
||||
|
||||
FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void)
|
||||
{
|
||||
/* esp32p4 has no assist_debug reset register: disable & clear interrupts manually. */
|
||||
for (int i = 0; i < CONFIG_SOC_CPU_CORES_NUM; i++) {
|
||||
assist_debug_ll_sp_spill_monitor_disable(i);
|
||||
assist_debug_ll_sp_spill_interrupt_clear(i);
|
||||
assist_debug_ll_sp_spill_set_min(i, 0);
|
||||
assist_debug_ll_sp_spill_set_max(i, 0xffffffff);
|
||||
/* Enable PC register storing when trigger stack monitor. */
|
||||
REG_WRITE(i ? ASSIST_DEBUG_CORE_1_RCD_EN_REG : ASSIST_DEBUG_CORE_0_RCD_EN_REG, ASSIST_DEBUG_CORE_1_RCD_PDEBUGEN | ASSIST_DEBUG_CORE_1_RCD_RECORDEN);
|
||||
}
|
||||
}
|
||||
#define assist_debug_ll_reset_register(...) \
|
||||
(void)__DECLARE_RCC_ATOMIC_ENV; assist_debug_ll_reset_register(__VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __ASSEMBLER__
|
|
@ -89,7 +89,7 @@ const soc_memory_region_t soc_memory_regions[] = {
|
|||
const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_memory_region_t);
|
||||
|
||||
|
||||
extern int _data_start, _bss_start_high, _heap_start_low, _heap_start_high, _iram_start, _iram_end, _rtc_force_slow_end;
|
||||
extern int _data_start_low, _data_start_high, _heap_start_low, _heap_start_high, _iram_start, _iram_end, _rtc_force_slow_end;
|
||||
extern int _tcm_text_start, _tcm_data_end;
|
||||
extern int _rtc_reserved_start, _rtc_reserved_end;
|
||||
|
||||
|
@ -100,8 +100,8 @@ extern int _rtc_reserved_start, _rtc_reserved_end;
|
|||
*/
|
||||
|
||||
// Static data region. DRAM used by data+bss and possibly rodata
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start_low, dram_data_low);
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_bss_start_high, (intptr_t)&_heap_start_high, dram_data_high);
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start_low, (intptr_t)&_heap_start_low, dram_data_low);
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start_high, (intptr_t)&_heap_start_high, dram_data_high);
|
||||
|
||||
// Target has a shared D/IRAM virtual address, no need to calculate I_D_OFFSET like previous chips
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -14,6 +14,12 @@
|
|||
#define MEMPROT_ISR _interrupt_handler
|
||||
#endif // CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
#define ASTDBG_ISR _panic_handler
|
||||
#else
|
||||
#define ASTDBG_ISR _interrupt_handler
|
||||
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
|
||||
#if CONFIG_ESP_IPC_ISR_ENABLE
|
||||
#define IPC_ISR_HANDLER esp_ipc_isr_handler
|
||||
#else
|
||||
|
@ -109,7 +115,7 @@ _mtvt_table:
|
|||
.word _panic_handler /* 40: ETS_INT_WDT_INUM (+16) panic-interrupt (soc-level panic) */
|
||||
.word _panic_handler /* 41: ETS_CACHEERR_INUM (+16) panic-interrupt (soc-level panic) */
|
||||
.word MEMPROT_ISR /* 42: ETS_MEMPROT_ERR_INUM (+16) handler (soc-level panic) */
|
||||
.word _interrupt_handler /* 43: Free interrupt number */
|
||||
.word ASTDBG_ISR /* 43: ETS_ASSIST_DEBUG_INUM (+16) handler (soc-level panic) */
|
||||
.word IPC_ISR_HANDLER /* 44: ETS_IPC_ISR_INUM (+16) handler*/
|
||||
.word _interrupt_handler /* 45: Free interrupt number */
|
||||
.word _interrupt_handler /* 46: Free interrupt number */
|
||||
|
|
|
@ -211,6 +211,10 @@ config SOC_CLK_TREE_SUPPORTED
|
|||
bool
|
||||
default y
|
||||
|
||||
config SOC_ASSIST_DEBUG_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_WDT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "soc/soc.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -68,6 +68,7 @@ typedef enum {
|
|||
PERIPH_AXI_PDMA_MODULE,
|
||||
PERIPH_UHCI_MODULE,
|
||||
PERIPH_PCNT_MODULE,
|
||||
PERIPH_ASSIST_DEBUG_MODULE,
|
||||
/* LP peripherals */
|
||||
PERIPH_LP_I2C0_MODULE,
|
||||
PERIPH_LP_UART0_MODULE,
|
||||
|
|
|
@ -231,6 +231,7 @@
|
|||
#define ETS_T1_WDT_INUM 24
|
||||
#define ETS_CACHEERR_INUM 25
|
||||
#define ETS_MEMPROT_ERR_INUM 26
|
||||
#define ETS_ASSIST_DEBUG_INUM 27 // Note: this interrupt can be combined with others (e.g., CACHEERR), as we can identify its trigger is activated
|
||||
#define ETS_IPC_ISR_INUM 28
|
||||
//CPU0 Max valid interrupt number
|
||||
#define ETS_MAX_INUM 31
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
// #define SOC_ULP_SUPPORTED 1 //TODO: IDF-7534
|
||||
#define SOC_SDMMC_HOST_SUPPORTED 1
|
||||
#define SOC_CLK_TREE_SUPPORTED 1
|
||||
// #define SOC_ASSIST_DEBUG_SUPPORTED 1 //TODO: IDF-7565
|
||||
#define SOC_ASSIST_DEBUG_SUPPORTED 1
|
||||
#define SOC_WDT_SUPPORTED 1
|
||||
#define SOC_SPI_FLASH_SUPPORTED 1
|
||||
// #define SOC_TOUCH_SENSOR_SUPPORTED 1 //TODO: IDF-7477
|
||||
|
|
|
@ -208,10 +208,8 @@ tools/test_apps/system/no_embedded_paths:
|
|||
reason: the other targets are not tested yet
|
||||
|
||||
tools/test_apps/system/panic:
|
||||
disable:
|
||||
- if: IDF_TARGET in ["esp32p4"]
|
||||
temporary: true
|
||||
reason: target(s) not supported yet # TODO: IDF-7511
|
||||
enable:
|
||||
- if: INCLUDE_DEFAULT == 1 or IDF_TARGET in ["esp32p4"] # preview targets
|
||||
|
||||
tools/test_apps/system/ram_loadable_app:
|
||||
disable_test:
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
CONFIG_ESP_SYSTEM_HW_STACK_GUARD=n
|
|
@ -1,5 +1,5 @@
|
|||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
# Introduction
|
||||
|
||||
|
|
|
@ -24,7 +24,12 @@ void test_int_wdt(void);
|
|||
|
||||
void test_task_wdt_cpu0(void);
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
void test_hw_stack_guard_cpu0(void);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
void test_hw_stack_guard_cpu1(void);
|
||||
#endif // CONFIG_FREERTOS_UNICORE
|
||||
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
||||
void test_panic_extram_stack(void);
|
||||
|
|
|
@ -31,9 +31,7 @@
|
|||
static const char* get_test_name(void)
|
||||
{
|
||||
static char test_name_str[BOOT_CMD_MAX_LEN] = {0};
|
||||
|
||||
printf("Enter test name: ");
|
||||
fflush(stdout);
|
||||
bool print_prompt = true;
|
||||
|
||||
/* Not using blocking fgets(stdin) here, as QEMU doesn't yet implement RX timeout interrupt,
|
||||
* which is required for the UART driver and blocking stdio to work.
|
||||
|
@ -42,16 +40,24 @@ static const char* get_test_name(void)
|
|||
char *p = test_name_str;
|
||||
const char *end = test_name_str + sizeof(test_name_str) - 1;
|
||||
while (p < end) {
|
||||
if (print_prompt) {
|
||||
printf("Enter test name: ");
|
||||
fflush(stdout);
|
||||
print_prompt = false;
|
||||
}
|
||||
c = getchar();
|
||||
if (c == EOF) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
} else if ((c == '\r' || c == '\n') && p != test_name_str) {
|
||||
} else if (c == '\r' || c == '\n') {
|
||||
/* terminate the line */
|
||||
puts("\n\r");
|
||||
fflush(stdout);
|
||||
*p = '\0';
|
||||
break;
|
||||
} else {
|
||||
print_prompt = true;
|
||||
if (p != test_name_str) {
|
||||
*p = '\0';
|
||||
break;
|
||||
}
|
||||
} else if (c >= '0' && c <= 'z') {
|
||||
/* echo the received character */
|
||||
putchar(c);
|
||||
fflush(stdout);
|
||||
|
@ -83,7 +89,12 @@ void app_main(void)
|
|||
HANDLE_TEST(test_name, test_abort_cache_disabled);
|
||||
HANDLE_TEST(test_name, test_int_wdt);
|
||||
HANDLE_TEST(test_name, test_task_wdt_cpu0);
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
HANDLE_TEST(test_name, test_hw_stack_guard_cpu0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
HANDLE_TEST(test_name, test_hw_stack_guard_cpu1);
|
||||
#endif // CONFIG_FREERTOS_UNICORE
|
||||
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
||||
HANDLE_TEST(test_name, test_panic_extram_stack);
|
||||
#endif
|
||||
|
|
|
@ -63,6 +63,8 @@ void test_task_wdt_cpu0(void)
|
|||
}
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
|
||||
__attribute__((optimize("-O0")))
|
||||
static void test_hw_stack_guard_cpu(void* arg)
|
||||
{
|
||||
|
@ -78,6 +80,18 @@ void test_hw_stack_guard_cpu0(void)
|
|||
}
|
||||
}
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
void test_hw_stack_guard_cpu1(void)
|
||||
{
|
||||
xTaskCreatePinnedToCore(test_hw_stack_guard_cpu, "HWSG1", 512, NULL, 1, NULL, 1);
|
||||
while (true) {
|
||||
vTaskDelay(100);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_FREERTOS_UNICORE
|
||||
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
|
||||
|
||||
static void stack_in_extram(void* arg) {
|
||||
|
|
|
@ -17,7 +17,8 @@ TARGETS_TESTED = [
|
|||
pytest.mark.esp32s3,
|
||||
pytest.mark.esp32c2,
|
||||
pytest.mark.esp32c6,
|
||||
pytest.mark.esp32h2
|
||||
pytest.mark.esp32h2,
|
||||
pytest.mark.esp32p4,
|
||||
]
|
||||
|
||||
# Most tests run on all targets and with all configs.
|
||||
|
@ -34,7 +35,11 @@ CONFIGS = [
|
|||
]
|
||||
|
||||
# Some tests only run on dual-core targets, they use the config below.
|
||||
TARGETS_DUAL_CORE = [pytest.mark.esp32, pytest.mark.esp32s3]
|
||||
TARGETS_DUAL_CORE = [
|
||||
pytest.mark.esp32,
|
||||
pytest.mark.esp32s3,
|
||||
pytest.mark.esp32p4,
|
||||
]
|
||||
CONFIGS_DUAL_CORE = [
|
||||
pytest.param('coredump_flash_bin_crc', marks=TARGETS_DUAL_CORE),
|
||||
pytest.param('coredump_flash_elf_sha', marks=TARGETS_DUAL_CORE),
|
||||
|
@ -58,6 +63,7 @@ TARGETS_HW_STACK_GUARD = [
|
|||
pytest.mark.esp32c3,
|
||||
pytest.mark.esp32c6,
|
||||
pytest.mark.esp32h2,
|
||||
pytest.mark.esp32p4,
|
||||
]
|
||||
|
||||
CONFIGS_HW_STACK_GUARD = [
|
||||
|
@ -68,6 +74,14 @@ CONFIGS_HW_STACK_GUARD = [
|
|||
pytest.param('panic', marks=TARGETS_HW_STACK_GUARD),
|
||||
]
|
||||
|
||||
CONFIGS_HW_STACK_GUARD_DUAL_CORE = [
|
||||
pytest.param('coredump_flash_bin_crc', marks=[pytest.mark.esp32p4]),
|
||||
pytest.param('coredump_uart_bin_crc', marks=[pytest.mark.esp32p4]),
|
||||
pytest.param('coredump_uart_elf_crc', marks=[pytest.mark.esp32p4]),
|
||||
pytest.param('gdbstub', marks=[pytest.mark.esp32p4]),
|
||||
pytest.param('panic', marks=[pytest.mark.esp32p4]),
|
||||
]
|
||||
|
||||
# Panic abort information will start with this string.
|
||||
PANIC_ABORT_PREFIX = 'Panic reason: '
|
||||
|
||||
|
@ -148,15 +162,16 @@ def test_task_wdt_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> N
|
|||
'Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:'
|
||||
)
|
||||
dut.expect_exact('CPU 1: Infinite loop')
|
||||
expected_backtrace = ['infinite_loop', 'vPortTaskWrapper']
|
||||
if dut.is_xtensa:
|
||||
# see comment in test_task_wdt_cpu0
|
||||
dut.expect_none('register dump:')
|
||||
dut.expect_exact('Print CPU 1 backtrace')
|
||||
dut.expect_backtrace()
|
||||
# On Xtensa, we get incorrect backtrace from GDB in this test
|
||||
expected_backtrace = ['infinite_loop', 'vPortTaskWrapper']
|
||||
else:
|
||||
assert False, 'No dual-core RISC-V chips yet, check this test case later'
|
||||
# on RISC-V, need to dump both registers and stack memory to reconstruct the backtrace
|
||||
dut.expect_reg_dump(core=1)
|
||||
dut.expect_stack_dump()
|
||||
|
||||
dut.expect_elf_sha256()
|
||||
dut.expect_none('Guru Meditation')
|
||||
|
@ -204,9 +219,9 @@ def test_int_wdt(
|
|||
dut.expect_stack_dump()
|
||||
|
||||
if target in TARGETS_DUAL_CORE_NAMES:
|
||||
assert dut.is_xtensa, 'No dual-core RISC-V chips yet, check the test case'
|
||||
dut.expect_reg_dump(1)
|
||||
dut.expect_backtrace()
|
||||
if dut.is_xtensa:
|
||||
dut.expect_backtrace()
|
||||
|
||||
dut.expect_elf_sha256()
|
||||
dut.expect_none('Guru Meditation')
|
||||
|
@ -228,9 +243,9 @@ def test_int_wdt_cache_disabled(
|
|||
dut.expect_stack_dump()
|
||||
|
||||
if target in TARGETS_DUAL_CORE_NAMES:
|
||||
assert dut.is_xtensa, 'No dual-core RISC-V chips yet, check the test case'
|
||||
dut.expect_reg_dump(1)
|
||||
dut.expect_backtrace()
|
||||
if dut.is_xtensa:
|
||||
dut.expect_backtrace()
|
||||
|
||||
dut.expect_elf_sha256()
|
||||
dut.expect_none('Guru Meditation')
|
||||
|
@ -251,6 +266,8 @@ def test_cache_error(dut: PanicTestDut, config: str, test_func_name: str) -> Non
|
|||
elif dut.target in ['esp32s2']:
|
||||
# Cache error interrupt is not enabled, IDF-1558
|
||||
dut.expect_gme('IllegalInstruction')
|
||||
elif dut.target in ['esp32p4']: # TODO IDF-7515
|
||||
dut.expect_gme('Instruction access fault')
|
||||
else:
|
||||
dut.expect_gme('Cache disabled but cached memory region accessed')
|
||||
dut.expect_reg_dump(0)
|
||||
|
@ -832,15 +849,36 @@ def test_gdbstub_coredump(dut: PanicTestDut) -> None:
|
|||
return # don't expect "Rebooting" output below
|
||||
|
||||
|
||||
def test_hw_stack_guard_cpu(dut: PanicTestDut, cpu: int) -> None:
|
||||
dut.expect_exact(f'Guru Meditation Error: Core {cpu} panic\'ed (Stack protection fault).')
|
||||
dut.expect_none('ASSIST_DEBUG is not triggered BUT interrupt occured!')
|
||||
dut.expect_exact(f'Detected in task "HWSG{cpu}"')
|
||||
addr = dut.expect('at 0x([0-9a-fA-F]{8})')
|
||||
assert addr.group(1) != b'00000000'
|
||||
addr = dut.expect('Stack pointer: 0x([0-9a-fA-F]{8})')
|
||||
assert addr.group(1) != b'00000000'
|
||||
addr = dut.expect(r'Stack bounds: 0x([0-9a-fA-F]{8})')
|
||||
assert addr.group(1) != b'00000000'
|
||||
start_addr = int(addr.group(1), 16)
|
||||
addr = dut.expect(r' - 0x([0-9a-fA-F]{8})')
|
||||
assert addr.group(1) != b'00000000'
|
||||
end_addr = int(addr.group(1), 16)
|
||||
assert end_addr > start_addr
|
||||
|
||||
|
||||
@pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD, indirect=True)
|
||||
@pytest.mark.generic
|
||||
def test_hw_stack_guard_cpu0(dut: PanicTestDut, config: str, test_func_name: str) -> None:
|
||||
dut.run_test_func(test_func_name)
|
||||
dut.expect_exact('Guru Meditation Error: Core 0 panic\'ed (Stack protection fault).')
|
||||
dut.expect_none('ASSIST_DEBUG is not triggered BUT interrupt occured!')
|
||||
dut.expect(r'Detected in task(.*)at 0x')
|
||||
dut.expect_exact('Stack pointer: 0x')
|
||||
dut.expect(r'Stack bounds: 0x(.*) - 0x')
|
||||
test_hw_stack_guard_cpu(dut, 0)
|
||||
common_test(dut, config)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD_DUAL_CORE, indirect=True)
|
||||
@pytest.mark.generic
|
||||
def test_hw_stack_guard_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> None:
|
||||
dut.run_test_func(test_func_name)
|
||||
test_hw_stack_guard_cpu(dut, 1)
|
||||
common_test(dut, config)
|
||||
|
||||
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Any, Dict, List, Optional, TextIO, Union
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import TextIO
|
||||
from typing import Union
|
||||
|
||||
import pexpect
|
||||
from panic_utils import NoGdbProcessError, attach_logger, quote_string, sha256, verify_valid_gdb_subprocess
|
||||
from panic_utils import attach_logger
|
||||
from panic_utils import NoGdbProcessError
|
||||
from panic_utils import quote_string
|
||||
from panic_utils import sha256
|
||||
from panic_utils import verify_valid_gdb_subprocess
|
||||
from pygdbmi.gdbcontroller import GdbController
|
||||
from pytest_embedded_idf.app import IdfApp
|
||||
from pytest_embedded_idf.dut import IdfDut
|
||||
|
@ -53,7 +62,7 @@ class PanicTestDut(IdfDut):
|
|||
|
||||
@property
|
||||
def is_multi_core(self) -> bool:
|
||||
return self.target in ['esp32', 'esp32s3']
|
||||
return self.target in ['esp32', 'esp32s3', 'esp32p4']
|
||||
|
||||
def run_test_func(self, test_func_name: str) -> None:
|
||||
self.expect_exact('Enter test name:')
|
||||
|
|
Ładowanie…
Reference in New Issue