mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
esp_system: support riscv panic
This commit is contained in:
parent
420aef1ffe
commit
4cc6b5571b
@ -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))
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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"
|
||||||
|
@ -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})
|
||||||
|
127
components/esp_system/port/arch/riscv/panic_arch.c
Normal file
127
components/esp_system/port/arch/riscv/panic_arch.c
Normal 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 = ®s;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,2 +0,0 @@
|
|||||||
COMPONENT_SRCDIRS += port port/esp32 port/arch/xtensa
|
|
||||||
COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o
|
|
220
components/esp_system/port/panic_handler.c
Normal file
220
components/esp_system/port/panic_handler.c
Normal 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();
|
||||||
|
}
|
@ -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})
|
||||||
|
|
@ -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];
|
2
components/esp_system/port/soc/esp32/component.mk
Normal file
2
components/esp_system/port/soc/esp32/component.mk
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
COMPONENT_SRCDIRS += port port/soc/esp32 port/arch/xtensa
|
||||||
|
COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o
|
@ -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})
|
||||||
|
|
@ -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})
|
||||||
|
|
20
components/riscv/include/esp_private/panic_reason.h
Normal file
20
components/riscv/include/esp_private/panic_reason.h
Normal 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
|
@ -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__ */
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user