diff --git a/components/esp32/panic.c b/components/esp32/panic.c index 4ec2b7c66..0efe56fe0 100644 --- a/components/esp32/panic.c +++ b/components/esp32/panic.c @@ -34,46 +34,58 @@ #include "esp_attr.h" /* -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 also is in here. + 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 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 //printf may be broken, so we fix our own printing fns... -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); +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); } -inline static void panicPutStr(const char *c) { - int x=0; - while (c[x]!=0) { - panicPutChar(c[x]); - x++; - } +inline static void panicPutStr(const char *c) +{ + int x = 0; + while (c[x] != 0) { + panicPutChar(c[x]); + x++; + } } -inline static void panicPutHex(int a) { - int x; - int c; - for (x=0; x<8; x++) { - c=(a>>28)&0xf; - if (c<10) panicPutChar('0'+c); else panicPutChar('a'+c-10); - a<<=4; - } +inline static void panicPutHex(int a) +{ + int x; + int c; + for (x = 0; x < 8; x++) { + c = (a >> 28) & 0xf; + if (c < 10) { + panicPutChar('0' + c); + } else { + panicPutChar('a' + c - 10); + } + a <<= 4; + } } -inline static void panicPutDec(int a) { - int n1, n2; - n1=a%10; - n2=a/10; - if (n2==0) panicPutChar(' '); else panicPutChar(n2+'0'); - panicPutChar(n1+'0'); +inline static void panicPutDec(int a) +{ + int n1, n2; + n1 = a % 10; + n2 = a / 10; + if (n2 == 0) { + panicPutChar(' '); + } else { + panicPutChar(n2 + '0'); + } + panicPutChar(n1 + '0'); } #else //No printing wanted. Stub out these functions. @@ -84,25 +96,26 @@ inline static void panicPutDec(int a) { } #endif -void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName ) { - panicPutStr("***ERROR*** A stack overflow in task "); - panicPutStr((char*)pcTaskName); - panicPutStr(" has been detected.\r\n"); - configASSERT(0); +void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName ) +{ + panicPutStr("***ERROR*** A stack overflow in task "); + panicPutStr((char *)pcTaskName); + panicPutStr(" has been detected.\r\n"); + configASSERT(0); } -static const char *edesc[]={ - "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" - }; +static const char *edesc[] = { + "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" +}; void commonErrorHandler(XtExcFrame *frame); @@ -115,191 +128,219 @@ static void haltOtherCore() } //Returns true when a debugger is attached using JTAG. -static int inOCDMode() { +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); + 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. + return 0; //Always return no debugger is attached. #endif } -void panicHandler(XtExcFrame *frame) { - int *regs=(int*)frame; - //Please keep in sync with PANIC_RSN_* defines - const char *reasons[]={ - "Unknown reason", - "Unhandled debug exception", - "Double exception", - "Unhandled kernel exception", - "Coprocessor exception", - "Interrupt wdt timeout on CPU0", - "Interrupt wdt timeout on CPU1", - }; - const char *reason=reasons[0]; - //The panic reason is stored in the EXCCAUSE register. - if (regs[20]<=PANIC_RSN_MAX) reason=reasons[regs[20]]; - haltOtherCore(); - panicPutStr("Guru Meditation Error: Core "); - panicPutDec(xPortGetCoreID()); - panicPutStr(" panic'ed ("); - panicPutStr(reason); - panicPutStr(")\r\n"); +void panicHandler(XtExcFrame *frame) +{ + int *regs = (int *)frame; + //Please keep in sync with PANIC_RSN_* defines + const char *reasons[] = { + "Unknown reason", + "Unhandled debug exception", + "Double exception", + "Unhandled kernel exception", + "Coprocessor exception", + "Interrupt wdt timeout on CPU0", + "Interrupt wdt timeout on CPU1", + }; + const char *reason = reasons[0]; + //The panic reason is stored in the EXCCAUSE register. + if (regs[20] <= PANIC_RSN_MAX) { + reason = reasons[regs[20]]; + } + haltOtherCore(); + panicPutStr("Guru Meditation Error: Core "); + panicPutDec(xPortGetCoreID()); + panicPutStr(" panic'ed ("); + panicPutStr(reason); + panicPutStr(")\r\n"); - if (inOCDMode()) { - asm("break.n 1"); - } - commonErrorHandler(frame); + if (inOCDMode()) { + asm("break.n 1"); + } + commonErrorHandler(frame); } -static void setFirstBreakpoint(uint32_t pc) { - asm( - "wsr.ibreaka0 %0\n" \ - "rsr.ibreakenable a3\n" \ - "movi a4,1\n" \ - "or a4, a4, a3\n" \ - "wsr.ibreakenable a4\n" \ - ::"r"(pc):"a3","a4"); +static void setFirstBreakpoint(uint32_t pc) +{ + asm( + "wsr.ibreaka0 %0\n" \ + "rsr.ibreakenable a3\n" \ + "movi a4,1\n" \ + "or a4, a4, a3\n" \ + "wsr.ibreakenable a4\n" \ + ::"r"(pc):"a3", "a4"); } -void xt_unhandled_exception(XtExcFrame *frame) { - int *regs=(int*)frame; - int x; +void xt_unhandled_exception(XtExcFrame *frame) +{ + int *regs = (int *)frame; + int x; - haltOtherCore(); - panicPutStr("Guru Meditation Error of type "); - x=regs[20]; - if (x<40) panicPutStr(edesc[x]); else panicPutStr("Unknown"); - panicPutStr(" occurred on core "); - panicPutDec(xPortGetCoreID()); - if (inOCDMode()) { - panicPutStr(" at pc="); - panicPutHex(regs[1]); - panicPutStr(". Setting bp and returning..\r\n"); - //Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger - //will kick in exactly at the context the error happened. - setFirstBreakpoint(regs[1]); - return; - } - panicPutStr(". Exception was unhandled.\r\n"); - commonErrorHandler(frame); + haltOtherCore(); + panicPutStr("Guru Meditation Error of type "); + x = regs[20]; + if (x < 40) { + panicPutStr(edesc[x]); + } else { + panicPutStr("Unknown"); + } + panicPutStr(" occurred on core "); + panicPutDec(xPortGetCoreID()); + if (inOCDMode()) { + panicPutStr(" at pc="); + panicPutHex(regs[1]); + panicPutStr(". Setting bp and returning..\r\n"); + //Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger + //will kick in exactly at the context the error happened. + 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 -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 -all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after -one second. + 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 + 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 + one second. */ -static void reconfigureAllWdts() { - TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; - TIMERG0.wdt_feed=1; - TIMERG0.wdt_config0.sys_reset_length=7; //3.2uS - TIMERG0.wdt_config0.cpu_reset_length=7; //3.2uS - TIMERG0.wdt_config0.stg0=TIMG_WDT_STG_SEL_RESET_SYSTEM; //1st stage timeout: reset system - TIMERG0.wdt_config1.clk_prescale=80*500; //Prescaler: wdt counts in ticks of 0.5mS - TIMERG0.wdt_config2=2000; //1 second before reset - TIMERG0.wdt_config0.en=1; - TIMERG0.wdt_wprotect=0; - //Disable wdt 1 - TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; - TIMERG1.wdt_config0.en=0; - TIMERG1.wdt_wprotect=0; +static void reconfigureAllWdts() +{ + TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE; + TIMERG0.wdt_feed = 1; + TIMERG0.wdt_config0.sys_reset_length = 7; //3.2uS + TIMERG0.wdt_config0.cpu_reset_length = 7; //3.2uS + TIMERG0.wdt_config0.stg0 = TIMG_WDT_STG_SEL_RESET_SYSTEM; //1st stage timeout: reset system + TIMERG0.wdt_config1.clk_prescale = 80 * 500; //Prescaler: wdt counts in ticks of 0.5mS + TIMERG0.wdt_config2 = 2000; //1 second before reset + TIMERG0.wdt_config0.en = 1; + TIMERG0.wdt_wprotect = 0; + //Disable wdt 1 + TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE; + TIMERG1.wdt_config0.en = 0; + TIMERG1.wdt_wprotect = 0; } #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() { - TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; - TIMERG0.wdt_config0.en=0; - TIMERG0.wdt_wprotect=0; - TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; - TIMERG1.wdt_config0.en=0; - TIMERG0.wdt_wprotect=0; +static void disableAllWdts() +{ + TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE; + TIMERG0.wdt_config0.en = 0; + TIMERG0.wdt_wprotect = 0; + TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE; + TIMERG1.wdt_config0.en = 0; + TIMERG0.wdt_wprotect = 0; } #endif -static inline bool stackPointerIsSane(uint32_t sp) { - return !(sp < 0x3ffae010 || sp > 0x3ffffff0 || ((sp & 0xf) != 0)); +static inline bool stackPointerIsSane(uint32_t sp) +{ + return !(sp < 0x3ffae010 || sp > 0x3ffffff0 || ((sp & 0xf) != 0)); } -static void putEntry(uint32_t pc, uint32_t sp) { - if (pc & 0x80000000) pc = (pc & 0x3fffffff) | 0x40000000; - panicPutStr(" 0x"); - panicPutHex(pc); - panicPutStr(":0x"); - panicPutHex(sp); +static void putEntry(uint32_t pc, uint32_t sp) +{ + if (pc & 0x80000000) { + pc = (pc & 0x3fffffff) | 0x40000000; + } + panicPutStr(" 0x"); + panicPutHex(pc); + panicPutStr(":0x"); + panicPutHex(sp); } -void doBacktrace(XtExcFrame *frame) { - uint32_t i = 0, pc = frame->pc, sp = frame->a1; - panicPutStr("\nBacktrace:"); - /* Do not check sanity on first entry, PC could be smashed. */ - putEntry(pc, sp); - pc = frame->a0; - while (i++ < 100) { - uint32_t psp = sp; - if (!stackPointerIsSane(sp) || i++ > 100) break; - sp = *((uint32_t *) (sp - 0x10 + 4)); - putEntry(pc, sp); - pc = *((uint32_t *) (psp - 0x10)); - if (pc < 0x40000000) break; - } - panicPutStr("\n\n"); +void doBacktrace(XtExcFrame *frame) +{ + uint32_t i = 0, pc = frame->pc, sp = frame->a1; + panicPutStr("\nBacktrace:"); + /* Do not check sanity on first entry, PC could be smashed. */ + putEntry(pc, sp); + pc = frame->a0; + while (i++ < 100) { + uint32_t psp = sp; + if (!stackPointerIsSane(sp) || i++ > 100) { + break; + } + sp = *((uint32_t *) (sp - 0x10 + 4)); + putEntry(pc, sp); + 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 -serial port and either jump to the gdb stub, halt the CPU or reboot. + 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. */ -void commonErrorHandler(XtExcFrame *frame) { - int *regs=(int*)frame; - int x, y; - const char *sdesc[]={ - "PC ","PS ","A0 ","A1 ","A2 ","A3 ","A4 ","A5 ", - "A6 ","A7 ","A8 ","A9 ","A10 ","A11 ","A12 ","A13 ", - "A14 ","A15 ","SAR ","EXCCAUSE","EXCVADDR","LBEG ","LEND ","LCOUNT "}; +void commonErrorHandler(XtExcFrame *frame) +{ + int *regs = (int *)frame; + int x, y; + const char *sdesc[] = { + "PC ", "PS ", "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ", + "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 - reconfigureAllWdts(); + //Feed the watchdogs, so they will give us time to print out debug info + reconfigureAllWdts(); - panicPutStr("Register dump:\r\n"); + panicPutStr("Register dump:\r\n"); - for (x=0; x<24; x+=4) { - for (y=0; y<4; y++) { - if (sdesc[x+y][0]!=0) { - panicPutStr(sdesc[x+y]); - panicPutStr(": 0x"); - panicPutHex(regs[x+y+1]); - panicPutStr(" "); - } - } - panicPutStr("\r\n"); - } - /* With windowed ABI backtracing is easy, let's do it. */ - doBacktrace(frame); + for (x = 0; x < 24; x += 4) { + for (y = 0; y < 4; y++) { + if (sdesc[x + y][0] != 0) { + panicPutStr(sdesc[x + y]); + panicPutStr(": 0x"); + panicPutHex(regs[x + y + 1]); + panicPutStr(" "); + } + } + panicPutStr("\r\n"); + } + /* With windowed ABI backtracing is easy, let's do it. */ + doBacktrace(frame); #if CONFIG_ESP32_PANIC_GDBSTUB - disableAllWdts(); - panicPutStr("Entering gdb stub now.\r\n"); - esp_gdbstub_panic_handler(frame); + disableAllWdts(); + panicPutStr("Entering gdb stub now.\r\n"); + esp_gdbstub_panic_handler(frame); #elif CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT - panicPutStr("Rebooting...\r\n"); - for (x=0; x<100; x++) ets_delay_us(1000); - software_reset(); + panicPutStr("Rebooting...\r\n"); + for (x = 0; x < 100; x++) { + ets_delay_us(1000); + } + software_reset(); #else - disableAllWdts(); - panicPutStr("CPU halted.\r\n"); - while(1); + disableAllWdts(); + panicPutStr("CPU halted.\r\n"); + while (1); #endif } -void esp_set_breakpoint_if_jtag(void *fn) { - if (!inOCDMode()) return; - setFirstBreakpoint((uint32_t)fn); +void esp_set_breakpoint_if_jtag(void *fn) +{ + if (!inOCDMode()) { + return; + } + setFirstBreakpoint((uint32_t)fn); } diff --git a/tools/format.sh b/tools/format.sh old mode 100644 new mode 100755