panic.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  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 "rom/rtc.h"
  16. #include "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/rtc_cntl_reg.h"
  24. #include "soc/timer_group_struct.h"
  25. #include "soc/timer_group_reg.h"
  26. #include "soc/cpu.h"
  27. #include "soc/rtc.h"
  28. #include "esp_gdbstub.h"
  29. #include "esp_panic.h"
  30. #include "esp_attr.h"
  31. #include "esp_err.h"
  32. #include "esp_core_dump.h"
  33. #include "esp_spi_flash.h"
  34. #include "esp_cache_err_int.h"
  35. #include "esp_app_trace.h"
  36. #if CONFIG_SYSVIEW_ENABLE
  37. #include "SEGGER_RTT.h"
  38. #endif
  39. #if CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO == -1
  40. #define APPTRACE_ONPANIC_HOST_FLUSH_TMO ESP_APPTRACE_TMO_INFINITE
  41. #else
  42. #define APPTRACE_ONPANIC_HOST_FLUSH_TMO (1000*CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO)
  43. #endif
  44. /*
  45. Panic handlers; these get called when an unhandled exception occurs or the assembly-level
  46. task switching / interrupt code runs into an unrecoverable error. The default task stack
  47. overflow handler and abort handler are also in here.
  48. */
  49. /*
  50. Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled.
  51. */
  52. #if !CONFIG_ESP32_PANIC_SILENT_REBOOT
  53. //printf may be broken, so we fix our own printing fns...
  54. static void panicPutChar(char c)
  55. {
  56. while (((READ_PERI_REG(UART_STATUS_REG(CONFIG_CONSOLE_UART_NUM)) >> UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT) >= 126) ;
  57. WRITE_PERI_REG(UART_FIFO_REG(CONFIG_CONSOLE_UART_NUM), c);
  58. }
  59. static void panicPutStr(const char *c)
  60. {
  61. int x = 0;
  62. while (c[x] != 0) {
  63. panicPutChar(c[x]);
  64. x++;
  65. }
  66. }
  67. static void panicPutHex(int a)
  68. {
  69. int x;
  70. int c;
  71. for (x = 0; x < 8; x++) {
  72. c = (a >> 28) & 0xf;
  73. if (c < 10) {
  74. panicPutChar('0' + c);
  75. } else {
  76. panicPutChar('a' + c - 10);
  77. }
  78. a <<= 4;
  79. }
  80. }
  81. static void panicPutDec(int a)
  82. {
  83. int n1, n2;
  84. n1 = a % 10;
  85. n2 = a / 10;
  86. if (n2 == 0) {
  87. panicPutChar(' ');
  88. } else {
  89. panicPutChar(n2 + '0');
  90. }
  91. panicPutChar(n1 + '0');
  92. }
  93. #else
  94. //No printing wanted. Stub out these functions.
  95. static void panicPutChar(char c) { }
  96. static void panicPutStr(const char *c) { }
  97. static void panicPutHex(int a) { }
  98. static void panicPutDec(int a) { }
  99. #endif
  100. void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
  101. {
  102. panicPutStr("***ERROR*** A stack overflow in task ");
  103. panicPutStr((char *)pcTaskName);
  104. panicPutStr(" has been detected.\r\n");
  105. abort();
  106. }
  107. static bool abort_called;
  108. static __attribute__((noreturn)) inline void invoke_abort()
  109. {
  110. abort_called = true;
  111. #if CONFIG_ESP32_APPTRACE_ENABLE
  112. #if CONFIG_SYSVIEW_ENABLE
  113. SEGGER_RTT_ESP32_FlushNoLock(CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  114. #else
  115. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH,
  116. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  117. #endif
  118. #endif
  119. while(1) {
  120. if (esp_cpu_in_ocd_debug_mode()) {
  121. __asm__ ("break 0,0");
  122. }
  123. *((int*) 0) = 0;
  124. }
  125. }
  126. void abort()
  127. {
  128. #if !CONFIG_ESP32_PANIC_SILENT_REBOOT
  129. ets_printf("abort() was called at PC 0x%08x on core %d\r\n", (intptr_t)__builtin_return_address(0) - 3, xPortGetCoreID());
  130. #endif
  131. invoke_abort();
  132. }
  133. static const char *edesc[] = {
  134. "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
  135. "Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue",
  136. "Privileged", "LoadStoreAlignment", "res", "res",
  137. "InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError",
  138. "InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res",
  139. "InstrFetchProhibited", "res", "res", "res",
  140. "LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res",
  141. "LoadProhibited", "StoreProhibited", "res", "res",
  142. "Cp0Dis", "Cp1Dis", "Cp2Dis", "Cp3Dis",
  143. "Cp4Dis", "Cp5Dis", "Cp6Dis", "Cp7Dis"
  144. };
  145. #define NUM_EDESCS (sizeof(edesc) / sizeof(char *))
  146. static void commonErrorHandler(XtExcFrame *frame);
  147. //The fact that we've panic'ed probably means the other CPU is now running wild, possibly
  148. //messing up the serial output, so we stall it here.
  149. static void haltOtherCore()
  150. {
  151. esp_cpu_stall( xPortGetCoreID() == 0 ? 1 : 0 );
  152. }
  153. static void setFirstBreakpoint(uint32_t pc)
  154. {
  155. asm(
  156. "wsr.ibreaka0 %0\n" \
  157. "rsr.ibreakenable a3\n" \
  158. "movi a4,1\n" \
  159. "or a4, a4, a3\n" \
  160. "wsr.ibreakenable a4\n" \
  161. ::"r"(pc):"a3", "a4");
  162. }
  163. void panicHandler(XtExcFrame *frame)
  164. {
  165. int core_id = xPortGetCoreID();
  166. //Please keep in sync with PANIC_RSN_* defines
  167. const char *reasons[] = {
  168. "Unknown reason",
  169. "Unhandled debug exception",
  170. "Double exception",
  171. "Unhandled kernel exception",
  172. "Coprocessor exception",
  173. "Interrupt wdt timeout on CPU0",
  174. "Interrupt wdt timeout on CPU1",
  175. "Cache disabled but cached memory region accessed",
  176. };
  177. const char *reason = reasons[0];
  178. //The panic reason is stored in the EXCCAUSE register.
  179. if (frame->exccause <= PANIC_RSN_MAX) {
  180. reason = reasons[frame->exccause];
  181. }
  182. if (frame->exccause == PANIC_RSN_CACHEERR && esp_cache_err_get_cpuid() != core_id) {
  183. // Cache error interrupt will be handled by the panic handler
  184. // on the other CPU.
  185. return;
  186. }
  187. haltOtherCore();
  188. esp_dport_access_int_deinit();
  189. panicPutStr("Guru Meditation Error: Core ");
  190. panicPutDec(core_id);
  191. panicPutStr(" panic'ed (");
  192. panicPutStr(reason);
  193. panicPutStr(")\r\n");
  194. if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) {
  195. int debugRsn;
  196. asm("rsr.debugcause %0":"=r"(debugRsn));
  197. panicPutStr("Debug exception reason: ");
  198. if (debugRsn&XCHAL_DEBUGCAUSE_ICOUNT_MASK) panicPutStr("SingleStep ");
  199. if (debugRsn&XCHAL_DEBUGCAUSE_IBREAK_MASK) panicPutStr("HwBreakpoint ");
  200. if (debugRsn&XCHAL_DEBUGCAUSE_DBREAK_MASK) {
  201. //Unlike what the ISA manual says, this core seemingly distinguishes from a DBREAK
  202. //reason caused by watchdog 0 and one caused by watchdog 1 by setting bit 8 of the
  203. //debugcause if the cause is watchdog 1 and clearing it if it's watchdog 0.
  204. if (debugRsn&(1<<8)) {
  205. #if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
  206. const char *name = pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(core_id));
  207. panicPutStr("Stack canary watchpoint triggered (");
  208. panicPutStr(name);
  209. panicPutStr(") ");
  210. #else
  211. panicPutStr("Watchpoint 1 triggered ");
  212. #endif
  213. } else {
  214. panicPutStr("Watchpoint 0 triggered ");
  215. }
  216. }
  217. if (debugRsn&XCHAL_DEBUGCAUSE_BREAK_MASK) panicPutStr("BREAK instr ");
  218. if (debugRsn&XCHAL_DEBUGCAUSE_BREAKN_MASK) panicPutStr("BREAKN instr ");
  219. if (debugRsn&XCHAL_DEBUGCAUSE_DEBUGINT_MASK) panicPutStr("DebugIntr ");
  220. panicPutStr("\r\n");
  221. }
  222. if (esp_cpu_in_ocd_debug_mode()) {
  223. #if CONFIG_ESP32_APPTRACE_ENABLE
  224. #if CONFIG_SYSVIEW_ENABLE
  225. SEGGER_RTT_ESP32_FlushNoLock(CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  226. #else
  227. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH,
  228. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  229. #endif
  230. #endif
  231. setFirstBreakpoint(frame->pc);
  232. return;
  233. }
  234. commonErrorHandler(frame);
  235. }
  236. void xt_unhandled_exception(XtExcFrame *frame)
  237. {
  238. haltOtherCore();
  239. esp_dport_access_int_deinit();
  240. if (!abort_called) {
  241. panicPutStr("Guru Meditation Error of type ");
  242. int exccause = frame->exccause;
  243. if (exccause < NUM_EDESCS) {
  244. panicPutStr(edesc[exccause]);
  245. } else {
  246. panicPutStr("Unknown");
  247. }
  248. panicPutStr(" occurred on core ");
  249. panicPutDec(xPortGetCoreID());
  250. if (esp_cpu_in_ocd_debug_mode()) {
  251. panicPutStr(" at pc=");
  252. panicPutHex(frame->pc);
  253. panicPutStr(". Setting bp and returning..\r\n");
  254. #if CONFIG_ESP32_APPTRACE_ENABLE
  255. #if CONFIG_SYSVIEW_ENABLE
  256. SEGGER_RTT_ESP32_FlushNoLock(CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  257. #else
  258. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH,
  259. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  260. #endif
  261. #endif
  262. //Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger
  263. //will kick in exactly at the context the error happened.
  264. setFirstBreakpoint(frame->pc);
  265. return;
  266. }
  267. panicPutStr(". Exception was unhandled.\r\n");
  268. }
  269. commonErrorHandler(frame);
  270. }
  271. /*
  272. If watchdogs are enabled, the panic handler runs the risk of getting aborted pre-emptively because
  273. an overzealous watchdog decides to reset it. On the other hand, if we disable all watchdogs, we run
  274. the risk of somehow halting in the panic handler and not resetting. That is why this routine kills
  275. all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after
  276. one second.
  277. */
  278. static void reconfigureAllWdts()
  279. {
  280. TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
  281. TIMERG0.wdt_feed = 1;
  282. TIMERG0.wdt_config0.sys_reset_length = 7; //3.2uS
  283. TIMERG0.wdt_config0.cpu_reset_length = 7; //3.2uS
  284. TIMERG0.wdt_config0.stg0 = TIMG_WDT_STG_SEL_RESET_SYSTEM; //1st stage timeout: reset system
  285. TIMERG0.wdt_config1.clk_prescale = 80 * 500; //Prescaler: wdt counts in ticks of 0.5mS
  286. TIMERG0.wdt_config2 = 2000; //1 second before reset
  287. TIMERG0.wdt_config0.en = 1;
  288. TIMERG0.wdt_wprotect = 0;
  289. //Disable wdt 1
  290. TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
  291. TIMERG1.wdt_config0.en = 0;
  292. TIMERG1.wdt_wprotect = 0;
  293. }
  294. /*
  295. This disables all the watchdogs for when we call the gdbstub.
  296. */
  297. static inline void disableAllWdts()
  298. {
  299. TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
  300. TIMERG0.wdt_config0.en = 0;
  301. TIMERG0.wdt_wprotect = 0;
  302. TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
  303. TIMERG1.wdt_config0.en = 0;
  304. TIMERG1.wdt_wprotect = 0;
  305. }
  306. static void esp_panic_wdt_start()
  307. {
  308. if (REG_GET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN)) {
  309. return;
  310. }
  311. WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
  312. WRITE_PERI_REG(RTC_CNTL_WDTFEED_REG, 1);
  313. REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_SYS_RESET_LENGTH, 7);
  314. REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_CPU_RESET_LENGTH, 7);
  315. REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG0, RTC_WDT_STG_SEL_RESET_SYSTEM);
  316. // 64KB of core dump data (stacks of about 30 tasks) will produce ~85KB base64 data.
  317. // @ 115200 UART speed it will take more than 6 sec to print them out.
  318. WRITE_PERI_REG(RTC_CNTL_WDTCONFIG1_REG, rtc_clk_slow_freq_get_hz() * 7);
  319. REG_SET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN);
  320. WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0);
  321. }
  322. void esp_panic_wdt_stop()
  323. {
  324. WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
  325. WRITE_PERI_REG(RTC_CNTL_WDTFEED_REG, 1);
  326. REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG0, RTC_WDT_STG_SEL_OFF);
  327. REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN);
  328. WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0);
  329. }
  330. static void esp_panic_dig_reset() __attribute__((noreturn));
  331. static void esp_panic_dig_reset()
  332. {
  333. // make sure all the panic handler output is sent from UART FIFO
  334. uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM);
  335. // switch to XTAL (otherwise we will keep running from the PLL)
  336. rtc_clk_cpu_freq_set(RTC_CPU_FREQ_XTAL);
  337. // reset the digital part
  338. esp_cpu_unstall(PRO_CPU_NUM);
  339. SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
  340. while (true) {
  341. ;
  342. }
  343. }
  344. static void putEntry(uint32_t pc, uint32_t sp)
  345. {
  346. if (pc & 0x80000000) {
  347. pc = (pc & 0x3fffffff) | 0x40000000;
  348. }
  349. panicPutStr(" 0x");
  350. panicPutHex(pc);
  351. panicPutStr(":0x");
  352. panicPutHex(sp);
  353. }
  354. static void doBacktrace(XtExcFrame *frame)
  355. {
  356. uint32_t i = 0, pc = frame->pc, sp = frame->a1;
  357. panicPutStr("\r\nBacktrace:");
  358. /* Do not check sanity on first entry, PC could be smashed. */
  359. putEntry(pc, sp);
  360. pc = frame->a0;
  361. while (i++ < 100) {
  362. uint32_t psp = sp;
  363. if (!esp_stack_ptr_is_sane(sp) || i++ > 100) {
  364. break;
  365. }
  366. sp = *((uint32_t *) (sp - 0x10 + 4));
  367. putEntry(pc - 3, sp); // stack frame addresses are return addresses, so subtract 3 to get the CALL address
  368. pc = *((uint32_t *) (psp - 0x10));
  369. if (pc < 0x40000000) {
  370. break;
  371. }
  372. }
  373. panicPutStr("\r\n\r\n");
  374. }
  375. void esp_restart_noos() __attribute__ ((noreturn));
  376. /*
  377. We arrive here after a panic or unhandled exception, when no OCD is detected. Dump the registers to the
  378. serial port and either jump to the gdb stub, halt the CPU or reboot.
  379. */
  380. static __attribute__((noreturn)) void commonErrorHandler(XtExcFrame *frame)
  381. {
  382. int *regs = (int *)frame;
  383. int x, y;
  384. const char *sdesc[] = {
  385. "PC ", "PS ", "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ",
  386. "A6 ", "A7 ", "A8 ", "A9 ", "A10 ", "A11 ", "A12 ", "A13 ",
  387. "A14 ", "A15 ", "SAR ", "EXCCAUSE", "EXCVADDR", "LBEG ", "LEND ", "LCOUNT "
  388. };
  389. // start panic WDT to restart system if we hang in this handler
  390. esp_panic_wdt_start();
  391. //Feed the watchdogs, so they will give us time to print out debug info
  392. reconfigureAllWdts();
  393. /* only dump registers for 'real' crashes, if crashing via abort()
  394. the register window is no longer useful.
  395. */
  396. if (!abort_called) {
  397. panicPutStr("Register dump:\r\n");
  398. for (x = 0; x < 24; x += 4) {
  399. for (y = 0; y < 4; y++) {
  400. if (sdesc[x + y][0] != 0) {
  401. panicPutStr(sdesc[x + y]);
  402. panicPutStr(": 0x");
  403. panicPutHex(regs[x + y + 1]);
  404. panicPutStr(" ");
  405. }
  406. }
  407. panicPutStr("\r\n");
  408. }
  409. }
  410. /* With windowed ABI backtracing is easy, let's do it. */
  411. doBacktrace(frame);
  412. #if CONFIG_ESP32_APPTRACE_ENABLE
  413. disableAllWdts();
  414. #if CONFIG_SYSVIEW_ENABLE
  415. SEGGER_RTT_ESP32_FlushNoLock(CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  416. #else
  417. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH,
  418. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  419. #endif
  420. reconfigureAllWdts();
  421. #endif
  422. #if CONFIG_ESP32_PANIC_GDBSTUB
  423. disableAllWdts();
  424. esp_panic_wdt_stop();
  425. panicPutStr("Entering gdb stub now.\r\n");
  426. esp_gdbstub_panic_handler(frame);
  427. #else
  428. #if CONFIG_ESP32_ENABLE_COREDUMP
  429. disableAllWdts();
  430. #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
  431. esp_core_dump_to_flash(frame);
  432. #endif
  433. #if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART && !CONFIG_ESP32_PANIC_SILENT_REBOOT
  434. esp_core_dump_to_uart(frame);
  435. #endif
  436. reconfigureAllWdts();
  437. #endif /* CONFIG_ESP32_ENABLE_COREDUMP */
  438. esp_panic_wdt_stop();
  439. #if CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
  440. panicPutStr("Rebooting...\r\n");
  441. if (frame->exccause != PANIC_RSN_CACHEERR) {
  442. esp_restart_noos();
  443. } else {
  444. // The only way to clear invalid cache access interrupt is to reset the digital part
  445. esp_panic_dig_reset();
  446. }
  447. #else
  448. disableAllWdts();
  449. panicPutStr("CPU halted.\r\n");
  450. while (1);
  451. #endif /* CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT */
  452. #endif /* CONFIG_ESP32_PANIC_GDBSTUB */
  453. }
  454. void esp_set_breakpoint_if_jtag(void *fn)
  455. {
  456. if (esp_cpu_in_ocd_debug_mode()) {
  457. setFirstBreakpoint((uint32_t)fn);
  458. }
  459. }
  460. esp_err_t esp_set_watchpoint(int no, void *adr, int size, int flags)
  461. {
  462. int x;
  463. if (no<0 || no>1) return ESP_ERR_INVALID_ARG;
  464. if (flags&(~0xC0000000)) return ESP_ERR_INVALID_ARG;
  465. int dbreakc=0x3F;
  466. //We support watching 2^n byte values, from 1 to 64. Calculate the mask for that.
  467. for (x=0; x<7; x++) {
  468. if (size==(1<<x)) break;
  469. dbreakc<<=1;
  470. }
  471. if (x==7) return ESP_ERR_INVALID_ARG;
  472. //Mask mask and add in flags.
  473. dbreakc=(dbreakc&0x3f)|flags;
  474. if (no==0) {
  475. asm volatile(
  476. "wsr.dbreaka0 %0\n" \
  477. "wsr.dbreakc0 %1\n" \
  478. ::"r"(adr),"r"(dbreakc));
  479. } else {
  480. asm volatile(
  481. "wsr.dbreaka1 %0\n" \
  482. "wsr.dbreakc1 %1\n" \
  483. ::"r"(adr),"r"(dbreakc));
  484. }
  485. return ESP_OK;
  486. }
  487. void esp_clear_watchpoint(int no)
  488. {
  489. //Setting a dbreakc register to 0 makes it trigger on neither load nor store, effectively disabling it.
  490. int dbreakc=0;
  491. if (no==0) {
  492. asm volatile(
  493. "wsr.dbreakc0 %0\n" \
  494. ::"r"(dbreakc));
  495. } else {
  496. asm volatile(
  497. "wsr.dbreakc1 %0\n" \
  498. ::"r"(dbreakc));
  499. }
  500. }
  501. void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression)
  502. {
  503. ets_printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at 0x%08x\n", rc, (intptr_t)__builtin_return_address(0) - 3);
  504. if (spi_flash_cache_enabled()) { // strings may be in flash cache
  505. ets_printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression);
  506. }
  507. invoke_abort();
  508. }