esp32: ReformatReformat panic.c (remove tabs, etc)

This commit is contained in:
Angus Gratton 2016-12-07 13:25:26 -08:00
parent 20fd57f147
commit b98405f9d9
2 changed files with 231 additions and 190 deletions

View file

@ -34,46 +34,58 @@
#include "esp_attr.h" #include "esp_attr.h"
/* /*
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 also is in here.
*/ */
/* /*
Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled. Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled.
*/ */
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT #if !CONFIG_ESP32_PANIC_SILENT_REBOOT
//printf may be broken, so we fix our own printing fns... //printf may be broken, so we fix our own printing fns...
inline static void panicPutChar(char c) { inline static void panicPutChar(char c)
while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ; {
WRITE_PERI_REG(UART_FIFO_REG(0), c); while (((READ_PERI_REG(UART_STATUS_REG(0)) >> UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT) >= 126) ;
WRITE_PERI_REG(UART_FIFO_REG(0), c);
} }
inline static void panicPutStr(const char *c) { inline static void panicPutStr(const char *c)
int x=0; {
while (c[x]!=0) { int x = 0;
panicPutChar(c[x]); while (c[x] != 0) {
x++; panicPutChar(c[x]);
} x++;
}
} }
inline static void panicPutHex(int a) { inline static void panicPutHex(int a)
int x; {
int c; int x;
for (x=0; x<8; x++) { int c;
c=(a>>28)&0xf; for (x = 0; x < 8; x++) {
if (c<10) panicPutChar('0'+c); else panicPutChar('a'+c-10); c = (a >> 28) & 0xf;
a<<=4; if (c < 10) {
} panicPutChar('0' + c);
} else {
panicPutChar('a' + c - 10);
}
a <<= 4;
}
} }
inline static void panicPutDec(int a) { inline static void panicPutDec(int a)
int n1, n2; {
n1=a%10; int n1, n2;
n2=a/10; n1 = a % 10;
if (n2==0) panicPutChar(' '); else panicPutChar(n2+'0'); n2 = a / 10;
panicPutChar(n1+'0'); if (n2 == 0) {
panicPutChar(' ');
} else {
panicPutChar(n2 + '0');
}
panicPutChar(n1 + '0');
} }
#else #else
//No printing wanted. Stub out these functions. //No printing wanted. Stub out these functions.
@ -84,25 +96,26 @@ 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((char*)pcTaskName); panicPutStr("***ERROR*** A stack overflow in task ");
panicPutStr(" has been detected.\r\n"); panicPutStr((char *)pcTaskName);
configASSERT(0); panicPutStr(" has been detected.\r\n");
configASSERT(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",
"Privileged", "LoadStoreAlignment", "res", "res", "Privileged", "LoadStoreAlignment", "res", "res",
"InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError", "InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError",
"InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res", "InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res",
"InstrFetchProhibited", "res", "res", "res", "InstrFetchProhibited", "res", "res", "res",
"LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res", "LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res",
"LoadProhibited", "StoreProhibited", "res", "res", "LoadProhibited", "StoreProhibited", "res", "res",
"Cp0Dis", "Cp1Dis", "Cp2Dis", "Cp3Dis", "Cp0Dis", "Cp1Dis", "Cp2Dis", "Cp3Dis",
"Cp4Dis", "Cp5Dis", "Cp6Dis", "Cp7Dis" "Cp4Dis", "Cp5Dis", "Cp6Dis", "Cp7Dis"
}; };
void commonErrorHandler(XtExcFrame *frame); void commonErrorHandler(XtExcFrame *frame);
@ -115,191 +128,219 @@ static void haltOtherCore()
} }
//Returns true when a debugger is attached using JTAG. //Returns true when a debugger is attached using JTAG.
static int inOCDMode() { static int inOCDMode()
{
#if CONFIG_ESP32_DEBUG_OCDAWARE #if CONFIG_ESP32_DEBUG_OCDAWARE
int dcr; int dcr;
int reg=0x10200C; //DSRSET register int reg = 0x10200C; //DSRSET register
asm("rer %0,%1":"=r"(dcr):"r"(reg)); asm("rer %0,%1":"=r"(dcr):"r"(reg));
return (dcr&0x1); return (dcr & 0x1);
#else #else
return 0; //Always return no debugger is attached. return 0; //Always return no debugger is attached.
#endif #endif
} }
void panicHandler(XtExcFrame *frame) { void panicHandler(XtExcFrame *frame)
int *regs=(int*)frame; {
//Please keep in sync with PANIC_RSN_* defines int *regs = (int *)frame;
const char *reasons[]={ //Please keep in sync with PANIC_RSN_* defines
"Unknown reason", const char *reasons[] = {
"Unhandled debug exception", "Unknown reason",
"Double exception", "Unhandled debug exception",
"Unhandled kernel exception", "Double exception",
"Coprocessor exception", "Unhandled kernel exception",
"Interrupt wdt timeout on CPU0", "Coprocessor exception",
"Interrupt wdt timeout on CPU1", "Interrupt wdt timeout on CPU0",
}; "Interrupt wdt timeout on CPU1",
const char *reason=reasons[0]; };
//The panic reason is stored in the EXCCAUSE register. const char *reason = reasons[0];
if (regs[20]<=PANIC_RSN_MAX) reason=reasons[regs[20]]; //The panic reason is stored in the EXCCAUSE register.
haltOtherCore(); if (regs[20] <= PANIC_RSN_MAX) {
panicPutStr("Guru Meditation Error: Core "); reason = reasons[regs[20]];
panicPutDec(xPortGetCoreID()); }
panicPutStr(" panic'ed ("); haltOtherCore();
panicPutStr(reason); panicPutStr("Guru Meditation Error: Core ");
panicPutStr(")\r\n"); panicPutDec(xPortGetCoreID());
panicPutStr(" panic'ed (");
panicPutStr(reason);
panicPutStr(")\r\n");
if (inOCDMode()) { if (inOCDMode()) {
asm("break.n 1"); asm("break.n 1");
} }
commonErrorHandler(frame); commonErrorHandler(frame);
} }
static void setFirstBreakpoint(uint32_t pc) { static void setFirstBreakpoint(uint32_t pc)
asm( {
"wsr.ibreaka0 %0\n" \ asm(
"rsr.ibreakenable a3\n" \ "wsr.ibreaka0 %0\n" \
"movi a4,1\n" \ "rsr.ibreakenable a3\n" \
"or a4, a4, a3\n" \ "movi a4,1\n" \
"wsr.ibreakenable a4\n" \ "or a4, a4, a3\n" \
::"r"(pc):"a3","a4"); "wsr.ibreakenable a4\n" \
::"r"(pc):"a3", "a4");
} }
void xt_unhandled_exception(XtExcFrame *frame) { void xt_unhandled_exception(XtExcFrame *frame)
int *regs=(int*)frame; {
int x; int *regs = (int *)frame;
int x;
haltOtherCore(); haltOtherCore();
panicPutStr("Guru Meditation Error of type "); panicPutStr("Guru Meditation Error of type ");
x=regs[20]; x = regs[20];
if (x<40) panicPutStr(edesc[x]); else panicPutStr("Unknown"); if (x < 40) {
panicPutStr(" occurred on core "); panicPutStr(edesc[x]);
panicPutDec(xPortGetCoreID()); } else {
if (inOCDMode()) { panicPutStr("Unknown");
panicPutStr(" at pc="); }
panicPutHex(regs[1]); panicPutStr(" occurred on core ");
panicPutStr(". Setting bp and returning..\r\n"); panicPutDec(xPortGetCoreID());
//Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger if (inOCDMode()) {
//will kick in exactly at the context the error happened. panicPutStr(" at pc=");
setFirstBreakpoint(regs[1]); panicPutHex(regs[1]);
return; panicPutStr(". Setting bp and returning..\r\n");
} //Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger
panicPutStr(". Exception was unhandled.\r\n"); //will kick in exactly at the context the error happened.
commonErrorHandler(frame); setFirstBreakpoint(regs[1]);
return;
}
panicPutStr(". Exception was unhandled.\r\n");
commonErrorHandler(frame);
} }
/* /*
If watchdogs are enabled, the panic handler runs the risk of getting aborted pre-emptively because If watchdogs are enabled, the panic handler runs the risk of getting aborted pre-emptively because
an overzealous watchdog decides to reset it. On the other hand, if we disable all watchdogs, we run an overzealous watchdog decides to reset it. On the other hand, if we disable all watchdogs, we run
the risk of somehow halting in the panic handler and not resetting. That is why this routine kills the risk of somehow halting in the panic handler and not resetting. That is why this routine kills
all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after
one second. one second.
*/ */
static void reconfigureAllWdts() { static void reconfigureAllWdts()
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; {
TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_config0.sys_reset_length=7; //3.2uS TIMERG0.wdt_feed = 1;
TIMERG0.wdt_config0.cpu_reset_length=7; //3.2uS TIMERG0.wdt_config0.sys_reset_length = 7; //3.2uS
TIMERG0.wdt_config0.stg0=TIMG_WDT_STG_SEL_RESET_SYSTEM; //1st stage timeout: reset system TIMERG0.wdt_config0.cpu_reset_length = 7; //3.2uS
TIMERG0.wdt_config1.clk_prescale=80*500; //Prescaler: wdt counts in ticks of 0.5mS TIMERG0.wdt_config0.stg0 = TIMG_WDT_STG_SEL_RESET_SYSTEM; //1st stage timeout: reset system
TIMERG0.wdt_config2=2000; //1 second before reset TIMERG0.wdt_config1.clk_prescale = 80 * 500; //Prescaler: wdt counts in ticks of 0.5mS
TIMERG0.wdt_config0.en=1; TIMERG0.wdt_config2 = 2000; //1 second before reset
TIMERG0.wdt_wprotect=0; TIMERG0.wdt_config0.en = 1;
//Disable wdt 1 TIMERG0.wdt_wprotect = 0;
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; //Disable wdt 1
TIMERG1.wdt_config0.en=0; TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG1.wdt_wprotect=0; TIMERG1.wdt_config0.en = 0;
TIMERG1.wdt_wprotect = 0;
} }
#if CONFIG_ESP32_PANIC_GDBSTUB || CONFIG_ESP32_PANIC_PRINT_HALT #if CONFIG_ESP32_PANIC_GDBSTUB || CONFIG_ESP32_PANIC_PRINT_HALT
/* /*
This disables all the watchdogs for when we call the gdbstub. This disables all the watchdogs for when we call the gdbstub.
*/ */
static void disableAllWdts() { static void disableAllWdts()
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; {
TIMERG0.wdt_config0.en=0; TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_wprotect=0; TIMERG0.wdt_config0.en = 0;
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_wprotect = 0;
TIMERG1.wdt_config0.en=0; TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_wprotect=0; TIMERG1.wdt_config0.en = 0;
TIMERG0.wdt_wprotect = 0;
} }
#endif #endif
static inline bool stackPointerIsSane(uint32_t sp) { 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) pc = (pc & 0x3fffffff) | 0x40000000; {
panicPutStr(" 0x"); if (pc & 0x80000000) {
panicPutHex(pc); pc = (pc & 0x3fffffff) | 0x40000000;
panicPutStr(":0x"); }
panicPutHex(sp); panicPutStr(" 0x");
panicPutHex(pc);
panicPutStr(":0x");
panicPutHex(sp);
} }
void doBacktrace(XtExcFrame *frame) { void doBacktrace(XtExcFrame *frame)
uint32_t i = 0, pc = frame->pc, sp = frame->a1; {
panicPutStr("\nBacktrace:"); uint32_t i = 0, pc = frame->pc, sp = frame->a1;
/* Do not check sanity on first entry, PC could be smashed. */ panicPutStr("\nBacktrace:");
putEntry(pc, sp); /* Do not check sanity on first entry, PC could be smashed. */
pc = frame->a0; putEntry(pc, sp);
while (i++ < 100) { pc = frame->a0;
uint32_t psp = sp; while (i++ < 100) {
if (!stackPointerIsSane(sp) || i++ > 100) break; uint32_t psp = sp;
sp = *((uint32_t *) (sp - 0x10 + 4)); if (!stackPointerIsSane(sp) || i++ > 100) {
putEntry(pc, sp); break;
pc = *((uint32_t *) (psp - 0x10)); }
if (pc < 0x40000000) break; sp = *((uint32_t *) (sp - 0x10 + 4));
} putEntry(pc, sp);
panicPutStr("\n\n"); pc = *((uint32_t *) (psp - 0x10));
if (pc < 0x40000000) {
break;
}
}
panicPutStr("\n\n");
} }
/* /*
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) { void commonErrorHandler(XtExcFrame *frame)
int *regs=(int*)frame; {
int x, y; int *regs = (int *)frame;
const char *sdesc[]={ int x, y;
"PC ","PS ","A0 ","A1 ","A2 ","A3 ","A4 ","A5 ", const char *sdesc[] = {
"A6 ","A7 ","A8 ","A9 ","A10 ","A11 ","A12 ","A13 ", "PC ", "PS ", "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ",
"A14 ","A15 ","SAR ","EXCCAUSE","EXCVADDR","LBEG ","LEND ","LCOUNT "}; "A6 ", "A7 ", "A8 ", "A9 ", "A10 ", "A11 ", "A12 ", "A13 ",
"A14 ", "A15 ", "SAR ", "EXCCAUSE", "EXCVADDR", "LBEG ", "LEND ", "LCOUNT "
};
//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"); 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");
esp_gdbstub_panic_handler(frame); esp_gdbstub_panic_handler(frame);
#elif CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT #elif CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
panicPutStr("Rebooting...\r\n"); panicPutStr("Rebooting...\r\n");
for (x=0; x<100; x++) ets_delay_us(1000); for (x = 0; x < 100; x++) {
software_reset(); ets_delay_us(1000);
}
software_reset();
#else #else
disableAllWdts(); disableAllWdts();
panicPutStr("CPU halted.\r\n"); panicPutStr("CPU halted.\r\n");
while(1); while (1);
#endif #endif
} }
void esp_set_breakpoint_if_jtag(void *fn) { void esp_set_breakpoint_if_jtag(void *fn)
if (!inOCDMode()) return; {
setFirstBreakpoint((uint32_t)fn); if (!inOCDMode()) {
return;
}
setFirstBreakpoint((uint32_t)fn);
} }

0
tools/format.sh Normal file → Executable file
View file