esp_system: support riscv panic

This commit is contained in:
Renz Bagaporo 2020-10-08 13:18:16 +08:00 committed by Angus Gratton
parent 420aef1ffe
commit 4cc6b5571b
32 changed files with 803 additions and 570 deletions

View File

@ -5,7 +5,7 @@ COMPONENT_ADD_INCLUDEDIRS := include
COMPONENT_PRIV_INCLUDEDIRS := private_include port/include COMPONENT_PRIV_INCLUDEDIRS := private_include port/include
COMPONENT_ADD_LDFRAGMENTS += linker.lf COMPONENT_ADD_LDFRAGMENTS += linker.lf
-include $(COMPONENT_PATH)/port/$(SOC_NAME)/component.mk include $(COMPONENT_PATH)/port/soc/$(SOC_NAME)/component.mk
# disable stack protection in files which are involved in initialization of that feature # disable stack protection in files which are involved in initialization of that feature
startup.o: CFLAGS := $(filter-out -fstack-protector%, $(CFLAGS)) startup.o: CFLAGS := $(filter-out -fstack-protector%, $(CFLAGS))

View File

@ -16,14 +16,20 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "soc/soc_caps.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern bool g_panic_abort; extern bool g_panic_abort;
extern void *g_exc_frames[SOC_CPU_CORES_NUM];
// Function to print longer amounts of information such as the details // Function to print longer amounts of information such as the details
// and backtrace field of panic_info_t. These functions should limit themselves // and backtrace field of panic_info_t. These functions should limit themselves
// to printing to the console and should do other more involved processing, // to printing to the console and should do other more involved processing,
@ -72,6 +78,20 @@ void panic_print_hex(int h);
void __attribute__((noreturn)) panic_abort(const char *details); void __attribute__((noreturn)) panic_abort(const char *details);
void panic_arch_fill_info(void *frame, panic_info_t *info);
void panic_soc_fill_info(void *frame, panic_info_t *info);
void panic_print_registers(const void *frame, int core);
void panic_print_backtrace(const void *frame, int core);
uint32_t panic_get_address(const void* frame);
void panic_set_address(void *frame, uint32_t addr);
uint32_t panic_get_cause(const void* frame);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -3,6 +3,7 @@ archive: libesp_system.a
entries: entries:
panic (noflash) panic (noflash)
panic_handler (noflash) panic_handler (noflash)
panic_arch (noflash)
reset_reason (noflash) reset_reason (noflash)
system_api:esp_system_abort (noflash) system_api:esp_system_abort (noflash)
startup:do_core_init (default) startup:do_core_init (default)

View File

@ -46,11 +46,26 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB
#include "esp_private/gdbstub.h"
#endif
#if CONFIG_ESP32_ENABLE_COREDUMP
#include "esp_core_dump.h"
#endif
#if CONFIG_APPTRACE_ENABLE
#include "esp_app_trace.h"
#if CONFIG_SYSVIEW_ENABLE
#include "SEGGER_RTT.h"
#endif
#if CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO == -1 #if CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO == -1
#define APPTRACE_ONPANIC_HOST_FLUSH_TMO ESP_APPTRACE_TMO_INFINITE #define APPTRACE_ONPANIC_HOST_FLUSH_TMO ESP_APPTRACE_TMO_INFINITE
#else #else
#define APPTRACE_ONPANIC_HOST_FLUSH_TMO (1000*CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO) #define APPTRACE_ONPANIC_HOST_FLUSH_TMO (1000*CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO)
#endif #endif
#endif // CONFIG_APPTRACE_ENABLE
#if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB #if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB
#include "esp_private/gdbstub.h" #include "esp_private/gdbstub.h"

View File

@ -1,10 +1,9 @@
target_include_directories(${COMPONENT_LIB} PRIVATE include) target_include_directories(${COMPONENT_LIB} PRIVATE include)
set(srcs "cpu_start.c") set(srcs "cpu_start.c" "panic_handler.c")
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) target_sources(${COMPONENT_LIB} PRIVATE ${srcs})
idf_build_get_property(target IDF_TARGET) idf_build_get_property(target IDF_TARGET)
add_subdirectory(${target}) add_subdirectory(soc/${target})

View File

@ -0,0 +1,127 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include "esp_private/panic_internal.h"
#include "riscv/rvruntime-frames.h"
extern void esp_panic_handler(panic_info_t *);
void panic_print_registers(const void *f, int core)
{
uint32_t *regs = (uint32_t *)f;
// only print ABI name
const char *desc[] = {
"MEPC ", "RA ", "SP ", "GP ", "TP ", "T0 ", "T1 ", "T2 ",
"S0/FP ", "S1 ", "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ",
"A6 ", "A7 ", "S2 ", "S3 ", "S4 ", "S5 ", "S6 ", "S7 ",
"S8 ", "S9 ", "S10 ", "S11 ", "T3 ", "T4 ", "T5 ", "T6 ",
"MSTATUS ", "MTVEC ", "MCAUSE ", "MTVAL ", "MHARTID "
};
panic_print_str("Core ");
panic_print_dec(((RvExcFrame *)f)->mhartid);
panic_print_str(" register dump:");
for (int x = 0; x < sizeof(desc) / sizeof(desc[0]); x += 4) {
panic_print_str("\r\n");
for (int y = 0; y < 4 && x + y < sizeof(desc) / sizeof(desc[0]); y++) {
if (desc[x + y][0] != 0) {
panic_print_str(desc[x + y]);
panic_print_str(": 0x");
panic_print_hex(regs[x + y]);
panic_print_str(" ");
}
}
}
}
void panic_soc_fill_info(void *f, panic_info_t *info)
{
// TODO ESP32-C3 IDF-2386 / support soc panic
return;
}
void panic_arch_fill_info(void *frame, panic_info_t *info)
{
RvExcFrame *regs = (RvExcFrame *) frame;
info->core = 0;
info->exception = PANIC_EXCEPTION_FAULT;
//Please keep in sync with PANIC_RSN_* defines
static const char *reason[] = {
"Instruction address misaligned",
"Instruction access fault",
"Illegal instruction",
"Breakpoint",
"Load address misaligned",
"Load access fault",
"Store address misaligned",
"Store access fault",
"Environment call from U-mode",
"Environment call from S-mode",
NULL,
"Environment call from M-mode",
"Instruction page fault",
"Load page fault",
NULL,
"Store page fault",
};
if (regs->mcause < (sizeof(reason) / sizeof(reason[0]))) {
if (reason[regs->mcause] != NULL) {
info->reason = (reason[regs->mcause]);
}
}
info->description = "Exception was unhandled.";
info->addr = (void *) regs->mepc;
info->frame = &regs;
}
void panic_print_backtrace(const void *frame, int core)
{
// Basic backtrace
panic_print_str("\r\nStack memory:\n");
uint32_t sp = (uint32_t)((RvExcFrame *)frame)->sp;
const int per_line = 8;
for (int x = 0; x < 1024; x += per_line * sizeof(uint32_t)) {
uint32_t *spp = (uint32_t *)(sp + x);
panic_print_hex(sp + x);
panic_print_str(": ");
for (int y = 0; y < per_line; y++) {
panic_print_str("0x");
panic_print_hex(spp[y]);
panic_print_char(y == per_line - 1 ? '\n' : ' ');
}
}
}
uint32_t panic_get_address(const void *f)
{
return ((RvExcFrame *)f)->mepc;
}
uint32_t panic_get_cause(const void *f)
{
return ((RvExcFrame *)f)->mcause;
}
void panic_set_address(void *f, uint32_t addr)
{
((RvExcFrame *)f)->mepc = addr;
}

View File

@ -11,185 +11,38 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <stdlib.h>
#include "freertos/xtensa_context.h" #include "freertos/xtensa_context.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "esp_spi_flash.h"
#include "esp_private/panic_reason.h"
#include "esp_private/system_internal.h"
#include "esp_debug_helpers.h" #include "esp_debug_helpers.h"
#include "soc/soc_memory_layout.h" #include "esp_private/panic_internal.h"
#include "soc/cpu.h" #include "esp_private/panic_reason.h"
#include "soc/soc_caps.h" #include "soc/soc.h"
#include "soc/rtc.h"
#include "hal/soc_hal.h"
#include "hal/cpu_hal.h"
#include "hal/wdt_types.h"
#include "hal/wdt_hal.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
#include "esp32/cache_err_int.h" #include "esp32/cache_err_int.h"
#include "esp32/dport_access.h" #else
#include "esp32/rom/uart.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/cache_err_int.h"
#include "esp32s2/rom/uart.h"
#include "esp32s2/memprot.h"
#include "soc/extmem_reg.h" #include "soc/extmem_reg.h"
#include "soc/cache_memory.h" #include "soc/cache_memory.h"
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/cache_err_int.h"
#include "esp32s2/memprot.h"
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/cache_err_int.h" #include "esp32s3/cache_err_int.h"
#include "esp32s3/rom/uart.h"
#include "esp32s3/memprot.h" #include "esp32s3/memprot.h"
#include "soc/extmem_reg.h"
#include "soc/cache_memory.h"
#include "soc/rtc_cntl_reg.h"
#endif #endif
#endif // CONFIG_IDF_TARGET_ESP32
#include "esp_private/panic_internal.h" void panic_print_registers(const void *f, int core)
extern int _invalid_pc_placeholder;
extern void esp_panic_handler(panic_info_t*);
static wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
static XtExcFrame *xt_exc_frames[SOC_CPU_CORES_NUM] = {NULL};
/*
Panic handlers; these get called when an unhandled exception occurs or the assembly-level
task switching / interrupt code runs into an unrecoverable error. The default task stack
overflow handler and abort handler are also in here.
*/
/*
Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled.
*/
static void print_illegal_instruction_details(const void *f)
{
XtExcFrame *frame = (XtExcFrame *) f;
/* Print out memory around the instruction word */
uint32_t epc = frame->pc;
epc = (epc & ~0x3) - 4;
/* check that the address was sane */
if (epc < SOC_IROM_MASK_LOW || epc >= SOC_IROM_HIGH) {
return;
}
volatile uint32_t *pepc = (uint32_t *)epc;
panic_print_str("Memory dump at 0x");
panic_print_hex(epc);
panic_print_str(": ");
panic_print_hex(*pepc);
panic_print_str(" ");
panic_print_hex(*(pepc + 1));
panic_print_str(" ");
panic_print_hex(*(pepc + 2));
}
static void print_debug_exception_details(const void *f)
{
int debug_rsn;
asm("rsr.debugcause %0":"=r"(debug_rsn));
panic_print_str("Debug exception reason: ");
if (debug_rsn & XCHAL_DEBUGCAUSE_ICOUNT_MASK) {
panic_print_str("SingleStep ");
}
if (debug_rsn & XCHAL_DEBUGCAUSE_IBREAK_MASK) {
panic_print_str("HwBreakpoint ");
}
if (debug_rsn & XCHAL_DEBUGCAUSE_DBREAK_MASK) {
//Unlike what the ISA manual says, this core seemingly distinguishes from a DBREAK
//reason caused by watchdog 0 and one caused by watchdog 1 by setting bit 8 of the
//debugcause if the cause is watchpoint 1 and clearing it if it's watchpoint 0.
if (debug_rsn & (1 << 8)) {
#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
int core = 0;
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
if (f == xt_exc_frames[1]) {
core = 1;
}
#endif
const char *name = pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(core));
panic_print_str("Stack canary watchpoint triggered (");
panic_print_str(name);
panic_print_str(") ");
#else
panic_print_str("Watchpoint 1 triggered ");
#endif
} else {
panic_print_str("Watchpoint 0 triggered ");
}
}
if (debug_rsn & XCHAL_DEBUGCAUSE_BREAK_MASK) {
panic_print_str("BREAK instr ");
}
if (debug_rsn & XCHAL_DEBUGCAUSE_BREAKN_MASK) {
panic_print_str("BREAKN instr ");
}
if (debug_rsn & XCHAL_DEBUGCAUSE_DEBUGINT_MASK) {
panic_print_str("DebugIntr ");
}
}
static void print_backtrace_entry(uint32_t pc, uint32_t sp)
{
panic_print_str("0x");
panic_print_hex(pc);
panic_print_str(":0x");
panic_print_hex(sp);
}
static void print_backtrace(const void *f, int core)
{
XtExcFrame *frame = (XtExcFrame *) f;
int depth = 100;
//Initialize stk_frame with first frame of stack
esp_backtrace_frame_t stk_frame = {.pc = frame->pc, .sp = frame->a1, .next_pc = frame->a0};
panic_print_str("\r\nBacktrace:");
print_backtrace_entry(esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
//Check if first frame is valid
bool corrupted = !(esp_stack_ptr_is_sane(stk_frame.sp) &&
(esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc)) ||
/* Ignore the first corrupted PC in case of InstrFetchProhibited */
frame->exccause == EXCCAUSE_INSTR_PROHIBITED));
uint32_t i = ((depth <= 0) ? INT32_MAX : depth) - 1; //Account for stack frame that's already printed
while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted) {
if (!esp_backtrace_get_next_frame(&stk_frame)) { //Get next stack frame
corrupted = true;
}
panic_print_str(" ");
print_backtrace_entry(esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
}
//Print backtrace termination marker
if (corrupted) {
panic_print_str(" |<-CORRUPTED");
} else if (stk_frame.next_pc != 0) { //Backtrace continues
panic_print_str(" |<-CONTINUES");
}
}
static void print_registers(const void *f, int core)
{ {
XtExcFrame *frame = (XtExcFrame *) f; XtExcFrame *frame = (XtExcFrame *) f;
int *regs = (int *)frame; int *regs = (int *)frame;
const char *sdesc[] = { const char *sdesc[] = {
"PC ", "PS ", "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ", "PC ", "PS ", "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ",
"A6 ", "A7 ", "A8 ", "A9 ", "A10 ", "A11 ", "A12 ", "A13 ", "A6 ", "A7 ", "A8 ", "A9 ", "A10 ", "A11 ", "A12 ", "A13 ",
@ -248,37 +101,76 @@ static void print_registers(const void *f, int core)
} }
} }
static void print_state_for_core(const void *f, int core) static void print_illegal_instruction_details(const void *f)
{ {
if (!g_panic_abort) { XtExcFrame *frame = (XtExcFrame *) f;
print_registers(f, core); /* Print out memory around the instruction word */
panic_print_str("\r\n"); uint32_t epc = frame->pc;
epc = (epc & ~0x3) - 4;
/* check that the address was sane */
if (epc < SOC_IROM_MASK_LOW || epc >= SOC_IROM_HIGH) {
return;
} }
print_backtrace(f, core); volatile uint32_t *pepc = (uint32_t *)epc;
panic_print_str("Memory dump at 0x");
panic_print_hex(epc);
panic_print_str(": ");
panic_print_hex(*pepc);
panic_print_str(" ");
panic_print_hex(*(pepc + 1));
panic_print_str(" ");
panic_print_hex(*(pepc + 2));
} }
static void print_state(const void *f)
static void print_debug_exception_details(const void *f)
{ {
int debug_rsn;
asm("rsr.debugcause %0":"=r"(debug_rsn));
panic_print_str("Debug exception reason: ");
if (debug_rsn & XCHAL_DEBUGCAUSE_ICOUNT_MASK) {
panic_print_str("SingleStep ");
}
if (debug_rsn & XCHAL_DEBUGCAUSE_IBREAK_MASK) {
panic_print_str("HwBreakpoint ");
}
if (debug_rsn & XCHAL_DEBUGCAUSE_DBREAK_MASK) {
//Unlike what the ISA manual says, this core seemingly distinguishes from a DBREAK
//reason caused by watchdog 0 and one caused by watchdog 1 by setting bit 8 of the
//debugcause if the cause is watchpoint 1 and clearing it if it's watchpoint 0.
if (debug_rsn & (1 << 8)) {
#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
int core = 0;
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
int err_core = f == xt_exc_frames[0] ? 0 : 1; if (f == g_exc_frames[1]) {
#else core = 1;
int err_core = 0; }
#endif #endif
print_state_for_core(f, err_core); const char *name = pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(core));
panic_print_str("Stack canary watchpoint triggered (");
panic_print_str("\r\n"); panic_print_str(name);
panic_print_str(") ");
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE #else
// If there are other frame info, print them as well panic_print_str("Watchpoint 1 triggered ");
for (int i = 0; i < SOC_CPU_CORES_NUM; i++) { #endif
// `f` is the frame for the offending core, see note above. } else {
if (err_core != i && xt_exc_frames[i] != NULL) { panic_print_str("Watchpoint 0 triggered ");
print_state_for_core(xt_exc_frames[i], i);
panic_print_str("\r\n");
} }
} }
#endif if (debug_rsn & XCHAL_DEBUGCAUSE_BREAK_MASK) {
panic_print_str("BREAK instr ");
}
if (debug_rsn & XCHAL_DEBUGCAUSE_BREAKN_MASK) {
panic_print_str("BREAKN instr ");
}
if (debug_rsn & XCHAL_DEBUGCAUSE_DEBUGINT_MASK) {
panic_print_str("DebugIntr ");
}
} }
#if CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32S2
@ -460,194 +352,146 @@ static inline void print_memprot_err_details(const void *f)
} }
#endif #endif
static void frame_to_panic_info(XtExcFrame *frame, panic_info_t *info, bool pseudo_excause)
void panic_arch_fill_info(void *f, panic_info_t *info)
{ {
info->core = cpu_hal_get_core_id(); XtExcFrame *frame = (XtExcFrame*) f;
info->exception = PANIC_EXCEPTION_FAULT; static const char *reason[] = {
info->details = NULL; "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
"Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue",
"Privileged", "LoadStoreAlignment", "res", "res",
"InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError",
"InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res",
"InstrFetchProhibited", "res", "res", "res",
"LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res",
"LoadProhibited", "StoreProhibited", "res", "res",
"Cp0Dis", "Cp1Dis", "Cp2Dis", "Cp3Dis",
"Cp4Dis", "Cp5Dis", "Cp6Dis", "Cp7Dis"
};
info->pseudo_excause = pseudo_excause; if (frame->exccause < (sizeof(reason) / sizeof(char *))) {
if (pseudo_excause) { info->reason = (reason[frame->exccause]);
if (frame->exccause == PANIC_RSN_INTWDT_CPU0) {
info->core = 0;
info->exception = PANIC_EXCEPTION_IWDT;
} else if (frame->exccause == PANIC_RSN_INTWDT_CPU1) {
info->core = 1;
info->exception = PANIC_EXCEPTION_IWDT;
} else if (frame->exccause == PANIC_RSN_CACHEERR) {
info->core = esp_cache_err_get_cpuid();
} else {}
//Please keep in sync with PANIC_RSN_* defines
static const char *pseudo_reason[] = {
"Unknown reason",
"Unhandled debug exception",
"Double exception",
"Unhandled kernel exception",
"Coprocessor exception",
"Interrupt wdt timeout on CPU0",
"Interrupt wdt timeout on CPU1",
#if CONFIG_IDF_TARGET_ESP32
"Cache disabled but cached memory region accessed",
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
"Cache exception",
#endif
};
info->reason = pseudo_reason[0];
info->description = NULL;
if (frame->exccause <= PANIC_RSN_MAX) {
info->reason = pseudo_reason[frame->exccause];
}
if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) {
info->details = print_debug_exception_details;
info->exception = PANIC_EXCEPTION_DEBUG;
}
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (frame->exccause == PANIC_RSN_CACHEERR) {
if ( esp_memprot_get_active_intr_memtype() != MEMPROT_NONE ) {
info->details = print_memprot_err_details;
info->reason = "Memory protection fault";
} else {
info->details = print_cache_err_details;
}
}
#endif
} else { } else {
static const char *reason[] = { info->reason = "Unknown";
"IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError", }
"Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue",
"Privileged", "LoadStoreAlignment", "res", "res", info->description = "Exception was unhandled.";
"InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError",
"InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res", if (frame->exccause == EXCCAUSE_ILLEGAL) {
"InstrFetchProhibited", "res", "res", "res", info->details = print_illegal_instruction_details;
"LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res",
"LoadProhibited", "StoreProhibited", "res", "res",
"Cp0Dis", "Cp1Dis", "Cp2Dis", "Cp3Dis",
"Cp4Dis", "Cp5Dis", "Cp6Dis", "Cp7Dis"
};
if (frame->exccause < (sizeof(reason) / sizeof(char *))) {
info->reason = (reason[frame->exccause]);
} else {
info->reason = "Unknown";
}
info->description = "Exception was unhandled.";
if (frame->exccause == EXCCAUSE_ILLEGAL) {
info->details = print_illegal_instruction_details;
}
} }
info->state = print_state;
info->addr = ((void *) ((XtExcFrame *) frame)->pc); info->addr = ((void *) ((XtExcFrame *) frame)->pc);
info->frame = frame;
} }
static void panic_handler(XtExcFrame *frame, bool pseudo_excause) void panic_soc_fill_info(void *f, panic_info_t *info)
{ {
/* // [refactor-todo] this should be in the common port panic_handler.c, once
* Setup environment and perform necessary architecture/chip specific // these special exceptions are supported in there.
* steps here prior to the system panic handler. XtExcFrame *frame = (XtExcFrame*) f;
* */ if (frame->exccause == PANIC_RSN_INTWDT_CPU0) {
int core_id = cpu_hal_get_core_id(); info->core = 0;
info->exception = PANIC_EXCEPTION_IWDT;
// If multiple cores arrive at panic handler, save frames for all of them } else if (frame->exccause == PANIC_RSN_INTWDT_CPU1) {
xt_exc_frames[core_id] = frame; info->core = 1;
info->exception = PANIC_EXCEPTION_IWDT;
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE } else if (frame->exccause == PANIC_RSN_CACHEERR) {
// These are cases where both CPUs both go into panic handler. The following code ensures info->core = esp_cache_err_get_cpuid();
// only one core proceeds to the system panic handler. } else {}
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(frame->exccause == PANIC_RSN_INTWDT_CPU0 && core_id == 1);
BUSY_WAIT_IF_TRUE(frame->exccause == PANIC_RSN_INTWDT_CPU1 && core_id == 0);
// For cache error, pause the non-offending core - offending core handles panic
if (frame->exccause == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) {
// Only print the backtrace for the offending core in case of the cache error
xt_exc_frames[core_id] = NULL;
while (1) {
;
}
}
}
esp_rom_delay_us(1);
SOC_HAL_STALL_OTHER_CORES();
#endif
//Please keep in sync with PANIC_RSN_* defines
static const char *pseudo_reason[] = {
"Unknown reason",
"Unhandled debug exception",
"Double exception",
"Unhandled kernel exception",
"Coprocessor exception",
"Interrupt wdt timeout on CPU0",
"Interrupt wdt timeout on CPU1",
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
esp_dport_access_int_abort(); "Cache disabled but cached memory region accessed",
#elif CONFIG_IDF_TARGET_ESP32S2
"Cache exception",
#endif #endif
};
#if !CONFIG_ESP_PANIC_HANDLER_IRAM info->reason = pseudo_reason[0];
// Re-enable CPU cache for current CPU if it was disabled info->description = NULL;
if (!spi_flash_cache_enabled()) {
spi_flash_enable_cache(core_id);
panic_print_str("Re-enable cpu cache.\r\n");
}
#endif
if (esp_cpu_in_ocd_debug_mode()) { if (frame->exccause <= PANIC_RSN_MAX) {
if (!(esp_ptr_executable(cpu_ll_pc_to_ptr(frame->pc)) && (frame->pc & 0xC0000000U))) { info->reason = pseudo_reason[frame->exccause];
/* Xtensa ABI sets the 2 MSBs of the PC according to the windowed call size
* Incase the PC is invalid, GDB will fail to translate addresses to function names
* Hence replacing the PC to a placeholder address in case of invalid PC
*/
frame->pc = (uint32_t)&_invalid_pc_placeholder;
}
if (frame->exccause == PANIC_RSN_INTWDT_CPU0 ||
frame->exccause == PANIC_RSN_INTWDT_CPU1) {
wdt_hal_write_protect_disable(&wdt0_context);
wdt_hal_handle_intr(&wdt0_context);
wdt_hal_write_protect_enable(&wdt0_context);
}
} }
// Convert architecture exception frame into abstracted panic info if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) {
panic_info_t info; info->details = print_debug_exception_details;
frame_to_panic_info(frame, &info, pseudo_excause); info->exception = PANIC_EXCEPTION_DEBUG;
// Call the system panic handler
esp_panic_handler(&info);
}
void panicHandler(XtExcFrame *frame)
{
// This panic handler gets called for when the double exception vector,
// kernel exception vector gets used; as well as handling interrupt-based
// faults cache error, wdt expiry. EXCAUSE register gets written with
// one of PANIC_RSN_* values.
panic_handler(frame, true);
}
void xt_unhandled_exception(XtExcFrame *frame)
{
panic_handler(frame, false);
}
void __attribute__((noreturn)) panic_restart(void)
{
bool digital_reset_needed = false;
#ifdef CONFIG_IDF_TARGET_ESP32
// On the ESP32, cache error status can only be cleared by system reset
if (esp_cache_err_get_cpuid() != -1) {
digital_reset_needed = true;
} }
#endif
#if CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32S2
if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) { if (frame->exccause == PANIC_RSN_CACHEERR) {
digital_reset_needed = true; if ( esp_memprot_is_intr_ena_any() ) {
info->details = print_memprot_err_details;
info->reason = "Memory protection fault";
} else {
info->details = print_cache_err_details;
}
} }
#endif #endif
if (digital_reset_needed) { }
esp_restart_noos_dig();
} static void print_backtrace_entry(uint32_t pc, uint32_t sp)
esp_restart_noos(); {
panic_print_str("0x");
panic_print_hex(pc);
panic_print_str(":0x");
panic_print_hex(sp);
}
uint32_t panic_get_address(const void* f)
{
return ((XtExcFrame*)f)->pc;
}
uint32_t panic_get_cause(const void* f)
{
return ((XtExcFrame*)f)->exccause;
}
void panic_set_address(void *f, uint32_t addr)
{
((XtExcFrame*)f)->pc = addr;
}
void panic_print_backtrace(const void *f, int core)
{
// [refactor-todo] once debug helpers have support for both xtensa and riscv, move to
// common panic_handler.c
XtExcFrame *frame = (XtExcFrame *) f;
int depth = 100;
//Initialize stk_frame with first frame of stack
esp_backtrace_frame_t stk_frame = {.pc = frame->pc, .sp = frame->a1, .next_pc = frame->a0};
panic_print_str("\r\nBacktrace:");
print_backtrace_entry(esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
//Check if first frame is valid
bool corrupted = !(esp_stack_ptr_is_sane(stk_frame.sp) &&
(esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc)) ||
/* Ignore the first corrupted PC in case of InstrFetchProhibited */
frame->exccause == EXCCAUSE_INSTR_PROHIBITED));
uint32_t i = ((depth <= 0) ? INT32_MAX : depth) - 1; //Account for stack frame that's already printed
while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted) {
if (!esp_backtrace_get_next_frame(&stk_frame)) { //Get next stack frame
corrupted = true;
}
panic_print_str(" ");
print_backtrace_entry(esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
}
//Print backtrace termination marker
if (corrupted) {
panic_print_str(" |<-CORRUPTED");
} else if (stk_frame.next_pc != 0) { //Backtrace continues
panic_print_str(" |<-CONTINUES");
}
} }

View File

@ -1,2 +0,0 @@
COMPONENT_SRCDIRS += port port/esp32 port/arch/xtensa
COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o

View File

@ -0,0 +1,220 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdlib.h>
#include "esp_spi_flash.h"
#include "esp_private/system_internal.h"
#include "soc/soc_memory_layout.h"
#include "soc/cpu.h"
#include "soc/soc_caps.h"
#include "soc/rtc.h"
#include "hal/soc_hal.h"
#include "hal/cpu_hal.h"
#include "sdkconfig.h"
#include "esp_rom_sys.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/dport_access.h"
#include "esp32/cache_err_int.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/memprot.h"
#include "esp32s2/cache_err_int.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/memprot.h"
#include "esp32s3/cache_err_int.h"
#endif
#include "esp_private/panic_internal.h"
#include "esp_private/panic_reason.h"
#include "hal/wdt_types.h"
#include "hal/wdt_hal.h"
extern int _invalid_pc_placeholder;
extern void esp_panic_handler(panic_info_t*);
static wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
void *g_exc_frames[SOC_CPU_CORES_NUM] = {NULL};
/*
Panic handlers; these get called when an unhandled exception occurs or the assembly-level
task switching / interrupt code runs into an unrecoverable error. The default task stack
overflow handler and abort handler are also in here.
*/
/*
Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled.
*/
static void print_state_for_core(const void *f, int core)
{
if (!g_panic_abort) {
panic_print_registers(f, core);
panic_print_str("\r\n");
}
panic_print_backtrace(f, core);
}
static void print_state(const void *f)
{
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
int err_core = f == g_exc_frames[0] ? 0 : 1;
#else
int err_core = 0;
#endif
print_state_for_core(f, err_core);
panic_print_str("\r\n");
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
// If there are other frame info, print them as well
for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
// `f` is the frame for the offending core, see note above.
if (err_core != i && g_exc_frames[i] != NULL) {
print_state_for_core(g_exc_frames[i], i);
panic_print_str("\r\n");
}
}
#endif
}
static void frame_to_panic_info(void *frame, panic_info_t *info, bool pseudo_excause)
{
info->core = cpu_hal_get_core_id();
info->exception = PANIC_EXCEPTION_FAULT;
info->details = NULL;
info->reason = "Unknown";
info->pseudo_excause = pseudo_excause;
if (pseudo_excause) {
panic_soc_fill_info(frame, info);
} else {
panic_arch_fill_info(frame, info);
}
info->state = print_state;
info->frame = frame;
}
static void panic_handler(void *frame, bool pseudo_excause)
{
/*
* Setup environment and perform necessary architecture/chip specific
* steps here prior to the system panic handler.
* */
int core_id = cpu_hal_get_core_id();
// If multiple cores arrive at panic handler, save frames for all of them
g_exc_frames[core_id] = frame;
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
// 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) {
;
}
}
}
esp_rom_delay_us(1);
SOC_HAL_STALL_OTHER_CORES();
#endif
#if CONFIG_IDF_TARGET_ESP32
esp_dport_access_int_abort();
#endif
#if !CONFIG_ESP_PANIC_HANDLER_IRAM
// Re-enable CPU cache for current CPU if it was disabled
if (!spi_flash_cache_enabled()) {
spi_flash_enable_cache(core_id);
panic_print_str("Re-enable cpu cache.\r\n");
}
#endif
if (esp_cpu_in_ocd_debug_mode()) {
#if __XTENSA__
if (!(esp_ptr_executable(cpu_ll_pc_to_ptr(panic_get_address(frame))) && (panic_get_address(frame) & 0xC0000000U))) {
/* Xtensa ABI sets the 2 MSBs of the PC according to the windowed call size
* Incase the PC is invalid, GDB will fail to translate addresses to function names
* Hence replacing the PC to a placeholder address in case of invalid PC
*/
panic_set_address(frame, (uint32_t)&_invalid_pc_placeholder);
}
#endif
if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 ||
panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1) {
wdt_hal_write_protect_disable(&wdt0_context);
wdt_hal_handle_intr(&wdt0_context);
wdt_hal_write_protect_enable(&wdt0_context);
}
}
// Convert architecture exception frame into abstracted panic info
panic_info_t info;
frame_to_panic_info(frame, &info, pseudo_excause);
// Call the system panic handler
esp_panic_handler(&info);
}
void panicHandler(void *frame)
{
// This panic handler gets called for when the double exception vector,
// kernel exception vector gets used; as well as handling interrupt-based
// faults cache error, wdt expiry. EXCAUSE register gets written with
// one of PANIC_RSN_* values.
panic_handler(frame, true);
}
void xt_unhandled_exception(void *frame)
{
panic_handler(frame, false);
}
void __attribute__((noreturn)) panic_restart(void)
{
bool digital_reset_needed = false;
#ifdef CONFIG_IDF_TARGET_ESP32
// On the ESP32, cache error status can only be cleared by system reset
if (esp_cache_err_get_cpuid() != -1) {
digital_reset_needed = true;
}
#endif
#if CONFIG_IDF_TARGET_ESP32S2
if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
digital_reset_needed = true;
}
#endif
if (digital_reset_needed) {
esp_restart_noos_dig();
}
esp_restart_noos();
}

View File

@ -1,8 +1,8 @@
set(srcs "dport_panic_highint_hdl.S" set(srcs "dport_panic_highint_hdl.S"
"clk.c" "clk.c"
"reset_reason.c" "reset_reason.c"
"../arch/xtensa/panic_handler.c" "../../arch/xtensa/panic_arch.c"
"../arch/xtensa/panic_handler_asm.S" "../../arch/xtensa/panic_handler_asm.S"
) )
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})

View File

@ -177,7 +177,8 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
wdt_hal_write_protect_enable(&rtc_wdt_ctx); wdt_hal_write_protect_enable(&rtc_wdt_ctx);
#endif #endif
rtc_cpu_freq_config_t old_config, new_config; rtc_cpu_freq_config_t old_config;
rtc_cpu_freq_config_t new_config;
rtc_clk_cpu_freq_get_config(&old_config); rtc_clk_cpu_freq_get_config(&old_config);
const uint32_t old_freq_mhz = old_config.freq_mhz; const uint32_t old_freq_mhz = old_config.freq_mhz;
const uint32_t new_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; const uint32_t new_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
@ -205,7 +206,9 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
*/ */
__attribute__((weak)) void esp_perip_clk_init(void) __attribute__((weak)) void esp_perip_clk_init(void)
{ {
uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; uint32_t common_perip_clk;
uint32_t hwcrypto_perip_clk;
uint32_t wifi_bt_sdio_clk;
#if CONFIG_FREERTOS_UNICORE #if CONFIG_FREERTOS_UNICORE
RESET_REASON rst_reas[1]; RESET_REASON rst_reas[1];

View File

@ -0,0 +1,2 @@
COMPONENT_SRCDIRS += port port/soc/esp32 port/arch/xtensa
COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o

View File

@ -2,8 +2,8 @@ set(srcs "async_memcpy_impl_cp_dma.c"
"dport_panic_highint_hdl.S" "dport_panic_highint_hdl.S"
"clk.c" "clk.c"
"reset_reason.c" "reset_reason.c"
"../arch/xtensa/panic_handler.c" "../../arch/xtensa/panic_arch.c"
"../arch/xtensa/panic_handler_asm.S" "../../arch/xtensa/panic_handler_asm.S"
) )
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})

View File

@ -1,9 +1,9 @@
set(srcs "dport_panic_highint_hdl.S" set(srcs "dport_panic_highint_hdl.S"
"clk.c" "clk.c"
"reset_reason.c" "reset_reason.c"
"../async_memcpy_impl_gdma.c" "../../async_memcpy_impl_gdma.c"
"../arch/xtensa/panic_handler.c" "../../arch/xtensa/panic_arch.c"
"../arch/xtensa/panic_handler_asm.S" "../../arch/xtensa/panic_handler_asm.S"
) )
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})

View File

@ -0,0 +1,20 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#define PANIC_RSN_NONE 0
#define PANIC_RSN_INTWDT_CPU0 1
#define PANIC_RSN_INTWDT_CPU1 2
#define PANIC_RSN_CACHEERR 3
#define PANIC_RSN_MAX 3

View File

@ -1,8 +1,22 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __RVRUNTIME_FRAMES_H__ #ifndef __RVRUNTIME_FRAMES_H__
#define __RVRUNTIME_FRAMES_H__ #define __RVRUNTIME_FRAMES_H__
/* Align a value up to nearest n-byte boundary, where n is a power of 2. */ /* Align a value up to nearest n-byte boundary, where n is a power of 2. */
#define ALIGNUP(n, val) (((val) + (n)-1) & -(n)) #define ALIGNUP(n, val) (((val) + (n) - 1) & -(n))
#ifdef STRUCT_BEGIN #ifdef STRUCT_BEGIN
#undef STRUCT_BEGIN #undef STRUCT_BEGIN
@ -12,19 +26,15 @@
#endif #endif
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) #if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
#define STRUCT_BEGIN .pushsection .text; .struct 0 #define STRUCT_BEGIN .pushsection .text; .struct 0
#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size #define STRUCT_FIELD(ctype,size,asname,name) asname: .space size
#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n) #define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n)
#define STRUCT_END(sname) sname##Size:; .popsection #define STRUCT_END(sname) sname##Size:; .popsection
#else #else
#define STRUCT_BEGIN typedef struct { #define STRUCT_BEGIN typedef struct {
#define STRUCT_FIELD(ctype,size,asname,name) ctype name; #define STRUCT_FIELD(ctype,size,asname,name) ctype name;
#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n]; #define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n];
#define STRUCT_END(sname) } sname; #define STRUCT_END(sname) } sname;
#endif #endif
/* /*
@ -33,63 +43,54 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
STRUCT_BEGIN STRUCT_BEGIN
STRUCT_FIELD (long, 4, RV_STK_MEPC, mepc) /* Machine Exception Program Counter */ STRUCT_FIELD (long, 4, RV_STK_MEPC, mepc) /* Machine Exception Program Counter */
STRUCT_FIELD (long, 4, RV_STK_RA, ra) /* Return address */ STRUCT_FIELD (long, 4, RV_STK_RA, ra) /* Return address */
STRUCT_FIELD (long, 4, RV_STK_SP, sp) /* Stack pointer */ STRUCT_FIELD (long, 4, RV_STK_SP, sp) /* Stack pointer */
STRUCT_FIELD (long, 4, RV_STK_GP, gp) /* Global pointer */ STRUCT_FIELD (long, 4, RV_STK_GP, gp) /* Global pointer */
STRUCT_FIELD (long, 4, RV_STK_TP, tp) /* Thread pointer */ STRUCT_FIELD (long, 4, RV_STK_TP, tp) /* Thread pointer */
STRUCT_FIELD (long, 4, RV_STK_T0, t0) /* Temporary/alternate link register */ STRUCT_FIELD (long, 4, RV_STK_T0, t0) /* Temporary/alternate link register */
STRUCT_FIELD (long, 4, RV_STK_T1, t1) /* t1-2: Temporaries */ STRUCT_FIELD (long, 4, RV_STK_T1, t1) /* t1-2: Temporaries */
STRUCT_FIELD (long, 4, RV_STK_T2, t2) STRUCT_FIELD (long, 4, RV_STK_T2, t2)
STRUCT_FIELD (long, 4, RV_STK_S0, s0) /* Saved register/frame pointer */ STRUCT_FIELD (long, 4, RV_STK_S0, s0) /* Saved register/frame pointer */
STRUCT_FIELD (long, 4, RV_STK_S1, s1) /* Saved register */ STRUCT_FIELD (long, 4, RV_STK_S1, s1) /* Saved register */
STRUCT_FIELD (long, 4, RV_STK_A0, a0) /* a0-1: Function arguments/return address */ STRUCT_FIELD (long, 4, RV_STK_A0, a0) /* a0-1: Function arguments/return address */
STRUCT_FIELD (long, 4, RV_STK_A1, a1) STRUCT_FIELD (long, 4, RV_STK_A1, a1)
STRUCT_FIELD (long, 4, RV_STK_A2, a2) /* a2-7: Function arguments */ STRUCT_FIELD (long, 4, RV_STK_A2, a2) /* a2-7: Function arguments */
STRUCT_FIELD (long, 4, RV_STK_A3, a3) STRUCT_FIELD (long, 4, RV_STK_A3, a3)
STRUCT_FIELD (long, 4, RV_STK_A4, a4) STRUCT_FIELD (long, 4, RV_STK_A4, a4)
STRUCT_FIELD (long, 4, RV_STK_A5, a5) STRUCT_FIELD (long, 4, RV_STK_A5, a5)
STRUCT_FIELD (long, 4, RV_STK_A6, a6) STRUCT_FIELD (long, 4, RV_STK_A6, a6)
STRUCT_FIELD (long, 4, RV_STK_A7, a7) STRUCT_FIELD (long, 4, RV_STK_A7, a7)
STRUCT_FIELD (long, 4, RV_STK_S2, s2) /* s2-11: Saved registers */ STRUCT_FIELD (long, 4, RV_STK_S2, s2) /* s2-11: Saved registers */
STRUCT_FIELD (long, 4, RV_STK_S3, s3) STRUCT_FIELD (long, 4, RV_STK_S3, s3)
STRUCT_FIELD (long, 4, RV_STK_S4, s4) STRUCT_FIELD (long, 4, RV_STK_S4, s4)
STRUCT_FIELD (long, 4, RV_STK_S5, s5) STRUCT_FIELD (long, 4, RV_STK_S5, s5)
STRUCT_FIELD (long, 4, RV_STK_S6, s6) STRUCT_FIELD (long, 4, RV_STK_S6, s6)
STRUCT_FIELD (long, 4, RV_STK_S7, s7) STRUCT_FIELD (long, 4, RV_STK_S7, s7)
STRUCT_FIELD (long, 4, RV_STK_S8, s8) STRUCT_FIELD (long, 4, RV_STK_S8, s8)
STRUCT_FIELD (long, 4, RV_STK_S9, s9) STRUCT_FIELD (long, 4, RV_STK_S9, s9)
STRUCT_FIELD (long, 4, RV_STK_S10, s10) STRUCT_FIELD (long, 4, RV_STK_S10, s10)
STRUCT_FIELD (long, 4, RV_STK_S11, s11) STRUCT_FIELD (long, 4, RV_STK_S11, s11)
STRUCT_FIELD (long, 4, RV_STK_T3, t3) /* t3-6: Temporaries */ STRUCT_FIELD (long, 4, RV_STK_T3, t3) /* t3-6: Temporaries */
STRUCT_FIELD (long, 4, RV_STK_T4, t4) STRUCT_FIELD (long, 4, RV_STK_T4, t4)
STRUCT_FIELD (long, 4, RV_STK_T5, t5) STRUCT_FIELD (long, 4, RV_STK_T5, t5)
STRUCT_FIELD (long, 4, RV_STK_T6, t6) STRUCT_FIELD (long, 4, RV_STK_T6, t6)
STRUCT_FIELD (long, 4, RV_STK_MSTATUS, mstatus) /* Machine Status */ STRUCT_FIELD (long, 4, RV_STK_MSTATUS, mstatus) /* Machine Status */
STRUCT_FIELD (long, 4, RV_STK_MTVEC, mtvec) /* Machine Trap-Vector Base Address */ STRUCT_FIELD (long, 4, RV_STK_MTVEC, mtvec) /* Machine Trap-Vector Base Address */
STRUCT_FIELD (long, 4, RV_STK_MCAUSE, mcause) /* Machine Trap Cause */ STRUCT_FIELD (long, 4, RV_STK_MCAUSE, mcause) /* Machine Trap Cause */
STRUCT_FIELD (long, 4, RV_STK_PCCRS, pccrs) /* Performance Counter Counter Registers */ STRUCT_FIELD (long, 4, RV_STK_MTVAL, mtval) /* Machine Trap Value */
STRUCT_FIELD (long, 4, RV_STK_PCER, pcer) /* Performance Counter Enable */ STRUCT_FIELD (long, 4, RV_STK_MHARTID, mhartid) /* Hardware Thread ID in machine mode */
STRUCT_FIELD (long, 4, RV_STK_PCMR, pcmr) /* Performance Counter Mode */
STRUCT_FIELD (long, 4, RV_STK_HWLP, hwlp) /* Hardware Loop Registers */
STRUCT_FIELD (long, 4, RV_STK_PRIVLV, privlv) /* Privilege Level */
STRUCT_FIELD (long, 4, RV_STK_UHARTID, uhartid) /* Hardware Thread ID */
STRUCT_FIELD (long, 4, RV_STK_MHARTID, mhartid) /* Hardware Thread ID */
STRUCT_FIELD (long, 4, RV_STK_DCSR, dcsr) /* Debug Control and Status */
STRUCT_FIELD (long, 4, RV_STK_DPC, dpc) /* Debug PC */
STRUCT_FIELD (long, 4, RV_STK_INTC_THRESH, intc_thresh)
STRUCT_FIELD (long, 4, RV_STK_RESERVED0, reserved0)
STRUCT_END(RvExcFrame) STRUCT_END(RvExcFrame)
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) #if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
# define RV_STK_SZ1 RvExcFrameSize #define RV_STK_SZ1 RvExcFrameSize
#else #else
# define RV_STK_SZ1 sizeof(RvExcFrame) #define RV_STK_SZ1 sizeof(RvExcFrame)
#endif #endif
/* /*
* This is the frame size. * Exception stack frame size, after align up to 16 bytes boundary
*/ */
#define RV_STK_FRMSZ (ALIGNUP(0x10, RV_STK_SZ1)) #define RV_STK_FRMSZ (ALIGNUP(0x10, RV_STK_SZ1))
#endif /* #ifndef __RVRUNTIME_FRAMES_H__ */ #endif /* #ifndef __RVRUNTIME_FRAMES_H__ */

View File

@ -13,101 +13,85 @@
// limitations under the License. // limitations under the License.
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/interrupt_reg.h" #include "soc/interrupt_reg.h"
#include "riscv/rvruntime-frames.h"
.equ SAVE_REGS, 32 .equ SAVE_REGS, 32
.equ CONTEXT_SIZE, (SAVE_REGS * 4) .equ CONTEXT_SIZE, (SAVE_REGS * 4)
.equ PANIC_REGS, 38
.equ PANIC_REGS_SIZE, (PANIC_REGS * 4)
.altmacro
.macro lwsp a, b
lw \a, ((\b)*4)(sp)
.endm
.macro swsp a, b
sw \a, ((\b)*4)(sp)
.endm
.macro save_regs .macro save_regs
addi sp, sp, -CONTEXT_SIZE addi sp, sp, -CONTEXT_SIZE
swsp ra, 1 sw ra, RV_STK_RA(sp)
swsp a0, 2 sw tp, RV_STK_TP(sp)
swsp a1, 3 sw t0, RV_STK_T0(sp)
swsp a2, 4 sw t1, RV_STK_T1(sp)
swsp a3, 5 sw t2, RV_STK_T2(sp)
swsp a4, 6 sw s0, RV_STK_S0(sp)
swsp a5, 7 sw s1, RV_STK_S1(sp)
swsp a6, 8 sw a0, RV_STK_A0(sp)
swsp a7, 9 sw a1, RV_STK_A1(sp)
swsp t0, 10 sw a2, RV_STK_A2(sp)
swsp t1, 11 sw a3, RV_STK_A3(sp)
swsp t2, 12 sw a4, RV_STK_A4(sp)
swsp t3, 13 sw a5, RV_STK_A5(sp)
swsp t4, 14 sw a6, RV_STK_A6(sp)
swsp t5, 15 sw a7, RV_STK_A7(sp)
swsp t6, 16 sw s2, RV_STK_S2(sp)
//swsp sp, 17 sw s3, RV_STK_S3(sp)
//swsp gp, 18 sw s4, RV_STK_S4(sp)
swsp tp, 19 sw s5, RV_STK_S5(sp)
swsp s0, 20 sw s6, RV_STK_S6(sp)
swsp s1, 21 sw s7, RV_STK_S7(sp)
swsp s2, 22 sw s8, RV_STK_S8(sp)
swsp s3, 23 sw s9, RV_STK_S9(sp)
swsp s4, 24 sw s10, RV_STK_S10(sp)
swsp s5, 25 sw s11, RV_STK_S11(sp)
swsp s6, 26 sw t3, RV_STK_T3(sp)
swsp s7, 27 sw t4, RV_STK_T4(sp)
swsp s8, 28 sw t5, RV_STK_T5(sp)
swsp s9, 29 sw t6, RV_STK_T6(sp)
swsp s10, 30
swsp s11, 31
.endm .endm
.macro save_mepc .macro save_mepc
csrr t0, mepc csrr t0, mepc
swsp t0, 0 sw t0, RV_STK_MEPC(sp)
.endm .endm
.macro restore_regs .macro restore_regs
lwsp ra, 1 lw ra, RV_STK_RA(sp)
lwsp a0, 2 lw tp, RV_STK_TP(sp)
lwsp a1, 3 lw t0, RV_STK_T0(sp)
lwsp a2, 4 lw t1, RV_STK_T1(sp)
lwsp a3, 5 lw t2, RV_STK_T2(sp)
lwsp a4, 6 lw s0, RV_STK_S0(sp)
lwsp a5, 7 lw s1, RV_STK_S1(sp)
lwsp a6, 8 lw a0, RV_STK_A0(sp)
lwsp a7, 9 lw a1, RV_STK_A1(sp)
lwsp t0, 10 lw a2, RV_STK_A2(sp)
lwsp t1, 11 lw a3, RV_STK_A3(sp)
lwsp t2, 12 lw a4, RV_STK_A4(sp)
lwsp t3, 13 lw a5, RV_STK_A5(sp)
lwsp t4, 14 lw a6, RV_STK_A6(sp)
lwsp t5, 15 lw a7, RV_STK_A7(sp)
lwsp t6, 16 lw s2, RV_STK_S2(sp)
//lwsp sp, 17 lw s3, RV_STK_S3(sp)
//lwsp gp, 18 lw s4, RV_STK_S4(sp)
lwsp tp, 19 lw s5, RV_STK_S5(sp)
lwsp s0, 20 lw s6, RV_STK_S6(sp)
lwsp s1, 21 lw s7, RV_STK_S7(sp)
lwsp s2, 22 lw s8, RV_STK_S8(sp)
lwsp s3, 23 lw s9, RV_STK_S9(sp)
lwsp s4, 24 lw s10, RV_STK_S10(sp)
lwsp s5, 25 lw s11, RV_STK_S11(sp)
lwsp s6, 26 lw t3, RV_STK_T3(sp)
lwsp s7, 27 lw t4, RV_STK_T4(sp)
lwsp s8, 28 lw t5, RV_STK_T5(sp)
lwsp s9, 29 lw t6, RV_STK_T6(sp)
lwsp s10, 30
lwsp s11, 31
addi sp, sp, CONTEXT_SIZE addi sp, sp, CONTEXT_SIZE
.endm .endm
.macro restore_mepc .macro restore_mepc
lwsp t0, 0 lw t0, RV_STK_MEPC(sp)
csrw mepc, t0 csrw mepc, t0
.endm .endm
@ -143,61 +127,61 @@ _vector_table:
.size _vector_table, .-_vector_table .size _vector_table, .-_vector_table
/* Exception handler.*/ /* Exception handler.*/
.global panicHandler .global xt_unhandled_exception
.type _panic_handler, @function .type _panic_handler, @function
_panic_handler: _panic_handler:
addi sp, sp, -PANIC_REGS_SIZE addi sp, sp, -RV_STK_FRMSZ /* allocate space on stack to store necessary registers */
swsp x0, 0 /* save general registers */
swsp x1, 1 sw ra, RV_STK_RA(sp)
/* x2 is sp - it will be placed on stack later (after we can use the other registers for computation) */ sw gp, RV_STK_GP(sp)
swsp x3, 3 sw tp, RV_STK_TP(sp)
swsp x4, 4 sw t0, RV_STK_T0(sp)
swsp x5, 5 sw t1, RV_STK_T1(sp)
swsp x6, 6 sw t2, RV_STK_T2(sp)
swsp x7, 7 sw s0, RV_STK_S0(sp)
swsp x8, 8 sw s1, RV_STK_S1(sp)
swsp x9, 9 sw a0, RV_STK_A0(sp)
swsp x10, 10 sw a1, RV_STK_A1(sp)
swsp x11, 11 sw a2, RV_STK_A2(sp)
swsp x12, 12 sw a3, RV_STK_A3(sp)
swsp x13, 13 sw a4, RV_STK_A4(sp)
swsp x14, 14 sw a5, RV_STK_A5(sp)
swsp x15, 15 sw a6, RV_STK_A6(sp)
swsp x16, 16 sw a7, RV_STK_A7(sp)
swsp x17, 17 sw s2, RV_STK_S2(sp)
swsp x18, 18 sw s3, RV_STK_S3(sp)
swsp x19, 19 sw s4, RV_STK_S4(sp)
swsp x20, 20 sw s5, RV_STK_S5(sp)
swsp x21, 21 sw s6, RV_STK_S6(sp)
swsp x22, 22 sw s7, RV_STK_S7(sp)
swsp x23, 23 sw s8, RV_STK_S8(sp)
swsp x24, 24 sw s9, RV_STK_S9(sp)
swsp x25, 25 sw s10, RV_STK_S10(sp)
swsp x26, 26 sw s11, RV_STK_S11(sp)
swsp x27, 27 sw t3, RV_STK_T3(sp)
swsp x28, 28 sw t4, RV_STK_T4(sp)
swsp x29, 29 sw t5, RV_STK_T5(sp)
swsp x30, 30 sw t6, RV_STK_T6(sp)
swsp x31, 31 addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */
/* "Undo" the modification already done to the sp (x2) by the panic handler */ sw t0, RV_STK_SP(sp)
addi a1, x2, PANIC_REGS_SIZE csrr t0, mepc
swsp a1, 2 sw t0, RV_STK_MEPC(sp)
csrr a1, mcause csrr t0, mstatus
swsp a1, 32 sw t0, RV_STK_MSTATUS(sp)
csrr a1, mepc csrr t0, mtvec
swsp a1, 33 sw t0, RV_STK_MTVEC(sp)
csrr a1, mhartid csrr t0, mcause
swsp a1, 34 sw t0, RV_STK_MCAUSE(sp)
csrr a1, mstatus csrr t0, mtval
swsp a1, 35 sw t0, RV_STK_MTVAL(sp)
csrr a1, mtval csrr t0, mhartid
swsp a1, 36 sw t0, RV_STK_MHARTID(sp)
csrr a1, mtvec
swsp a1, 37 /* call xt_unhandled_exception(sp,cause) */
mv a0, sp mv a0, sp
csrr a1, mcause csrr a1, mcause
jal zero, panicHandler jal zero, xt_unhandled_exception
/* panicHandler never returns */ /* panicHandler never returns */
.size _panic_handler, .-_panic_handler .size _panic_handler, .-_panic_handler
/* This is the interrupt handler. /* This is the interrupt handler.
@ -215,16 +199,15 @@ _interrupt_handler:
/* scheduler not enabled, jump directly to ISR handler */ /* scheduler not enabled, jump directly to ISR handler */
lw t0, uxSchedulerRunning lw t0, uxSchedulerRunning
beq t0,zero,already_on_handler beq t0, zero, already_on_handler
/* increments the ISR nesting count */ /* increments the ISR nesting count */
/* This will work properly when we have nested interrupts */
la t0, uxInterruptNesting la t0, uxInterruptNesting
lw t1, 0x0(t0) lw t1, 0x0(t0)
addi t2,t1,1 addi t2,t1,1
sw t2, 0x0(t0) sw t2, 0x0(t0)
/* If reached here from another low-prio ISR, skip stack pushing to TCB */ /* If reached here from another low priority ISR, skip stack pushing to TCB */
bne t1,zero, already_on_handler bne t1,zero, already_on_handler
/* Otherwise, save current sp, and use the isr stack from here */ /* Otherwise, save current sp, and use the isr stack from here */
@ -242,7 +225,7 @@ already_on_handler:
lw s3, 0(t0) lw s3, 0(t0)
/* Increase interrupt threshold level */ /* Increase interrupt threshold level */
la t2, 0x7fffffff li t2, 0x7fffffff
and t1, s1, t2 /* t1 = mcause & mask */ and t1, s1, t2 /* t1 = mcause & mask */
slli t1, t1, 2 /* t1 = mcause * 4 */ slli t1, t1, 2 /* t1 = mcause * 4 */
la t2, INTC_INT_PRIO_REG(0) la t2, INTC_INT_PRIO_REG(0)
@ -252,14 +235,14 @@ already_on_handler:
sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */ sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */
fence fence
la t0, 0x8 li t0, 0x8
csrrs t0, mstatus, t0 csrrs t0, mstatus, t0
/* call the C dispatcher */ /* call the C dispatcher */
mv a0, sp /* argument 1, stack pointer */ mv a0, sp /* argument 1, stack pointer */
csrr a1, mcause /* argument 2, interrupt number */ csrr a1, mcause /* argument 2, interrupt number */
/* mask off the interrupt flag of mcause */ /* mask off the interrupt flag of mcause */
la t0, 0x7fffffff li t0, 0x7fffffff
and a1, a1, t0 and a1, a1, t0
jal _global_interrupt_handler jal _global_interrupt_handler
@ -281,7 +264,7 @@ already_on_handler:
la t0, uxInterruptNesting la t0, uxInterruptNesting
lw t1, 0x0(t0) lw t1, 0x0(t0)
/* Already zero, protect againts underflow */ /* Already zero, protect against underflow */
beq t1, zero, isr_skip_decrement beq t1, zero, isr_skip_decrement
addi t1,t1, -1 addi t1,t1, -1
sw t1, 0x0(t0) sw t1, 0x0(t0)
@ -290,7 +273,7 @@ isr_skip_decrement:
/* may still have interrupts pending, skip section below and exit */ /* may still have interrupts pending, skip section below and exit */
bne t1,zero,isr_exit bne t1,zero,isr_exit
/* handlered all the ISRs and scheduled the next task, take its stack */ /* handled all the ISRs and scheduled the next task, take its stack */
/* load on sp, then exit. */ /* load on sp, then exit. */
lw sp, pxCurrentTCB lw sp, pxCurrentTCB
lw sp, 0x0(sp) lw sp, 0x0(sp)

View File

@ -31,7 +31,7 @@ Using these symbols is done by creating an assembly file (suffix .S) and definin
rsr a0, EXCSAVE_5 rsr a0, EXCSAVE_5
rfi 5 rfi 5
For a real-life example, see the :component_file:`esp_system/port/{IDF_TARGET_PATH_NAME}/dport_panic_highint_hdl.S` file; the panic handler interrupt is implemented there. For a real-life example, see the :component_file:`esp_system/port/soc/{IDF_TARGET_PATH_NAME}/dport_panic_highint_hdl.S` file; the panic handler interrupt is implemented there.
Notes Notes

View File

@ -17299,7 +17299,7 @@ END GROUP
.literal.commonErrorHandler .literal.commonErrorHandler
0x0000000040080b80 0x4 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o) 0x0000000040080b80 0x4 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o)
0x28 (size before relaxing) 0x28 (size before relaxing)
.literal.panicHandler .literal.panic_handle_pseudo_exception
0x0000000040080b84 0x38 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o) 0x0000000040080b84 0x38 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o)
0xc0 (size before relaxing) 0xc0 (size before relaxing)
.literal.xt_unhandled_exception .literal.xt_unhandled_exception
@ -18250,10 +18250,10 @@ END GROUP
0x0000000040087c34 0x44 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o) 0x0000000040087c34 0x44 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o)
0x56 (size before relaxing) 0x56 (size before relaxing)
*fill* 0x0000000040087c78 0x0 *fill* 0x0000000040087c78 0x0
.text.panicHandler .text.panic_handle_pseudo_exception
0x0000000040087c78 0x1a0 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o) 0x0000000040087c78 0x1a0 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o)
0x1cc (size before relaxing) 0x1cc (size before relaxing)
0x0000000040087c78 panicHandler 0x0000000040087c78 panic_handle_pseudo_exception
.text.xt_unhandled_exception .text.xt_unhandled_exception
0x0000000040087e18 0x77 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o) 0x0000000040087e18 0x77 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o)
0xa1 (size before relaxing) 0xa1 (size before relaxing)

View File

@ -8909,7 +8909,7 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-el
.literal.vApplicationStackOverflowHook .literal.vApplicationStackOverflowHook
0x0000000040080bb8 0x8 esp-idf/esp32/libesp32.a(panic.c.obj) 0x0000000040080bb8 0x8 esp-idf/esp32/libesp32.a(panic.c.obj)
0x18 (size before relaxing) 0x18 (size before relaxing)
.literal.panicHandler .literal.panic_handle_pseudo_exception
0x0000000040080bc0 0x34 esp-idf/esp32/libesp32.a(panic.c.obj) 0x0000000040080bc0 0x34 esp-idf/esp32/libesp32.a(panic.c.obj)
0xa8 (size before relaxing) 0xa8 (size before relaxing)
.literal.xt_unhandled_exception .literal.xt_unhandled_exception
@ -10153,10 +10153,10 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-el
0x23 (size before relaxing) 0x23 (size before relaxing)
0x0000000040086bd0 vApplicationStackOverflowHook 0x0000000040086bd0 vApplicationStackOverflowHook
*fill* 0x0000000040086be7 0x1 *fill* 0x0000000040086be7 0x1
.text.panicHandler .text.panic_handle_pseudo_exception
0x0000000040086be8 0x165 esp-idf/esp32/libesp32.a(panic.c.obj) 0x0000000040086be8 0x165 esp-idf/esp32/libesp32.a(panic.c.obj)
0x19c (size before relaxing) 0x19c (size before relaxing)
0x0000000040086be8 panicHandler 0x0000000040086be8 panic_handle_pseudo_exception
*fill* 0x0000000040086d4d 0x3 *fill* 0x0000000040086d4d 0x3
.text.xt_unhandled_exception .text.xt_unhandled_exception
0x0000000040086d50 0x88 esp-idf/esp32/libesp32.a(panic.c.obj) 0x0000000040086d50 0x88 esp-idf/esp32/libesp32.a(panic.c.obj)
@ -10939,7 +10939,7 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-el
.rodata.vApplicationStackOverflowHook.str1.4 .rodata.vApplicationStackOverflowHook.str1.4
0x000000003ffb1cbc 0x3e esp-idf/esp32/libesp32.a(panic.c.obj) 0x000000003ffb1cbc 0x3e esp-idf/esp32/libesp32.a(panic.c.obj)
*fill* 0x000000003ffb1cfa 0x2 *fill* 0x000000003ffb1cfa 0x2
.rodata.panicHandler.str1.4 .rodata.panic_handle_pseudo_exception.str1.4
0x000000003ffb1cfc 0x1a9 esp-idf/esp32/libesp32.a(panic.c.obj) 0x000000003ffb1cfc 0x1a9 esp-idf/esp32/libesp32.a(panic.c.obj)
*fill* 0x000000003ffb1ea5 0x3 *fill* 0x000000003ffb1ea5 0x3
.rodata.xt_unhandled_exception.str1.4 .rodata.xt_unhandled_exception.str1.4
@ -17060,7 +17060,7 @@ newlib_include_locks_impl esp-idf/newlib/libnewlib.a(loc
newlib_include_pthread_impl esp-idf/newlib/libnewlib.a(pthread.c.obj) newlib_include_pthread_impl esp-idf/newlib/libnewlib.a(pthread.c.obj)
newlib_include_syscalls_impl esp-idf/newlib/libnewlib.a(syscalls.c.obj) newlib_include_syscalls_impl esp-idf/newlib/libnewlib.a(syscalls.c.obj)
opendir esp-idf/vfs/libvfs.a(vfs.c.obj) opendir esp-idf/vfs/libvfs.a(vfs.c.obj)
panicHandler esp-idf/esp32/libesp32.a(panic.c.obj) panic_handle_pseudo_exception esp-idf/esp32/libesp32.a(panic.c.obj)
esp-idf/freertos/libfreertos.a(xtensa_vectors.S.obj) esp-idf/freertos/libfreertos.a(xtensa_vectors.S.obj)
esp-idf/esp32/libesp32.a(dport_panic_highint_hdl.S.obj) esp-idf/esp32/libesp32.a(dport_panic_highint_hdl.S.obj)
pcTaskGetTaskName esp-idf/freertos/libfreertos.a(tasks.c.obj) pcTaskGetTaskName esp-idf/freertos/libfreertos.a(tasks.c.obj)

View File

@ -7678,7 +7678,7 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32s2-elf/esp-2019r2-8.2.0/xtensa-esp32s
.literal.vApplicationStackOverflowHook .literal.vApplicationStackOverflowHook
0x0000000040024a4c 0x8 esp-idf/esp32s2/libesp32s2.a(panic.c.obj) 0x0000000040024a4c 0x8 esp-idf/esp32s2/libesp32s2.a(panic.c.obj)
0x18 (size before relaxing) 0x18 (size before relaxing)
.literal.panicHandler .literal.panic_handle_pseudo_exception
0x0000000040024a54 0x9c esp-idf/esp32s2/libesp32s2.a(panic.c.obj) 0x0000000040024a54 0x9c esp-idf/esp32s2/libesp32s2.a(panic.c.obj)
0x1a8 (size before relaxing) 0x1a8 (size before relaxing)
.literal.xt_unhandled_exception .literal.xt_unhandled_exception
@ -8819,10 +8819,10 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32s2-elf/esp-2019r2-8.2.0/xtensa-esp32s
0x23 (size before relaxing) 0x23 (size before relaxing)
0x0000000040029b88 vApplicationStackOverflowHook 0x0000000040029b88 vApplicationStackOverflowHook
*fill* 0x0000000040029b9f 0x1 *fill* 0x0000000040029b9f 0x1
.text.panicHandler .text.panic_handle_pseudo_exception
0x0000000040029ba0 0x31d esp-idf/esp32s2/libesp32s2.a(panic.c.obj) 0x0000000040029ba0 0x31d esp-idf/esp32s2/libesp32s2.a(panic.c.obj)
0x3a0 (size before relaxing) 0x3a0 (size before relaxing)
0x0000000040029ba0 panicHandler 0x0000000040029ba0 panic_handle_pseudo_exception
*fill* 0x0000000040029ebd 0x3 *fill* 0x0000000040029ebd 0x3
.text.xt_unhandled_exception .text.xt_unhandled_exception
0x0000000040029ec0 0x7d esp-idf/esp32s2/libesp32s2.a(panic.c.obj) 0x0000000040029ec0 0x7d esp-idf/esp32s2/libesp32s2.a(panic.c.obj)
@ -9570,7 +9570,7 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32s2-elf/esp-2019r2-8.2.0/xtensa-esp32s
.rodata.vApplicationStackOverflowHook.str1.4 .rodata.vApplicationStackOverflowHook.str1.4
0x000000003ffbd8f4 0x3e esp-idf/esp32s2/libesp32s2.a(panic.c.obj) 0x000000003ffbd8f4 0x3e esp-idf/esp32s2/libesp32s2.a(panic.c.obj)
*fill* 0x000000003ffbd932 0x2 *fill* 0x000000003ffbd932 0x2
.rodata.panicHandler.str1.4 .rodata.panic_handle_pseudo_exception.str1.4
0x000000003ffbd934 0x418 esp-idf/esp32s2/libesp32s2.a(panic.c.obj) 0x000000003ffbd934 0x418 esp-idf/esp32s2/libesp32s2.a(panic.c.obj)
.rodata.xt_unhandled_exception.str1.4 .rodata.xt_unhandled_exception.str1.4
0x000000003ffbdd4c 0x4d esp-idf/esp32s2/libesp32s2.a(panic.c.obj) 0x000000003ffbdd4c 0x4d esp-idf/esp32s2/libesp32s2.a(panic.c.obj)
@ -15047,7 +15047,7 @@ newlib_include_locks_impl esp-idf/newlib/libnewlib.a(loc
newlib_include_pthread_impl esp-idf/newlib/libnewlib.a(pthread.c.obj) newlib_include_pthread_impl esp-idf/newlib/libnewlib.a(pthread.c.obj)
newlib_include_syscalls_impl esp-idf/newlib/libnewlib.a(syscalls.c.obj) newlib_include_syscalls_impl esp-idf/newlib/libnewlib.a(syscalls.c.obj)
opendir esp-idf/vfs/libvfs.a(vfs.c.obj) opendir esp-idf/vfs/libvfs.a(vfs.c.obj)
panicHandler esp-idf/esp32s2/libesp32s2.a(panic.c.obj) panic_handle_pseudo_exception esp-idf/esp32s2/libesp32s2.a(panic.c.obj)
esp-idf/freertos/libfreertos.a(xtensa_vectors.S.obj) esp-idf/freertos/libfreertos.a(xtensa_vectors.S.obj)
esp-idf/esp32s2/libesp32s2.a(dport_panic_highint_hdl.S.obj) esp-idf/esp32s2/libesp32s2.a(dport_panic_highint_hdl.S.obj)
pcTaskGetTaskName esp-idf/freertos/libfreertos.a(tasks.c.obj) pcTaskGetTaskName esp-idf/freertos/libfreertos.a(tasks.c.obj)