| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | // 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 <xtensa/config/core.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "rom/rtc.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  | #include "rom/uart.h"
 | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "freertos/FreeRTOS.h"
 | 
					
						
							|  |  |  | #include "freertos/task.h"
 | 
					
						
							|  |  |  | #include "freertos/xtensa_api.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-13 23:02:03 +08:00
										 |  |  | #include "soc/uart_reg.h"
 | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | #include "soc/io_mux_reg.h"
 | 
					
						
							|  |  |  | #include "soc/dport_reg.h"
 | 
					
						
							|  |  |  | #include "soc/rtc_cntl_reg.h"
 | 
					
						
							| 
									
										
										
										
											2016-10-25 17:05:13 +08:00
										 |  |  | #include "soc/timer_group_struct.h"
 | 
					
						
							| 
									
										
										
										
											2016-10-26 12:23:01 +08:00
										 |  |  | #include "soc/timer_group_reg.h"
 | 
					
						
							| 
									
										
										
										
											2016-11-21 17:15:37 +08:00
										 |  |  | #include "soc/cpu.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  | #include "soc/rtc.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-23 15:59:37 +05:00
										 |  |  | #include "soc/rtc_wdt.h"
 | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-26 12:23:01 +08:00
										 |  |  | #include "esp_gdbstub.h"
 | 
					
						
							|  |  |  | #include "esp_panic.h"
 | 
					
						
							| 
									
										
										
										
											2016-10-28 14:32:11 +08:00
										 |  |  | #include "esp_attr.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-09 16:42:45 +08:00
										 |  |  | #include "esp_err.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-22 02:56:23 +03:00
										 |  |  | #include "esp_core_dump.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-02 17:22:22 +11:00
										 |  |  | #include "esp_spi_flash.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  | #include "esp_cache_err_int.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-25 19:35:28 +03:00
										 |  |  | #include "esp_app_trace.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-29 12:57:59 +03:00
										 |  |  | #include "esp_system_internal.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-31 12:47:06 +02:00
										 |  |  | #include "sdkconfig.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-22 06:07:37 +03:00
										 |  |  | #if CONFIG_SYSVIEW_ENABLE
 | 
					
						
							|  |  |  | #include "SEGGER_RTT.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 06:07:37 +03:00
										 |  |  | #if CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO == -1
 | 
					
						
							|  |  |  | #define APPTRACE_ONPANIC_HOST_FLUSH_TMO   ESP_APPTRACE_TMO_INFINITE
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define APPTRACE_ONPANIC_HOST_FLUSH_TMO   (1000*CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |   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 | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  |   overflow handler and abort handler are also in here. | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 14:32:11 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |   Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled. | 
					
						
							| 
									
										
										
										
											2016-10-28 14:32:11 +08:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-27 11:17:24 +08:00
										 |  |  | #if !CONFIG_ESP32_PANIC_SILENT_REBOOT
 | 
					
						
							| 
									
										
										
										
											2016-08-23 20:14:54 +08:00
										 |  |  | //printf may be broken, so we fix our own printing fns...
 | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  | static void panicPutChar(char c) | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-04-12 17:46:57 +08:00
										 |  |  |     while (((READ_PERI_REG(UART_STATUS_REG(CONFIG_CONSOLE_UART_NUM)) >> UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT) >= 126) ; | 
					
						
							|  |  |  |     WRITE_PERI_REG(UART_FIFO_REG(CONFIG_CONSOLE_UART_NUM), c); | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  | static void panicPutStr(const char *c) | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | { | 
					
						
							|  |  |  |     int x = 0; | 
					
						
							|  |  |  |     while (c[x] != 0) { | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |         panicPutChar(c[x]); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |         x++; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  | static void panicPutHex(int a) | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | { | 
					
						
							|  |  |  |     int x; | 
					
						
							|  |  |  |     int c; | 
					
						
							|  |  |  |     for (x = 0; x < 8; x++) { | 
					
						
							|  |  |  |         c = (a >> 28) & 0xf; | 
					
						
							|  |  |  |         if (c < 10) { | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |             panicPutChar('0' + c); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |             panicPutChar('a' + c - 10); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |         a <<= 4; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  | static void panicPutDec(int a) | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | { | 
					
						
							|  |  |  |     int n1, n2; | 
					
						
							|  |  |  |     n1 = a % 10; | 
					
						
							|  |  |  |     n2 = a / 10; | 
					
						
							|  |  |  |     if (n2 == 0) { | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |         panicPutChar(' '); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |         panicPutChar(n2 + '0'); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |     panicPutChar(n1 + '0'); | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | //No printing wanted. Stub out these functions.
 | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  | static void panicPutChar(char c) { } | 
					
						
							|  |  |  | static void panicPutStr(const char *c) { } | 
					
						
							|  |  |  | static void panicPutHex(int a) { } | 
					
						
							|  |  |  | static void panicPutDec(int a) { } | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | void  __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |     panicPutStr("***ERROR*** A stack overflow in task "); | 
					
						
							|  |  |  |     panicPutStr((char *)pcTaskName); | 
					
						
							|  |  |  |     panicPutStr(" has been detected.\r\n"); | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  |     abort(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-29 12:57:59 +03:00
										 |  |  | /* These two weak stubs for esp_reset_reason_{get,set}_hint are used when
 | 
					
						
							|  |  |  |  * the application does not call esp_reset_reason() function, and | 
					
						
							|  |  |  |  * reset_reason.c is not linked into the output file. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void __attribute__((weak)) esp_reset_reason_set_hint(esp_reset_reason_t hint) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | esp_reset_reason_t __attribute__((weak)) esp_reset_reason_get_hint(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return ESP_RST_UNKNOWN; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  | static bool abort_called; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 17:22:22 +11:00
										 |  |  | static __attribute__((noreturn)) inline void invoke_abort() | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  | { | 
					
						
							|  |  |  |     abort_called = true; | 
					
						
							| 
									
										
										
										
											2017-01-25 19:35:28 +03:00
										 |  |  | #if CONFIG_ESP32_APPTRACE_ENABLE
 | 
					
						
							| 
									
										
										
										
											2017-03-22 06:07:37 +03:00
										 |  |  | #if CONFIG_SYSVIEW_ENABLE
 | 
					
						
							|  |  |  |     SEGGER_RTT_ESP32_FlushNoLock(CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |                               APPTRACE_ONPANIC_HOST_FLUSH_TMO); | 
					
						
							| 
									
										
										
										
											2017-03-22 06:07:37 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-01-25 19:35:28 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |     while (1) { | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |         if (esp_cpu_in_ocd_debug_mode()) { | 
					
						
							|  |  |  |             __asm__ ("break 0,0"); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |         *((int *) 0) = 0; | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 17:22:22 +11:00
										 |  |  | void abort() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if !CONFIG_ESP32_PANIC_SILENT_REBOOT
 | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |     ets_printf("abort() was called at PC 0x%08x on core %d\r\n", (intptr_t)__builtin_return_address(0) - 3, xPortGetCoreID()); | 
					
						
							| 
									
										
										
										
											2017-03-02 17:22:22 +11:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-07-29 12:57:59 +03:00
										 |  |  |     /* Calling code might have set other reset reason hint (such as Task WDT),
 | 
					
						
							|  |  |  |      * don't overwrite that. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (esp_reset_reason_get_hint() == ESP_RST_UNKNOWN) { | 
					
						
							|  |  |  |         esp_reset_reason_set_hint(ESP_RST_PANIC); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-03-02 17:22:22 +11:00
										 |  |  |     invoke_abort(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | 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" | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  | #define NUM_EDESCS (sizeof(edesc) / sizeof(char *))
 | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  | static void commonErrorHandler(XtExcFrame *frame); | 
					
						
							| 
									
										
										
										
											2018-01-09 01:46:24 +08:00
										 |  |  | static inline void disableAllWdts(); | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | //The fact that we've panic'ed probably means the other CPU is now running wild, possibly
 | 
					
						
							| 
									
										
										
										
											2016-11-21 17:15:37 +08:00
										 |  |  | //messing up the serial output, so we stall it here.
 | 
					
						
							|  |  |  | static void haltOtherCore() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     esp_cpu_stall( xPortGetCoreID() == 0 ? 1 : 0 ); | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-11 21:43:58 +08:00
										 |  |  | //When interrupt watchdog happen in one core, both cores will be interrupted.
 | 
					
						
							|  |  |  | //The core which doesn't trigger the interrupt watchdog will save the frame and return.
 | 
					
						
							|  |  |  | //The core which triggers the interrupt watchdog will use the saved frame, and dump frames for both cores.
 | 
					
						
							|  |  |  | #if !CONFIG_FREERTOS_UNICORE
 | 
					
						
							|  |  |  | static volatile XtExcFrame * other_core_frame = NULL; | 
					
						
							|  |  |  | #endif //!CONFIG_FREERTOS_UNICORE
 | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | void panicHandler(XtExcFrame *frame) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  |     int core_id = xPortGetCoreID(); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     //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", | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  |         "Cache disabled but cached memory region accessed", | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     }; | 
					
						
							|  |  |  |     const char *reason = reasons[0]; | 
					
						
							|  |  |  |     //The panic reason is stored in the EXCCAUSE register.
 | 
					
						
							| 
									
										
										
										
											2017-04-12 17:48:14 +08:00
										 |  |  |     if (frame->exccause <= PANIC_RSN_MAX) { | 
					
						
							|  |  |  |         reason = reasons[frame->exccause]; | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-11 21:43:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if !CONFIG_FREERTOS_UNICORE
 | 
					
						
							|  |  |  |     //Save frame for other core.
 | 
					
						
							|  |  |  |     if ((frame->exccause == PANIC_RSN_INTWDT_CPU0 && core_id == 1) || (frame->exccause == PANIC_RSN_INTWDT_CPU1 && core_id == 0)) { | 
					
						
							|  |  |  |         other_core_frame = frame; | 
					
						
							|  |  |  |         while (1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //The core which triggers the interrupt watchdog will delay 1 us, so the other core can save its frame.
 | 
					
						
							|  |  |  |     if (frame->exccause == PANIC_RSN_INTWDT_CPU0 || frame->exccause == PANIC_RSN_INTWDT_CPU1) { | 
					
						
							|  |  |  |         ets_delay_us(1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  |     if (frame->exccause == PANIC_RSN_CACHEERR && esp_cache_err_get_cpuid() != core_id) { | 
					
						
							|  |  |  |         // Cache error interrupt will be handled by the panic handler
 | 
					
						
							|  |  |  |         // on the other CPU.
 | 
					
						
							| 
									
										
										
										
											2018-01-11 21:43:58 +08:00
										 |  |  |         while (1); | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-11 21:43:58 +08:00
										 |  |  | #endif //!CONFIG_FREERTOS_UNICORE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-29 12:57:59 +03:00
										 |  |  |     if (frame->exccause == PANIC_RSN_INTWDT_CPU0 || frame->exccause == PANIC_RSN_INTWDT_CPU1) { | 
					
						
							|  |  |  |         esp_reset_reason_set_hint(ESP_RST_INT_WDT); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     haltOtherCore(); | 
					
						
							| 
									
										
										
										
											2017-09-11 12:31:16 +08:00
										 |  |  |     esp_dport_access_int_abort(); | 
					
						
							| 
									
										
										
										
											2017-01-10 14:48:47 +03:00
										 |  |  |     panicPutStr("Guru Meditation Error: Core "); | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  |     panicPutDec(core_id); | 
					
						
							| 
									
										
										
										
											2017-01-10 14:48:47 +03:00
										 |  |  |     panicPutStr(" panic'ed ("); | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |     panicPutStr(reason); | 
					
						
							|  |  |  |     panicPutStr(")\r\n"); | 
					
						
							|  |  |  |     if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) { | 
					
						
							|  |  |  |         int debugRsn; | 
					
						
							|  |  |  |         asm("rsr.debugcause %0":"=r"(debugRsn)); | 
					
						
							|  |  |  |         panicPutStr("Debug exception reason: "); | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |         if (debugRsn & XCHAL_DEBUGCAUSE_ICOUNT_MASK) { | 
					
						
							|  |  |  |             panicPutStr("SingleStep "); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (debugRsn & XCHAL_DEBUGCAUSE_IBREAK_MASK) { | 
					
						
							|  |  |  |             panicPutStr("HwBreakpoint "); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (debugRsn & XCHAL_DEBUGCAUSE_DBREAK_MASK) { | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |             //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 watchdog 1 and clearing it if it's watchdog 0.
 | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |             if (debugRsn & (1 << 8)) { | 
					
						
							| 
									
										
										
										
											2017-01-10 13:05:19 +08:00
										 |  |  | #if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
 | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |                 const char *name = pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(core_id)); | 
					
						
							|  |  |  |                 panicPutStr("Stack canary watchpoint triggered ("); | 
					
						
							|  |  |  |                 panicPutStr(name); | 
					
						
							|  |  |  |                 panicPutStr(") "); | 
					
						
							| 
									
										
										
										
											2017-01-10 13:05:19 +08:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |                 panicPutStr("Watchpoint 1 triggered "); | 
					
						
							| 
									
										
										
										
											2017-01-10 13:05:19 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 panicPutStr("Watchpoint 0 triggered "); | 
					
						
							| 
									
										
										
										
											2017-01-10 13:05:19 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (debugRsn & XCHAL_DEBUGCAUSE_BREAK_MASK) { | 
					
						
							|  |  |  |             panicPutStr("BREAK instr "); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (debugRsn & XCHAL_DEBUGCAUSE_BREAKN_MASK) { | 
					
						
							|  |  |  |             panicPutStr("BREAKN instr "); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (debugRsn & XCHAL_DEBUGCAUSE_DEBUGINT_MASK) { | 
					
						
							|  |  |  |             panicPutStr("DebugIntr "); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |         panicPutStr("\r\n"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  |     if (esp_cpu_in_ocd_debug_mode()) { | 
					
						
							| 
									
										
										
										
											2018-01-09 01:46:24 +08:00
										 |  |  |         disableAllWdts(); | 
					
						
							|  |  |  |         if (frame->exccause == PANIC_RSN_INTWDT_CPU0 || | 
					
						
							|  |  |  |             frame->exccause == PANIC_RSN_INTWDT_CPU1) { | 
					
						
							|  |  |  |             TIMERG1.int_clr_timers.wdt = 1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-01-25 19:35:28 +03:00
										 |  |  | #if CONFIG_ESP32_APPTRACE_ENABLE
 | 
					
						
							| 
									
										
										
										
											2017-03-22 06:07:37 +03:00
										 |  |  | #if CONFIG_SYSVIEW_ENABLE
 | 
					
						
							|  |  |  |         SEGGER_RTT_ESP32_FlushNoLock(CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |                                   APPTRACE_ONPANIC_HOST_FLUSH_TMO); | 
					
						
							| 
									
										
										
										
											2017-03-22 06:07:37 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-01-25 19:35:28 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-04-12 17:48:14 +08:00
										 |  |  |         setFirstBreakpoint(frame->pc); | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     commonErrorHandler(frame); | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | void xt_unhandled_exception(XtExcFrame *frame) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     haltOtherCore(); | 
					
						
							| 
									
										
										
										
											2017-09-11 12:31:16 +08:00
										 |  |  |     esp_dport_access_int_abort(); | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |     if (!abort_called) { | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |         panicPutStr("Guru Meditation Error: Core "); | 
					
						
							|  |  |  |         panicPutDec(xPortGetCoreID()); | 
					
						
							|  |  |  |         panicPutStr(" panic'ed ("); | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |         int exccause = frame->exccause; | 
					
						
							|  |  |  |         if (exccause < NUM_EDESCS) { | 
					
						
							|  |  |  |             panicPutStr(edesc[exccause]); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             panicPutStr("Unknown"); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-06-12 18:50:59 +08:00
										 |  |  |         panicPutStr(")"); | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |         if (esp_cpu_in_ocd_debug_mode()) { | 
					
						
							|  |  |  |             panicPutStr(" at pc="); | 
					
						
							|  |  |  |             panicPutHex(frame->pc); | 
					
						
							|  |  |  |             panicPutStr(". Setting bp and returning..\r\n"); | 
					
						
							| 
									
										
										
										
											2017-01-25 19:35:28 +03:00
										 |  |  | #if CONFIG_ESP32_APPTRACE_ENABLE
 | 
					
						
							| 
									
										
										
										
											2017-03-22 06:07:37 +03:00
										 |  |  | #if CONFIG_SYSVIEW_ENABLE
 | 
					
						
							|  |  |  |             SEGGER_RTT_ESP32_FlushNoLock(CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |             esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |                                       APPTRACE_ONPANIC_HOST_FLUSH_TMO); | 
					
						
							| 
									
										
										
										
											2017-03-22 06:07:37 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-01-25 19:35:28 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-06-08 15:21:03 +10:00
										 |  |  |             //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(frame->pc); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         panicPutStr(". Exception was unhandled.\r\n"); | 
					
						
							| 
									
										
										
										
											2018-07-29 12:57:59 +03:00
										 |  |  |         esp_reset_reason_set_hint(ESP_RST_PANIC); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     commonErrorHandler(frame); | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-26 12:23:01 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |   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. | 
					
						
							| 
									
										
										
										
											2016-10-26 12:23:01 +08:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | 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; | 
					
						
							| 
									
										
										
										
											2016-10-25 17:05:13 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-26 12:23:01 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |   This disables all the watchdogs for when we call the gdbstub. | 
					
						
							| 
									
										
										
										
											2016-10-26 12:23:01 +08:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2017-01-25 19:35:28 +03:00
										 |  |  | static inline void disableAllWdts() | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | { | 
					
						
							|  |  |  |     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; | 
					
						
							| 
									
										
										
										
											2017-03-29 21:09:47 +03:00
										 |  |  |     TIMERG1.wdt_wprotect = 0; | 
					
						
							| 
									
										
										
										
											2016-10-25 17:05:13 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  | static void esp_panic_dig_reset() __attribute__((noreturn)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void esp_panic_dig_reset() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // make sure all the panic handler output is sent from UART FIFO
 | 
					
						
							|  |  |  |     uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM); | 
					
						
							|  |  |  |     // switch to XTAL (otherwise we will keep running from the PLL)
 | 
					
						
							| 
									
										
										
										
											2018-07-29 10:50:49 +03:00
										 |  |  |     rtc_clk_cpu_freq_set_xtal(); | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  |     // reset the digital part
 | 
					
						
							|  |  |  |     esp_cpu_unstall(PRO_CPU_NUM); | 
					
						
							|  |  |  |     SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST); | 
					
						
							|  |  |  |     while (true) { | 
					
						
							|  |  |  |         ; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | static void putEntry(uint32_t pc, uint32_t sp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (pc & 0x80000000) { | 
					
						
							|  |  |  |         pc = (pc & 0x3fffffff) | 0x40000000; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |     panicPutStr(" 0x"); | 
					
						
							|  |  |  |     panicPutHex(pc); | 
					
						
							|  |  |  |     panicPutStr(":0x"); | 
					
						
							|  |  |  |     panicPutHex(sp); | 
					
						
							| 
									
										
										
										
											2016-12-07 18:58:55 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void doBacktrace(XtExcFrame *frame) | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | { | 
					
						
							|  |  |  |     uint32_t i = 0, pc = frame->pc, sp = frame->a1; | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |     panicPutStr("\r\nBacktrace:"); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     /* Do not check sanity on first entry, PC could be smashed. */ | 
					
						
							|  |  |  |     putEntry(pc, sp); | 
					
						
							|  |  |  |     pc = frame->a0; | 
					
						
							|  |  |  |     while (i++ < 100) { | 
					
						
							|  |  |  |         uint32_t psp = sp; | 
					
						
							| 
									
										
										
										
											2017-04-20 19:38:38 +03:00
										 |  |  |         if (!esp_stack_ptr_is_sane(sp) || i++ > 100) { | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         sp = *((uint32_t *) (sp - 0x10 + 4)); | 
					
						
							| 
									
										
										
										
											2017-06-08 15:27:50 +10:00
										 |  |  |         putEntry(pc - 3, sp); // stack frame addresses are return addresses, so subtract 3 to get the CALL address
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |         pc = *((uint32_t *) (psp - 0x10)); | 
					
						
							|  |  |  |         if (pc < 0x40000000) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |     panicPutStr("\r\n\r\n"); | 
					
						
							| 
									
										
										
										
											2016-12-07 18:58:55 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2018-01-11 21:43:58 +08:00
										 |  |  |  * Dump registers and do backtrace. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void commonErrorHandler_dump(XtExcFrame *frame, int core_id) | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | { | 
					
						
							|  |  |  |     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  " | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  |     /* only dump registers for 'real' crashes, if crashing via abort()
 | 
					
						
							|  |  |  |        the register window is no longer useful. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     if (!abort_called) { | 
					
						
							| 
									
										
										
										
											2018-01-11 21:43:58 +08:00
										 |  |  |         panicPutStr("Core"); | 
					
						
							|  |  |  |         panicPutDec(core_id); | 
					
						
							|  |  |  |         panicPutStr(" register dump:\r\n"); | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (x = 0; x < 24; x += 4) { | 
					
						
							|  |  |  |             for (y = 0; y < 4; y++) { | 
					
						
							|  |  |  |                 if (sdesc[x + y][0] != 0) { | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |                     panicPutStr(sdesc[x + y]); | 
					
						
							|  |  |  |                     panicPutStr(": 0x"); | 
					
						
							|  |  |  |                     panicPutHex(regs[x + y + 1]); | 
					
						
							|  |  |  |                     panicPutStr("  "); | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-01-15 16:49:18 +08:00
										 |  |  |             panicPutStr("\r\n"); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-11 21:43:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (xPortInterruptedFromISRContext() | 
					
						
							|  |  |  | #if !CONFIG_FREERTOS_UNICORE
 | 
					
						
							|  |  |  |             && other_core_frame != frame | 
					
						
							|  |  |  | #endif //!CONFIG_FREERTOS_UNICORE
 | 
					
						
							|  |  |  |             ) { | 
					
						
							|  |  |  |             //If the core which triggers the interrupt watchdog was in ISR context, dump the epc registers.
 | 
					
						
							|  |  |  |             uint32_t __value; | 
					
						
							|  |  |  |             panicPutStr("Core"); | 
					
						
							|  |  |  |             panicPutDec(core_id); | 
					
						
							|  |  |  |             panicPutStr(" was running in ISR context:\r\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             __asm__("rsr.epc1 %0" : "=a"(__value)); | 
					
						
							|  |  |  |             panicPutStr("EPC1    : 0x"); | 
					
						
							|  |  |  |             panicPutHex(__value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             __asm__("rsr.epc2 %0" : "=a"(__value)); | 
					
						
							|  |  |  |             panicPutStr("  EPC2    : 0x"); | 
					
						
							|  |  |  |             panicPutHex(__value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             __asm__("rsr.epc3 %0" : "=a"(__value)); | 
					
						
							|  |  |  |             panicPutStr("  EPC3    : 0x"); | 
					
						
							|  |  |  |             panicPutHex(__value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             __asm__("rsr.epc4 %0" : "=a"(__value)); | 
					
						
							|  |  |  |             panicPutStr("  EPC4    : 0x"); | 
					
						
							|  |  |  |             panicPutHex(__value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             panicPutStr("\r\n"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     /* With windowed ABI backtracing is easy, let's do it. */ | 
					
						
							|  |  |  |     doBacktrace(frame); | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-11 21:43:58 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |   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. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static __attribute__((noreturn)) void commonErrorHandler(XtExcFrame *frame) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int core_id = xPortGetCoreID(); | 
					
						
							|  |  |  |     // start panic WDT to restart system if we hang in this handler
 | 
					
						
							| 
									
										
										
										
											2018-07-23 15:59:37 +05:00
										 |  |  |     if (!rtc_wdt_is_on()) { | 
					
						
							|  |  |  |         rtc_wdt_protect_off(); | 
					
						
							|  |  |  |         rtc_wdt_disable(); | 
					
						
							|  |  |  |         rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us); | 
					
						
							|  |  |  |         rtc_wdt_set_length_of_reset_signal(RTC_WDT_CPU_RESET_SIG, RTC_WDT_LENGTH_3_2us); | 
					
						
							|  |  |  |         rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_SYSTEM); | 
					
						
							|  |  |  |         // 64KB of core dump data (stacks of about 30 tasks) will produce ~85KB base64 data.
 | 
					
						
							|  |  |  |         // @ 115200 UART speed it will take more than 6 sec to print them out.
 | 
					
						
							|  |  |  |         rtc_wdt_set_time(RTC_WDT_STAGE0, 7000); | 
					
						
							|  |  |  |         rtc_wdt_enable(); | 
					
						
							|  |  |  |         rtc_wdt_protect_on(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-11 21:43:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     //Feed the watchdogs, so they will give us time to print out debug info
 | 
					
						
							|  |  |  |     reconfigureAllWdts(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     commonErrorHandler_dump(frame, core_id); | 
					
						
							|  |  |  | #if !CONFIG_FREERTOS_UNICORE
 | 
					
						
							|  |  |  |     if (other_core_frame != NULL) { | 
					
						
							|  |  |  |         commonErrorHandler_dump((XtExcFrame *)other_core_frame, (core_id ? 0 : 1)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif //!CONFIG_FREERTOS_UNICORE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 19:35:28 +03:00
										 |  |  | #if CONFIG_ESP32_APPTRACE_ENABLE
 | 
					
						
							|  |  |  |     disableAllWdts(); | 
					
						
							| 
									
										
										
										
											2017-03-22 06:07:37 +03:00
										 |  |  | #if CONFIG_SYSVIEW_ENABLE
 | 
					
						
							|  |  |  |     SEGGER_RTT_ESP32_FlushNoLock(CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |                               APPTRACE_ONPANIC_HOST_FLUSH_TMO); | 
					
						
							| 
									
										
										
										
											2017-03-22 06:07:37 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-01-25 19:35:28 +03:00
										 |  |  |     reconfigureAllWdts(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-27 11:17:24 +08:00
										 |  |  | #if CONFIG_ESP32_PANIC_GDBSTUB
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     disableAllWdts(); | 
					
						
							| 
									
										
										
										
											2018-07-23 15:59:37 +05:00
										 |  |  |     rtc_wdt_disable(); | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |     panicPutStr("Entering gdb stub now.\r\n"); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     esp_gdbstub_panic_handler(frame); | 
					
						
							| 
									
										
										
										
											2016-12-22 02:56:23 +03:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2017-01-19 20:24:55 +03:00
										 |  |  | #if CONFIG_ESP32_ENABLE_COREDUMP
 | 
					
						
							| 
									
										
										
										
											2017-09-04 20:05:36 +03:00
										 |  |  |     static bool s_dumping_core; | 
					
						
							|  |  |  |     if (s_dumping_core) { | 
					
						
							|  |  |  |         panicPutStr("Re-entered core dump! Exception happened during core dump!\r\n"); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         disableAllWdts(); | 
					
						
							|  |  |  |         s_dumping_core = true; | 
					
						
							| 
									
										
										
										
											2016-12-22 02:56:23 +03:00
										 |  |  | #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
 | 
					
						
							| 
									
										
										
										
											2017-09-04 20:05:36 +03:00
										 |  |  |         esp_core_dump_to_flash(frame); | 
					
						
							| 
									
										
										
										
											2016-12-22 02:56:23 +03:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART && !CONFIG_ESP32_PANIC_SILENT_REBOOT
 | 
					
						
							| 
									
										
										
										
											2017-09-04 20:05:36 +03:00
										 |  |  |         esp_core_dump_to_uart(frame); | 
					
						
							| 
									
										
										
										
											2017-01-19 20:24:55 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-09-04 20:05:36 +03:00
										 |  |  |         s_dumping_core = false; | 
					
						
							|  |  |  |         reconfigureAllWdts(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-07-11 10:18:08 +08:00
										 |  |  | #endif /* CONFIG_ESP32_ENABLE_COREDUMP */
 | 
					
						
							| 
									
										
										
										
											2018-07-23 15:59:37 +05:00
										 |  |  |     rtc_wdt_disable(); | 
					
						
							| 
									
										
										
										
											2016-12-22 02:56:23 +03:00
										 |  |  | #if CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
 | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |     panicPutStr("Rebooting...\r\n"); | 
					
						
							| 
									
										
										
										
											2017-03-09 20:50:39 +08:00
										 |  |  |     if (frame->exccause != PANIC_RSN_CACHEERR) { | 
					
						
							|  |  |  |         esp_restart_noos(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         // The only way to clear invalid cache access interrupt is to reset the digital part
 | 
					
						
							|  |  |  |         esp_panic_dig_reset(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     disableAllWdts(); | 
					
						
							| 
									
										
										
										
											2017-01-03 22:01:40 +03:00
										 |  |  |     panicPutStr("CPU halted.\r\n"); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     while (1); | 
					
						
							| 
									
										
										
										
											2017-07-11 10:18:08 +08:00
										 |  |  | #endif /* CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT */
 | 
					
						
							|  |  |  | #endif /* CONFIG_ESP32_PANIC_GDBSTUB */
 | 
					
						
							| 
									
										
										
										
											2016-08-17 23:08:22 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-24 12:23:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  | void esp_set_breakpoint_if_jtag(void *fn) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-12-06 16:33:24 -08:00
										 |  |  |     if (esp_cpu_in_ocd_debug_mode()) { | 
					
						
							|  |  |  |         setFirstBreakpoint((uint32_t)fn); | 
					
						
							| 
									
										
										
										
											2016-12-07 13:25:26 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-08-24 12:23:58 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-01-09 16:42:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | esp_err_t esp_set_watchpoint(int no, void *adr, int size, int flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int x; | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |     if (no < 0 || no > 1) { | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_ARG; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (flags & (~0xC0000000)) { | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_ARG; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int dbreakc = 0x3F; | 
					
						
							| 
									
										
										
										
											2017-01-09 16:42:45 +08:00
										 |  |  |     //We support watching 2^n byte values, from 1 to 64. Calculate the mask for that.
 | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |     for (x = 0; x < 7; x++) { | 
					
						
							|  |  |  |         if (size == (1 << x)) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         dbreakc <<= 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (x == 7) { | 
					
						
							|  |  |  |         return ESP_ERR_INVALID_ARG; | 
					
						
							| 
									
										
										
										
											2017-01-09 16:42:45 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     //Mask mask and add in flags.
 | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |     dbreakc = (dbreakc & 0x3f) | flags; | 
					
						
							| 
									
										
										
										
											2017-01-09 16:42:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |     if (no == 0) { | 
					
						
							| 
									
										
										
										
											2017-01-09 16:42:45 +08:00
										 |  |  |         asm volatile( | 
					
						
							|  |  |  |             "wsr.dbreaka0 %0\n" \ | 
					
						
							|  |  |  |             "wsr.dbreakc0 %1\n" \ | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |             ::"r"(adr), "r"(dbreakc)); | 
					
						
							| 
									
										
										
										
											2017-01-09 16:42:45 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         asm volatile( | 
					
						
							|  |  |  |             "wsr.dbreaka1 %0\n" \ | 
					
						
							|  |  |  |             "wsr.dbreakc1 %1\n" \ | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |             ::"r"(adr), "r"(dbreakc)); | 
					
						
							| 
									
										
										
										
											2017-01-09 16:42:45 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return ESP_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void esp_clear_watchpoint(int no) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     //Setting a dbreakc register to 0 makes it trigger on neither load nor store, effectively disabling it.
 | 
					
						
							| 
									
										
										
										
											2017-09-20 17:17:51 +08:00
										 |  |  |     int dbreakc = 0; | 
					
						
							|  |  |  |     if (no == 0) { | 
					
						
							| 
									
										
										
										
											2017-01-09 16:42:45 +08:00
										 |  |  |         asm volatile( | 
					
						
							|  |  |  |             "wsr.dbreakc0 %0\n" \ | 
					
						
							|  |  |  |             ::"r"(dbreakc)); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         asm volatile( | 
					
						
							|  |  |  |             "wsr.dbreakc1 %0\n" \ | 
					
						
							|  |  |  |             ::"r"(dbreakc)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 17:22:22 +11:00
										 |  |  | void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-05-31 12:47:06 +02:00
										 |  |  |     ets_printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x", rc); | 
					
						
							|  |  |  | #ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP
 | 
					
						
							|  |  |  |     ets_printf(" (%s)", esp_err_to_name(rc)); | 
					
						
							|  |  |  | #endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP
 | 
					
						
							|  |  |  |     ets_printf(" at 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3); | 
					
						
							| 
									
										
										
										
											2017-03-02 17:22:22 +11:00
										 |  |  |     if (spi_flash_cache_enabled()) { // strings may be in flash cache
 | 
					
						
							|  |  |  |         ets_printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     invoke_abort(); | 
					
						
							|  |  |  | } |