mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
panic handlers: Print the PC address where abort() was called, don't dump registers
This commit is contained in:
parent
a760eb3980
commit
da977149f6
@ -42,3 +42,15 @@ void IRAM_ATTR esp_cpu_unstall(int cpu_id)
|
|||||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
|
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IRAM_ATTR esp_cpu_in_ocd_debug_mode()
|
||||||
|
{
|
||||||
|
#if CONFIG_ESP32_DEBUG_OCDAWARE
|
||||||
|
int dcr;
|
||||||
|
int reg=0x10200C; //DSRSET register
|
||||||
|
asm("rer %0,%1":"=r"(dcr):"r"(reg));
|
||||||
|
return (dcr&0x1);
|
||||||
|
#else
|
||||||
|
return false; // Always return false if "OCD aware" is disabled
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -94,4 +94,13 @@ void esp_cpu_stall(int cpu_id);
|
|||||||
*/
|
*/
|
||||||
void esp_cpu_unstall(int cpu_id);
|
void esp_cpu_unstall(int cpu_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if a JTAG debugger is attached to CPU
|
||||||
|
* OCD (on chip debug) port.
|
||||||
|
*
|
||||||
|
* @note If "Make exception and panic handlers JTAG/OCD aware"
|
||||||
|
* is disabled, this function always returns false.
|
||||||
|
*/
|
||||||
|
bool esp_cpu_in_ocd_debug_mode();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
/*
|
/*
|
||||||
Panic handlers; these get called when an unhandled exception occurs or the assembly-level
|
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
|
task switching / interrupt code runs into an unrecoverable error. The default task stack
|
||||||
overflow handler also is in here.
|
overflow handler and abort handler are also in here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -95,15 +95,29 @@ inline static void panicPutHex(int a) { }
|
|||||||
inline static void panicPutDec(int a) { }
|
inline static void panicPutDec(int a) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
|
void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
|
||||||
{
|
{
|
||||||
panicPutStr("***ERROR*** A stack overflow in task ");
|
panicPutStr("***ERROR*** A stack overflow in task ");
|
||||||
panicPutStr((char *)pcTaskName);
|
panicPutStr((char *)pcTaskName);
|
||||||
panicPutStr(" has been detected.\r\n");
|
panicPutStr(" has been detected.\r\n");
|
||||||
configASSERT(0);
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool abort_called;
|
||||||
|
|
||||||
|
void abort()
|
||||||
|
{
|
||||||
|
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||||
|
ets_printf("abort() was called at PC 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||||
|
#endif
|
||||||
|
abort_called = true;
|
||||||
|
while(1) {
|
||||||
|
__asm__ ("break 0,0");
|
||||||
|
*((int*) 0) = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *edesc[] = {
|
static const char *edesc[] = {
|
||||||
"IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
|
"IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
|
||||||
"Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue",
|
"Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue",
|
||||||
@ -118,7 +132,7 @@ static const char *edesc[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void commonErrorHandler(XtExcFrame *frame);
|
static void commonErrorHandler(XtExcFrame *frame);
|
||||||
|
|
||||||
//The fact that we've panic'ed probably means the other CPU is now running wild, possibly
|
//The fact that we've panic'ed probably means the other CPU is now running wild, possibly
|
||||||
//messing up the serial output, so we stall it here.
|
//messing up the serial output, so we stall it here.
|
||||||
@ -127,19 +141,6 @@ static void haltOtherCore()
|
|||||||
esp_cpu_stall( xPortGetCoreID() == 0 ? 1 : 0 );
|
esp_cpu_stall( xPortGetCoreID() == 0 ? 1 : 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
//Returns true when a debugger is attached using JTAG.
|
|
||||||
static int inOCDMode()
|
|
||||||
{
|
|
||||||
#if CONFIG_ESP32_DEBUG_OCDAWARE
|
|
||||||
int dcr;
|
|
||||||
int reg = 0x10200C; //DSRSET register
|
|
||||||
asm("rer %0,%1":"=r"(dcr):"r"(reg));
|
|
||||||
return (dcr & 0x1);
|
|
||||||
#else
|
|
||||||
return 0; //Always return no debugger is attached.
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void panicHandler(XtExcFrame *frame)
|
void panicHandler(XtExcFrame *frame)
|
||||||
{
|
{
|
||||||
int *regs = (int *)frame;
|
int *regs = (int *)frame;
|
||||||
@ -165,7 +166,7 @@ void panicHandler(XtExcFrame *frame)
|
|||||||
panicPutStr(reason);
|
panicPutStr(reason);
|
||||||
panicPutStr(")\r\n");
|
panicPutStr(")\r\n");
|
||||||
|
|
||||||
if (inOCDMode()) {
|
if (esp_cpu_in_ocd_debug_mode()) {
|
||||||
asm("break.n 1");
|
asm("break.n 1");
|
||||||
}
|
}
|
||||||
commonErrorHandler(frame);
|
commonErrorHandler(frame);
|
||||||
@ -197,7 +198,7 @@ void xt_unhandled_exception(XtExcFrame *frame)
|
|||||||
}
|
}
|
||||||
panicPutStr(" occurred on core ");
|
panicPutStr(" occurred on core ");
|
||||||
panicPutDec(xPortGetCoreID());
|
panicPutDec(xPortGetCoreID());
|
||||||
if (inOCDMode()) {
|
if (esp_cpu_in_ocd_debug_mode()) {
|
||||||
panicPutStr(" at pc=");
|
panicPutStr(" at pc=");
|
||||||
panicPutHex(regs[1]);
|
panicPutHex(regs[1]);
|
||||||
panicPutStr(". Setting bp and returning..\r\n");
|
panicPutStr(". Setting bp and returning..\r\n");
|
||||||
@ -255,6 +256,7 @@ static inline bool stackPointerIsSane(uint32_t sp)
|
|||||||
{
|
{
|
||||||
return !(sp < 0x3ffae010 || sp > 0x3ffffff0 || ((sp & 0xf) != 0));
|
return !(sp < 0x3ffae010 || sp > 0x3ffffff0 || ((sp & 0xf) != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void putEntry(uint32_t pc, uint32_t sp)
|
static void putEntry(uint32_t pc, uint32_t sp)
|
||||||
{
|
{
|
||||||
if (pc & 0x80000000) {
|
if (pc & 0x80000000) {
|
||||||
@ -265,7 +267,8 @@ static void putEntry(uint32_t pc, uint32_t sp)
|
|||||||
panicPutStr(":0x");
|
panicPutStr(":0x");
|
||||||
panicPutHex(sp);
|
panicPutHex(sp);
|
||||||
}
|
}
|
||||||
void doBacktrace(XtExcFrame *frame)
|
|
||||||
|
static void doBacktrace(XtExcFrame *frame)
|
||||||
{
|
{
|
||||||
uint32_t i = 0, pc = frame->pc, sp = frame->a1;
|
uint32_t i = 0, pc = frame->pc, sp = frame->a1;
|
||||||
panicPutStr("\nBacktrace:");
|
panicPutStr("\nBacktrace:");
|
||||||
@ -291,7 +294,7 @@ void doBacktrace(XtExcFrame *frame)
|
|||||||
We arrive here after a panic or unhandled exception, when no OCD is detected. Dump the registers to the
|
We arrive here after a panic or unhandled exception, when no OCD is detected. Dump the registers to the
|
||||||
serial port and either jump to the gdb stub, halt the CPU or reboot.
|
serial port and either jump to the gdb stub, halt the CPU or reboot.
|
||||||
*/
|
*/
|
||||||
void commonErrorHandler(XtExcFrame *frame)
|
static void commonErrorHandler(XtExcFrame *frame)
|
||||||
{
|
{
|
||||||
int *regs = (int *)frame;
|
int *regs = (int *)frame;
|
||||||
int x, y;
|
int x, y;
|
||||||
@ -304,21 +307,28 @@ void commonErrorHandler(XtExcFrame *frame)
|
|||||||
//Feed the watchdogs, so they will give us time to print out debug info
|
//Feed the watchdogs, so they will give us time to print out debug info
|
||||||
reconfigureAllWdts();
|
reconfigureAllWdts();
|
||||||
|
|
||||||
panicPutStr("Register dump:\r\n");
|
/* only dump registers for 'real' crashes, if crashing via abort()
|
||||||
|
the register window is no longer useful.
|
||||||
|
*/
|
||||||
|
if (!abort_called) {
|
||||||
|
panicPutStr("Register dump:\r\n");
|
||||||
|
|
||||||
for (x = 0; x < 24; x += 4) {
|
for (x = 0; x < 24; x += 4) {
|
||||||
for (y = 0; y < 4; y++) {
|
for (y = 0; y < 4; y++) {
|
||||||
if (sdesc[x + y][0] != 0) {
|
if (sdesc[x + y][0] != 0) {
|
||||||
panicPutStr(sdesc[x + y]);
|
panicPutStr(sdesc[x + y]);
|
||||||
panicPutStr(": 0x");
|
panicPutStr(": 0x");
|
||||||
panicPutHex(regs[x + y + 1]);
|
panicPutHex(regs[x + y + 1]);
|
||||||
panicPutStr(" ");
|
panicPutStr(" ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
panicPutStr("\r\n");
|
||||||
}
|
}
|
||||||
panicPutStr("\r\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* With windowed ABI backtracing is easy, let's do it. */
|
/* With windowed ABI backtracing is easy, let's do it. */
|
||||||
doBacktrace(frame);
|
doBacktrace(frame);
|
||||||
|
|
||||||
#if CONFIG_ESP32_PANIC_GDBSTUB
|
#if CONFIG_ESP32_PANIC_GDBSTUB
|
||||||
disableAllWdts();
|
disableAllWdts();
|
||||||
panicPutStr("Entering gdb stub now.\r\n");
|
panicPutStr("Entering gdb stub now.\r\n");
|
||||||
@ -339,8 +349,7 @@ void commonErrorHandler(XtExcFrame *frame)
|
|||||||
|
|
||||||
void esp_set_breakpoint_if_jtag(void *fn)
|
void esp_set_breakpoint_if_jtag(void *fn)
|
||||||
{
|
{
|
||||||
if (!inOCDMode()) {
|
if (esp_cpu_in_ocd_debug_mode()) {
|
||||||
return;
|
setFirstBreakpoint((uint32_t)fn);
|
||||||
}
|
}
|
||||||
setFirstBreakpoint((uint32_t)fn);
|
|
||||||
}
|
}
|
||||||
|
@ -22,15 +22,6 @@
|
|||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
|
|
||||||
void IRAM_ATTR abort()
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
__asm__ ("break 0,0");
|
|
||||||
*((int*) 0) = 0;
|
|
||||||
} while(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* IRAM_ATTR _malloc_r(struct _reent *r, size_t size)
|
void* IRAM_ATTR _malloc_r(struct _reent *r, size_t size)
|
||||||
{
|
{
|
||||||
return pvPortMalloc(size);
|
return pvPortMalloc(size);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user