panic.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <stdlib.h>
  14. #include <xtensa/config/core.h>
  15. #include "esp32s2/rom/rtc.h"
  16. #include "esp32s2/rom/uart.h"
  17. #include "freertos/FreeRTOS.h"
  18. #include "freertos/task.h"
  19. #include "freertos/xtensa_api.h"
  20. #include "soc/uart_reg.h"
  21. #include "soc/io_mux_reg.h"
  22. #include "soc/dport_reg.h"
  23. #include "soc/extmem_reg.h"
  24. #include "soc/cache_memory.h"
  25. #include "soc/rtc_cntl_reg.h"
  26. #include "soc/timer_group_struct.h"
  27. #include "soc/timer_group_reg.h"
  28. #include "soc/cpu.h"
  29. #include "soc/soc_memory_layout.h"
  30. #include "soc/rtc.h"
  31. #include "soc/rtc_wdt.h"
  32. #include "esp_private/gdbstub.h"
  33. #include "esp_debug_helpers.h"
  34. #include "esp_private/panic_reason.h"
  35. #include "esp_attr.h"
  36. #include "esp_err.h"
  37. #include "esp_core_dump.h"
  38. #include "esp_spi_flash.h"
  39. #include "esp32s2/cache_err_int.h"
  40. #include "esp_app_trace.h"
  41. #include "esp_private/system_internal.h"
  42. #include "sdkconfig.h"
  43. #if CONFIG_SYSVIEW_ENABLE
  44. #include "SEGGER_RTT.h"
  45. #endif
  46. #if CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO == -1
  47. #define APPTRACE_ONPANIC_HOST_FLUSH_TMO ESP_APPTRACE_TMO_INFINITE
  48. #else
  49. #define APPTRACE_ONPANIC_HOST_FLUSH_TMO (1000*CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO)
  50. #endif
  51. /*
  52. Panic handlers; these get called when an unhandled exception occurs or the assembly-level
  53. task switching / interrupt code runs into an unrecoverable error. The default task stack
  54. overflow handler and abort handler are also in here.
  55. */
  56. /*
  57. Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled.
  58. */
  59. #if !CONFIG_ESP32S2_PANIC_SILENT_REBOOT
  60. //printf may be broken, so we fix our own printing fns...
  61. static void panicPutChar(char c)
  62. {
  63. while (((READ_PERI_REG(UART_STATUS_REG(CONFIG_ESP_CONSOLE_UART_NUM)) >> UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT) >= 126) ;
  64. WRITE_PERI_REG(UART_FIFO_AHB_REG(CONFIG_ESP_CONSOLE_UART_NUM), c);
  65. }
  66. static void panicPutStr(const char *c)
  67. {
  68. int x = 0;
  69. while (c[x] != 0) {
  70. panicPutChar(c[x]);
  71. x++;
  72. }
  73. }
  74. static void panicPutHex(int a)
  75. {
  76. int x;
  77. int c;
  78. for (x = 0; x < 8; x++) {
  79. c = (a >> 28) & 0xf;
  80. if (c < 10) {
  81. panicPutChar('0' + c);
  82. } else {
  83. panicPutChar('a' + c - 10);
  84. }
  85. a <<= 4;
  86. }
  87. }
  88. static void panicPutDec(int a)
  89. {
  90. int n1, n2;
  91. n1 = a % 10;
  92. n2 = a / 10;
  93. if (n2 == 0) {
  94. panicPutChar(' ');
  95. } else {
  96. panicPutChar(n2 + '0');
  97. }
  98. panicPutChar(n1 + '0');
  99. }
  100. #else
  101. //No printing wanted. Stub out these functions.
  102. static void panicPutChar(char c) { }
  103. static void panicPutStr(const char *c) { }
  104. static void panicPutHex(int a) { }
  105. static void panicPutDec(int a) { }
  106. #endif
  107. void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
  108. {
  109. panicPutStr("***ERROR*** A stack overflow in task ");
  110. panicPutStr((char *)pcTaskName);
  111. panicPutStr(" has been detected.\r\n");
  112. abort();
  113. }
  114. /* These two weak stubs for esp_reset_reason_{get,set}_hint are used when
  115. * the application does not call esp_reset_reason() function, and
  116. * reset_reason.c is not linked into the output file.
  117. */
  118. void __attribute__((weak)) esp_reset_reason_set_hint(esp_reset_reason_t hint)
  119. {
  120. }
  121. esp_reset_reason_t __attribute__((weak)) esp_reset_reason_get_hint(void)
  122. {
  123. return ESP_RST_UNKNOWN;
  124. }
  125. static bool abort_called;
  126. static __attribute__((noreturn)) inline void invoke_abort(void)
  127. {
  128. abort_called = true;
  129. #if CONFIG_APPTRACE_ENABLE
  130. #if CONFIG_SYSVIEW_ENABLE
  131. SEGGER_RTT_ESP32_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  132. #else
  133. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH,
  134. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  135. #endif
  136. #endif
  137. while (1) {
  138. if (esp_cpu_in_ocd_debug_mode()) {
  139. __asm__ ("break 0,0");
  140. }
  141. *((int *) 0) = 0;
  142. }
  143. }
  144. void abort(void)
  145. {
  146. #if !CONFIG_ESP32S2_PANIC_SILENT_REBOOT
  147. ets_printf("abort() was called at PC 0x%08x on core %d\r\n", (intptr_t)__builtin_return_address(0) - 3, xPortGetCoreID());
  148. #endif
  149. /* Calling code might have set other reset reason hint (such as Task WDT),
  150. * don't overwrite that.
  151. */
  152. if (esp_reset_reason_get_hint() == ESP_RST_UNKNOWN) {
  153. esp_reset_reason_set_hint(ESP_RST_PANIC);
  154. }
  155. invoke_abort();
  156. }
  157. static const char *edesc[] = {
  158. "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
  159. "Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue",
  160. "Privileged", "LoadStoreAlignment", "res", "res",
  161. "InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError",
  162. "InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res",
  163. "InstrFetchProhibited", "res", "res", "res",
  164. "LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res",
  165. "LoadProhibited", "StoreProhibited", "res", "res",
  166. "Cp0Dis", "Cp1Dis", "Cp2Dis", "Cp3Dis",
  167. "Cp4Dis", "Cp5Dis", "Cp6Dis", "Cp7Dis"
  168. };
  169. #define NUM_EDESCS (sizeof(edesc) / sizeof(char *))
  170. static void commonErrorHandler(XtExcFrame *frame);
  171. static inline void disableAllWdts(void);
  172. //The fact that we've panic'ed probably means the other CPU is now running wild, possibly
  173. //messing up the serial output, so we stall it here.
  174. static void setFirstBreakpoint(uint32_t pc)
  175. {
  176. asm(
  177. "wsr.ibreaka0 %0\n" \
  178. "rsr.ibreakenable a3\n" \
  179. "movi a4,1\n" \
  180. "or a4, a4, a3\n" \
  181. "wsr.ibreakenable a4\n" \
  182. ::"r"(pc):"a3", "a4");
  183. }
  184. static inline void printCacheError(void)
  185. {
  186. uint32_t vaddr = 0, size = 0;
  187. uint32_t status[2];
  188. status[0] = REG_READ(EXTMEM_CACHE_DBG_STATUS0_REG);
  189. status[1] = REG_READ(EXTMEM_CACHE_DBG_STATUS1_REG);
  190. for (int i = 0; i < 32; i++) {
  191. switch (status[0] & BIT(i)) {
  192. case EXTMEM_IC_SYNC_SIZE_FAULT_ST:
  193. vaddr = REG_READ(EXTMEM_PRO_ICACHE_MEM_SYNC0_REG);
  194. size = REG_READ(EXTMEM_PRO_ICACHE_MEM_SYNC1_REG);
  195. panicPutStr("Icache sync parameter configuration error, the error address and size is 0x");
  196. panicPutHex(vaddr);
  197. panicPutStr("(0x");
  198. panicPutHex(size);
  199. panicPutStr(")\r\n");
  200. break;
  201. case EXTMEM_IC_PRELOAD_SIZE_FAULT_ST:
  202. vaddr = REG_READ(EXTMEM_PRO_ICACHE_PRELOAD_ADDR_REG);
  203. size = REG_READ(EXTMEM_PRO_ICACHE_PRELOAD_SIZE_REG);
  204. panicPutStr("Icache preload parameter configuration error, the error address and size is 0x");
  205. panicPutHex(vaddr);
  206. panicPutStr("(0x");
  207. panicPutHex(size);
  208. panicPutStr(")\r\n");
  209. break;
  210. case EXTMEM_ICACHE_REJECT_ST:
  211. vaddr = REG_READ(EXTMEM_PRO_ICACHE_REJECT_VADDR_REG);
  212. panicPutStr("Icache reject error occurred while accessing the address 0x");
  213. panicPutHex(vaddr);
  214. if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
  215. panicPutStr(" (invalid mmu entry)");
  216. }
  217. panicPutStr("\r\n");
  218. break;
  219. default:
  220. break;
  221. }
  222. switch (status[1] & BIT(i)) {
  223. case EXTMEM_DC_SYNC_SIZE_FAULT_ST:
  224. vaddr = REG_READ(EXTMEM_PRO_DCACHE_MEM_SYNC0_REG);
  225. size = REG_READ(EXTMEM_PRO_DCACHE_MEM_SYNC1_REG);
  226. panicPutStr("Dcache sync parameter configuration error, the error address and size is 0x");
  227. panicPutHex(vaddr);
  228. panicPutStr("(0x");
  229. panicPutHex(size);
  230. panicPutStr(")\r\n");
  231. break;
  232. case EXTMEM_DC_PRELOAD_SIZE_FAULT_ST:
  233. vaddr = REG_READ(EXTMEM_PRO_DCACHE_PRELOAD_ADDR_REG);
  234. size = REG_READ(EXTMEM_PRO_DCACHE_PRELOAD_SIZE_REG);
  235. panicPutStr("Dcache preload parameter configuration error, the error address and size is 0x");
  236. panicPutHex(vaddr);
  237. panicPutStr("(0x");
  238. panicPutHex(size);
  239. panicPutStr(")\r\n");
  240. break;
  241. case EXTMEM_DCACHE_WRITE_FLASH_ST:
  242. panicPutStr("Write back error occurred while dcache tries to write back to flash\r\n");
  243. break;
  244. case EXTMEM_DCACHE_REJECT_ST:
  245. vaddr = REG_READ(EXTMEM_PRO_DCACHE_REJECT_VADDR_REG);
  246. panicPutStr("Dcache reject error occurred while accessing the address 0x");
  247. panicPutHex(vaddr);
  248. if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
  249. panicPutStr(" (invalid mmu entry)");
  250. }
  251. panicPutStr("\r\n");
  252. break;
  253. case EXTMEM_MMU_ENTRY_FAULT_ST:
  254. vaddr = REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_VADDR_REG);
  255. panicPutStr("MMU entry fault error occurred while accessing the address 0x");
  256. panicPutHex(vaddr);
  257. if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
  258. panicPutStr(" (invalid mmu entry)");
  259. }
  260. panicPutStr("\r\n");
  261. break;
  262. default:
  263. break;
  264. }
  265. }
  266. panicPutStr("\r\n");
  267. }
  268. void panicHandler(XtExcFrame *frame)
  269. {
  270. int core_id = xPortGetCoreID();
  271. //Please keep in sync with PANIC_RSN_* defines
  272. const char *reasons[] = {
  273. "Unknown reason",
  274. "Unhandled debug exception",
  275. "Double exception",
  276. "Unhandled kernel exception",
  277. "Coprocessor exception",
  278. "Interrupt wdt timeout on CPU0",
  279. "Interrupt wdt timeout on CPU1",
  280. "Cache exception",
  281. };
  282. const char *reason = reasons[0];
  283. //The panic reason is stored in the EXCCAUSE register.
  284. if (frame->exccause <= PANIC_RSN_MAX) {
  285. reason = reasons[frame->exccause];
  286. }
  287. if (frame->exccause == PANIC_RSN_INTWDT_CPU0) {
  288. esp_reset_reason_set_hint(ESP_RST_INT_WDT);
  289. }
  290. panicPutStr("Guru Meditation Error: Core ");
  291. panicPutDec(core_id);
  292. panicPutStr(" panic'ed (");
  293. panicPutStr(reason);
  294. panicPutStr(")\r\n");
  295. if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) {
  296. int debugRsn;
  297. asm("rsr.debugcause %0":"=r"(debugRsn));
  298. panicPutStr("Debug exception reason: ");
  299. if (debugRsn & XCHAL_DEBUGCAUSE_ICOUNT_MASK) {
  300. panicPutStr("SingleStep ");
  301. }
  302. if (debugRsn & XCHAL_DEBUGCAUSE_IBREAK_MASK) {
  303. panicPutStr("HwBreakpoint ");
  304. }
  305. if (debugRsn & XCHAL_DEBUGCAUSE_DBREAK_MASK) {
  306. //Unlike what the ISA manual says, this core seemingly distinguishes from a DBREAK
  307. //reason caused by watchdog 0 and one caused by watchdog 1 by setting bit 8 of the
  308. //debugcause if the cause is watchdog 1 and clearing it if it's watchdog 0.
  309. if (debugRsn & (1 << 8)) {
  310. #if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
  311. const char *name = pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(core_id));
  312. panicPutStr("Stack canary watchpoint triggered (");
  313. panicPutStr(name);
  314. panicPutStr(") ");
  315. #else
  316. panicPutStr("Watchpoint 1 triggered ");
  317. #endif
  318. } else {
  319. panicPutStr("Watchpoint 0 triggered ");
  320. }
  321. }
  322. if (debugRsn & XCHAL_DEBUGCAUSE_BREAK_MASK) {
  323. panicPutStr("BREAK instr ");
  324. }
  325. if (debugRsn & XCHAL_DEBUGCAUSE_BREAKN_MASK) {
  326. panicPutStr("BREAKN instr ");
  327. }
  328. if (debugRsn & XCHAL_DEBUGCAUSE_DEBUGINT_MASK) {
  329. panicPutStr("DebugIntr ");
  330. }
  331. panicPutStr("\r\n");
  332. } else if (frame->exccause == PANIC_RSN_CACHEERR) {
  333. panicPutStr(" ^~~~~~~~~~~~~~~\r\n");
  334. printCacheError();
  335. }
  336. if (esp_cpu_in_ocd_debug_mode()) {
  337. disableAllWdts();
  338. if (frame->exccause == PANIC_RSN_INTWDT_CPU0 ||
  339. frame->exccause == PANIC_RSN_INTWDT_CPU1) {
  340. TIMERG1.int_clr.wdt = 1;
  341. }
  342. #if CONFIG_APPTRACE_ENABLE
  343. #if CONFIG_SYSVIEW_ENABLE
  344. SEGGER_RTT_ESP32_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  345. #else
  346. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH,
  347. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  348. #endif
  349. #endif
  350. setFirstBreakpoint(frame->pc);
  351. return;
  352. }
  353. commonErrorHandler(frame);
  354. }
  355. void xt_unhandled_exception(XtExcFrame *frame)
  356. {
  357. if (!abort_called) {
  358. panicPutStr("Guru Meditation Error: Core ");
  359. panicPutDec(xPortGetCoreID());
  360. panicPutStr(" panic'ed (");
  361. int exccause = frame->exccause;
  362. if (exccause < NUM_EDESCS) {
  363. panicPutStr(edesc[exccause]);
  364. } else {
  365. panicPutStr("Unknown");
  366. }
  367. panicPutStr(")");
  368. if (esp_cpu_in_ocd_debug_mode()) {
  369. panicPutStr(" at pc=");
  370. panicPutHex(frame->pc);
  371. panicPutStr(". Setting bp and returning..\r\n");
  372. #if CONFIG_APPTRACE_ENABLE
  373. #if CONFIG_SYSVIEW_ENABLE
  374. SEGGER_RTT_ESP32_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  375. #else
  376. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH,
  377. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  378. #endif
  379. #endif
  380. //Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger
  381. //will kick in exactly at the context the error happened.
  382. setFirstBreakpoint(frame->pc);
  383. return;
  384. }
  385. panicPutStr(". Exception was unhandled.\r\n");
  386. esp_reset_reason_set_hint(ESP_RST_PANIC);
  387. }
  388. commonErrorHandler(frame);
  389. }
  390. /*
  391. If watchdogs are enabled, the panic handler runs the risk of getting aborted pre-emptively because
  392. an overzealous watchdog decides to reset it. On the other hand, if we disable all watchdogs, we run
  393. the risk of somehow halting in the panic handler and not resetting. That is why this routine kills
  394. all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after
  395. one second.
  396. */
  397. static void reconfigureAllWdts(void)
  398. {
  399. TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
  400. TIMERG0.wdt_feed = 1;
  401. TIMERG0.wdt_config0.sys_reset_length = 7; //3.2uS
  402. TIMERG0.wdt_config0.cpu_reset_length = 7; //3.2uS
  403. TIMERG0.wdt_config0.stg0 = TIMG_WDT_STG_SEL_RESET_SYSTEM; //1st stage timeout: reset system
  404. TIMERG0.wdt_config1.clk_prescale = 80 * 500; //Prescaler: wdt counts in ticks of 0.5mS
  405. TIMERG0.wdt_config2 = 2000; //1 second before reset
  406. TIMERG0.wdt_config0.en = 1;
  407. TIMERG0.wdt_wprotect = 0;
  408. //Disable wdt 1
  409. TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
  410. TIMERG1.wdt_config0.en = 0;
  411. TIMERG1.wdt_wprotect = 0;
  412. }
  413. /*
  414. This disables all the watchdogs for when we call the gdbstub.
  415. */
  416. static inline void disableAllWdts(void)
  417. {
  418. TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
  419. TIMERG0.wdt_config0.en = 0;
  420. TIMERG0.wdt_wprotect = 0;
  421. TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
  422. TIMERG1.wdt_config0.en = 0;
  423. TIMERG1.wdt_wprotect = 0;
  424. }
  425. #if CONFIG_ESP32S2_PANIC_PRINT_REBOOT || CONFIG_ESP32S2_PANIC_SILENT_REBOOT
  426. static void esp_panic_dig_reset(void) __attribute__((noreturn));
  427. static void esp_panic_dig_reset(void)
  428. {
  429. // make sure all the panic handler output is sent from UART FIFO
  430. uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
  431. // switch to XTAL (otherwise we will keep running from the PLL)
  432. rtc_clk_cpu_freq_set_xtal();
  433. SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
  434. while (true) {
  435. ;
  436. }
  437. }
  438. #endif
  439. static void putEntry(uint32_t pc, uint32_t sp)
  440. {
  441. if (pc & 0x80000000) {
  442. pc = (pc & 0x3fffffff) | 0x40000000;
  443. }
  444. panicPutStr(" 0x");
  445. panicPutHex(pc);
  446. panicPutStr(":0x");
  447. panicPutHex(sp);
  448. }
  449. static void doBacktrace(XtExcFrame *frame)
  450. {
  451. uint32_t i = 0, pc = frame->pc, sp = frame->a1;
  452. panicPutStr("\r\nBacktrace:");
  453. /* Do not check sanity on first entry, PC could be smashed. */
  454. putEntry(pc, sp);
  455. pc = frame->a0;
  456. while (i++ < 100) {
  457. uint32_t psp = sp;
  458. if (!esp_stack_ptr_is_sane(sp) || i++ > 100) {
  459. break;
  460. }
  461. sp = *((uint32_t *) (sp - 0x10 + 4));
  462. putEntry(pc - 3, sp); // stack frame addresses are return addresses, so subtract 3 to get the CALL address
  463. pc = *((uint32_t *) (psp - 0x10));
  464. if (pc < 0x40000000) {
  465. break;
  466. }
  467. }
  468. panicPutStr("\r\n\r\n");
  469. }
  470. /*
  471. * Dump registers and do backtrace.
  472. */
  473. static void commonErrorHandler_dump(XtExcFrame *frame, int core_id)
  474. {
  475. int *regs = (int *)frame;
  476. int x, y;
  477. const char *sdesc[] = {
  478. "PC ", "PS ", "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ",
  479. "A6 ", "A7 ", "A8 ", "A9 ", "A10 ", "A11 ", "A12 ", "A13 ",
  480. "A14 ", "A15 ", "SAR ", "EXCCAUSE", "EXCVADDR", "LBEG ", "LEND ", "LCOUNT "
  481. };
  482. /* only dump registers for 'real' crashes, if crashing via abort()
  483. the register window is no longer useful.
  484. */
  485. if (!abort_called) {
  486. panicPutStr("Core");
  487. panicPutDec(core_id);
  488. panicPutStr(" register dump:\r\n");
  489. for (x = 0; x < 24; x += 4) {
  490. for (y = 0; y < 4; y++) {
  491. if (sdesc[x + y][0] != 0) {
  492. panicPutStr(sdesc[x + y]);
  493. panicPutStr(": 0x");
  494. panicPutHex(regs[x + y + 1]);
  495. panicPutStr(" ");
  496. }
  497. }
  498. panicPutStr("\r\n");
  499. }
  500. if (xPortInterruptedFromISRContext()) {
  501. //If the core which triggers the interrupt watchdog was in ISR context, dump the epc registers.
  502. uint32_t __value;
  503. panicPutStr("Core");
  504. panicPutDec(core_id);
  505. panicPutStr(" was running in ISR context:\r\n");
  506. __asm__("rsr.epc1 %0" : "=a"(__value));
  507. panicPutStr("EPC1 : 0x");
  508. panicPutHex(__value);
  509. __asm__("rsr.epc2 %0" : "=a"(__value));
  510. panicPutStr(" EPC2 : 0x");
  511. panicPutHex(__value);
  512. __asm__("rsr.epc3 %0" : "=a"(__value));
  513. panicPutStr(" EPC3 : 0x");
  514. panicPutHex(__value);
  515. __asm__("rsr.epc4 %0" : "=a"(__value));
  516. panicPutStr(" EPC4 : 0x");
  517. panicPutHex(__value);
  518. panicPutStr("\r\n");
  519. }
  520. }
  521. /* With windowed ABI backtracing is easy, let's do it. */
  522. doBacktrace(frame);
  523. }
  524. /*
  525. We arrive here after a panic or unhandled exception, when no OCD is detected. Dump the registers to the
  526. serial port and either jump to the gdb stub, halt the CPU or reboot.
  527. */
  528. static __attribute__((noreturn)) void commonErrorHandler(XtExcFrame *frame)
  529. {
  530. int core_id = xPortGetCoreID();
  531. // start panic WDT to restart system if we hang in this handler
  532. if (!rtc_wdt_is_on()) {
  533. rtc_wdt_protect_off();
  534. rtc_wdt_disable();
  535. rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us);
  536. rtc_wdt_set_length_of_reset_signal(RTC_WDT_CPU_RESET_SIG, RTC_WDT_LENGTH_3_2us);
  537. rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_SYSTEM);
  538. // 64KB of core dump data (stacks of about 30 tasks) will produce ~85KB base64 data.
  539. // @ 115200 UART speed it will take more than 6 sec to print them out.
  540. rtc_wdt_set_time(RTC_WDT_STAGE0, 7000);
  541. rtc_wdt_enable();
  542. rtc_wdt_protect_on();
  543. }
  544. //Feed the watchdogs, so they will give us time to print out debug info
  545. reconfigureAllWdts();
  546. commonErrorHandler_dump(frame, core_id);
  547. #if CONFIG_APPTRACE_ENABLE
  548. disableAllWdts();
  549. #if CONFIG_SYSVIEW_ENABLE
  550. SEGGER_RTT_ESP32_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  551. #else
  552. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH,
  553. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  554. #endif
  555. reconfigureAllWdts();
  556. #endif
  557. #if CONFIG_ESP32S2_PANIC_GDBSTUB
  558. disableAllWdts();
  559. rtc_wdt_disable();
  560. panicPutStr("Entering gdb stub now.\r\n");
  561. esp_gdbstub_panic_handler(frame);
  562. #else
  563. #if CONFIG_ESP32_ENABLE_COREDUMP
  564. static bool s_dumping_core;
  565. if (s_dumping_core) {
  566. panicPutStr("Re-entered core dump! Exception happened during core dump!\r\n");
  567. } else {
  568. disableAllWdts();
  569. s_dumping_core = true;
  570. #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
  571. esp_core_dump_to_flash(frame);
  572. #endif
  573. #if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART && !CONFIG_ESP32S2_PANIC_SILENT_REBOOT
  574. esp_core_dump_to_uart(frame);
  575. #endif
  576. s_dumping_core = false;
  577. reconfigureAllWdts();
  578. }
  579. #endif /* CONFIG_ESP32_ENABLE_COREDUMP */
  580. rtc_wdt_disable();
  581. #if CONFIG_ESP32S2_PANIC_PRINT_REBOOT || CONFIG_ESP32S2_PANIC_SILENT_REBOOT
  582. panicPutStr("Rebooting...\r\n");
  583. if (frame->exccause != PANIC_RSN_CACHEERR) {
  584. esp_restart_noos();
  585. } else {
  586. // The only way to clear invalid cache access interrupt is to reset the digital part
  587. esp_panic_dig_reset();
  588. }
  589. #else
  590. disableAllWdts();
  591. panicPutStr("CPU halted.\r\n");
  592. while (1);
  593. #endif /* CONFIG_ESP32S2_PANIC_PRINT_REBOOT || CONFIG_ESP32S2_PANIC_SILENT_REBOOT */
  594. #endif /* CONFIG_ESP32S2_PANIC_GDBSTUB */
  595. }
  596. void esp_set_breakpoint_if_jtag(void *fn)
  597. {
  598. if (esp_cpu_in_ocd_debug_mode()) {
  599. setFirstBreakpoint((uint32_t)fn);
  600. }
  601. }
  602. void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression)
  603. {
  604. ets_printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x", rc);
  605. #ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP
  606. ets_printf(" (%s)", esp_err_to_name(rc));
  607. #endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP
  608. ets_printf(" at 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3);
  609. if (spi_flash_cache_enabled()) { // strings may be in flash cache
  610. ets_printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression);
  611. }
  612. invoke_abort();
  613. }