]> granicus.if.org Git - esp-idf/commitdiff
panic handlers: Print the PC address where abort() was called, don't dump registers
authorAngus Gratton <angus@espressif.com>
Wed, 7 Dec 2016 00:33:24 +0000 (16:33 -0800)
committerAngus Gratton <angus@espressif.com>
Tue, 27 Dec 2016 23:09:40 +0000 (10:09 +1100)
components/esp32/cpu_util.c
components/esp32/include/soc/cpu.h
components/esp32/panic.c
components/newlib/syscalls.c

index cff61ab796ed1d2281146eec8f6ddadd5058f4fd..e3b4ef8f164495f333bb0fe70213639559b0bd42 100644 (file)
@@ -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);
     }
 }
+
+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
+}
index 4457c81a22c65b71591d0f6afa70d4748ff324d9..b89ae2875f7be761e604dd736baf5b73c6719123 100644 (file)
@@ -94,4 +94,13 @@ void esp_cpu_stall(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
index 0efe56fe01bf2550a14709a836a35be9e556e561..3cdbfb3e3977600f2f9de792c66fc3d0395fc1aa 100644 (file)
@@ -36,7 +36,7 @@
 /*
   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.
+  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) { }
 #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);
+    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[] = {
     "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
     "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
 //messing up the serial output, so we stall it here.
@@ -127,19 +141,6 @@ static void haltOtherCore()
     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)
 {
     int *regs = (int *)frame;
@@ -165,7 +166,7 @@ void panicHandler(XtExcFrame *frame)
     panicPutStr(reason);
     panicPutStr(")\r\n");
 
-    if (inOCDMode()) {
+    if (esp_cpu_in_ocd_debug_mode()) {
         asm("break.n 1");
     }
     commonErrorHandler(frame);
@@ -197,7 +198,7 @@ void xt_unhandled_exception(XtExcFrame *frame)
     }
     panicPutStr(" occurred on core ");
     panicPutDec(xPortGetCoreID());
-    if (inOCDMode()) {
+    if (esp_cpu_in_ocd_debug_mode()) {
         panicPutStr(" at pc=");
         panicPutHex(regs[1]);
         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));
 }
+
 static void putEntry(uint32_t pc, uint32_t sp)
 {
     if (pc & 0x80000000) {
@@ -265,7 +267,8 @@ static void putEntry(uint32_t pc, uint32_t sp)
     panicPutStr(":0x");
     panicPutHex(sp);
 }
-void doBacktrace(XtExcFrame *frame)
+
+static void doBacktrace(XtExcFrame *frame)
 {
     uint32_t i = 0, pc = frame->pc, sp = frame->a1;
     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
   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 x, y;
@@ -304,21 +307,28 @@ void commonErrorHandler(XtExcFrame *frame)
     //Feed the watchdogs, so they will give us time to print out debug info
     reconfigureAllWdts();
 
-    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("  ");
+    /* 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 (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");
         }
-        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");
@@ -339,8 +349,7 @@ void commonErrorHandler(XtExcFrame *frame)
 
 void esp_set_breakpoint_if_jtag(void *fn)
 {
-    if (!inOCDMode()) {
-        return;
+    if (esp_cpu_in_ocd_debug_mode()) {
+        setFirstBreakpoint((uint32_t)fn);
     }
-    setFirstBreakpoint((uint32_t)fn);
 }
index 3b2fbf62cacc22548979f9526a608a328e350e4f..74182d07f25d5a2e028229ef177e71ff3b24bf3e 100644 (file)
 #include "esp_attr.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)
 {
     return pvPortMalloc(size);