panic.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include "esp_err.h"
  9. #include "esp_attr.h"
  10. #include "esp_private/system_internal.h"
  11. #include "esp_private/usb_console.h"
  12. #include "esp_cpu.h"
  13. #include "soc/rtc.h"
  14. #include "hal/timer_hal.h"
  15. #include "hal/wdt_types.h"
  16. #include "hal/wdt_hal.h"
  17. #include "hal/mwdt_ll.h"
  18. #include "esp_private/esp_int_wdt.h"
  19. #include "esp_private/panic_internal.h"
  20. #include "port/panic_funcs.h"
  21. #include "esp_rom_sys.h"
  22. #include "sdkconfig.h"
  23. #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  24. #if __has_include("esp_app_desc.h")
  25. #define WITH_ELF_SHA256
  26. #include "esp_app_desc.h"
  27. #endif
  28. #endif // CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  29. #if CONFIG_ESP_COREDUMP_ENABLE
  30. #include "esp_core_dump.h"
  31. #endif
  32. #if CONFIG_APPTRACE_ENABLE
  33. #include "esp_app_trace.h"
  34. #if CONFIG_APPTRACE_SV_ENABLE
  35. #include "SEGGER_RTT.h"
  36. #endif
  37. #if CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO == -1
  38. #define APPTRACE_ONPANIC_HOST_FLUSH_TMO ESP_APPTRACE_TMO_INFINITE
  39. #else
  40. #define APPTRACE_ONPANIC_HOST_FLUSH_TMO (1000*CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO)
  41. #endif
  42. #endif // CONFIG_APPTRACE_ENABLE
  43. #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  44. #include "hal/uart_hal.h"
  45. #endif
  46. #if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB
  47. #include "esp_gdbstub.h"
  48. #endif
  49. #if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG || CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
  50. #include "hal/usb_serial_jtag_ll.h"
  51. #endif
  52. #ifdef __XTENSA__
  53. #include "xtensa/semihosting.h"
  54. #elif __riscv
  55. #include "riscv/semihosting.h"
  56. #endif
  57. #define ESP_SEMIHOSTING_SYS_PANIC_REASON 0x116
  58. #define MWDT_DEFAULT_TICKS_PER_US 500
  59. bool g_panic_abort = false;
  60. char *g_panic_abort_details = NULL;
  61. static wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT();
  62. #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  63. #if CONFIG_ESP_CONSOLE_UART
  64. static uart_hal_context_t s_panic_uart = { .dev = CONFIG_ESP_CONSOLE_UART_NUM == 0 ? &UART0 :&UART1 };
  65. static void panic_print_char_uart(const char c)
  66. {
  67. uint32_t sz = 0;
  68. while (!uart_hal_get_txfifo_len(&s_panic_uart));
  69. uart_hal_write_txfifo(&s_panic_uart, (uint8_t *) &c, 1, &sz);
  70. }
  71. #endif // CONFIG_ESP_CONSOLE_UART
  72. #if CONFIG_ESP_CONSOLE_USB_CDC
  73. static void panic_print_char_usb_cdc(const char c)
  74. {
  75. esp_usb_console_write_buf(&c, 1);
  76. /* result ignored */
  77. }
  78. #endif // CONFIG_ESP_CONSOLE_USB_CDC
  79. #if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG || CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
  80. //Timeout; if there's no host listening, the txfifo won't ever
  81. //be writable after the first packet.
  82. #define USBSERIAL_TIMEOUT_MAX_US 50000
  83. static int s_usbserial_timeout = 0;
  84. static void panic_print_char_usb_serial_jtag(const char c)
  85. {
  86. while (!usb_serial_jtag_ll_txfifo_writable() && s_usbserial_timeout < (USBSERIAL_TIMEOUT_MAX_US / 100)) {
  87. esp_rom_delay_us(100);
  88. s_usbserial_timeout++;
  89. }
  90. if (usb_serial_jtag_ll_txfifo_writable()) {
  91. usb_serial_jtag_ll_write_txfifo((const uint8_t *)&c, 1);
  92. s_usbserial_timeout = 0;
  93. }
  94. }
  95. #endif //CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG || CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
  96. void panic_print_char(const char c)
  97. {
  98. #if CONFIG_ESP_CONSOLE_UART
  99. panic_print_char_uart(c);
  100. #endif
  101. #if CONFIG_ESP_CONSOLE_USB_CDC
  102. panic_print_char_usb_cdc(c);
  103. #endif
  104. #if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG || CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
  105. panic_print_char_usb_serial_jtag(c);
  106. #endif
  107. }
  108. void panic_print_str(const char *str)
  109. {
  110. for (int i = 0; str[i] != 0; i++) {
  111. panic_print_char(str[i]);
  112. }
  113. }
  114. void panic_print_hex(int h)
  115. {
  116. int x;
  117. int c;
  118. // Does not print '0x', only the digits (8 digits to print)
  119. for (x = 0; x < 8; x++) {
  120. c = (h >> 28) & 0xf; // extract the leftmost byte
  121. if (c < 10) {
  122. panic_print_char('0' + c);
  123. } else {
  124. panic_print_char('a' + c - 10);
  125. }
  126. h <<= 4; // move the 2nd leftmost byte to the left, to be extracted next
  127. }
  128. }
  129. void panic_print_dec(int d)
  130. {
  131. // can print at most 2 digits!
  132. int n1, n2;
  133. n1 = d % 10; // extract ones digit
  134. n2 = d / 10; // extract tens digit
  135. if (n2 == 0) {
  136. panic_print_char(' ');
  137. } else {
  138. panic_print_char(n2 + '0');
  139. }
  140. panic_print_char(n1 + '0');
  141. }
  142. #endif // CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  143. /*
  144. If watchdogs are enabled, the panic handler runs the risk of getting aborted pre-emptively because
  145. an overzealous watchdog decides to reset it. On the other hand, if we disable all watchdogs, we run
  146. the risk of somehow halting in the panic handler and not resetting. That is why this routine kills
  147. all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after
  148. one second.
  149. We have to do this before we do anything that might cause issues in the WDT interrupt handlers,
  150. for example stalling the other core on ESP32 may cause the ESP32_ECO3_CACHE_LOCK_FIX
  151. handler to get stuck.
  152. */
  153. void esp_panic_handler_reconfigure_wdts(uint32_t timeout_ms)
  154. {
  155. wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
  156. #if SOC_TIMER_GROUPS >= 2
  157. // IDF-3825
  158. wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1};
  159. #endif
  160. //Todo: Refactor to use Interrupt or Task Watchdog API, and a system level WDT context
  161. //Reconfigure TWDT (Timer Group 0)
  162. wdt_hal_init(&wdt0_context, WDT_MWDT0, MWDT_LL_DEFAULT_CLK_PRESCALER, false); //Prescaler: wdt counts in ticks of TG0_WDT_TICK_US
  163. wdt_hal_write_protect_disable(&wdt0_context);
  164. wdt_hal_config_stage(&wdt0_context, 0, timeout_ms * 1000 / MWDT_DEFAULT_TICKS_PER_US, WDT_STAGE_ACTION_RESET_SYSTEM); //1 second before reset
  165. wdt_hal_enable(&wdt0_context);
  166. wdt_hal_write_protect_enable(&wdt0_context);
  167. #if SOC_TIMER_GROUPS >= 2
  168. //Disable IWDT (Timer Group 1)
  169. wdt_hal_write_protect_disable(&wdt1_context);
  170. wdt_hal_disable(&wdt1_context);
  171. wdt_hal_write_protect_enable(&wdt1_context);
  172. #endif
  173. }
  174. /*
  175. This disables all the watchdogs for when we call the gdbstub.
  176. */
  177. static inline void disable_all_wdts(void)
  178. {
  179. wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
  180. #if SOC_TIMER_GROUPS >= 2
  181. wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1};
  182. #endif
  183. //Todo: Refactor to use Interrupt or Task Watchdog API, and a system level WDT context
  184. //Task WDT is the Main Watchdog Timer of Timer Group 0
  185. wdt_hal_write_protect_disable(&wdt0_context);
  186. wdt_hal_disable(&wdt0_context);
  187. wdt_hal_write_protect_enable(&wdt0_context);
  188. #if SOC_TIMER_GROUPS >= 2
  189. //Interupt WDT is the Main Watchdog Timer of Timer Group 1
  190. wdt_hal_write_protect_disable(&wdt1_context);
  191. wdt_hal_disable(&wdt1_context);
  192. wdt_hal_write_protect_enable(&wdt1_context);
  193. #endif
  194. }
  195. static void print_abort_details(const void *f)
  196. {
  197. panic_print_str(g_panic_abort_details);
  198. }
  199. // Control arrives from chip-specific panic handler, environment prepared for
  200. // the 'main' logic of panic handling. This means that chip-specific stuff have
  201. // already been done, and panic_info_t has been filled.
  202. void esp_panic_handler(panic_info_t *info)
  203. {
  204. // The port-level panic handler has already called this, but call it again
  205. // to reset the TG0WDT period
  206. esp_panic_handler_reconfigure_wdts(1000);
  207. // If the exception was due to an abort, override some of the panic info
  208. if (g_panic_abort) {
  209. info->description = NULL;
  210. info->details = g_panic_abort_details ? print_abort_details : NULL;
  211. info->reason = NULL;
  212. info->exception = PANIC_EXCEPTION_ABORT;
  213. }
  214. /*
  215. * For any supported chip, the panic handler prints the contents of panic_info_t in the following format:
  216. *
  217. *
  218. * Guru Meditation Error: Core <core> (<exception>). <description>
  219. * <details>
  220. *
  221. * <state>
  222. *
  223. * <elf_info>
  224. *
  225. *
  226. * ----------------------------------------------------------------------------------------
  227. * core - core where exception was triggered
  228. * exception - what kind of exception occurred
  229. * description - a short description regarding the exception that occurred
  230. * details - more details about the exception
  231. * state - processor state like register contents, and backtrace
  232. * elf_info - details about the image currently running
  233. *
  234. * NULL fields in panic_info_t are not printed.
  235. *
  236. * */
  237. if (info->reason) {
  238. panic_print_str("Guru Meditation Error: Core ");
  239. panic_print_dec(info->core);
  240. panic_print_str(" panic'ed (");
  241. panic_print_str(info->reason);
  242. panic_print_str("). ");
  243. }
  244. if (info->description) {
  245. panic_print_str(info->description);
  246. }
  247. panic_print_str("\r\n");
  248. PANIC_INFO_DUMP(info, details);
  249. panic_print_str("\r\n");
  250. // If on-chip-debugger is attached, and system is configured to be aware of this,
  251. // then only print up to details. Users should be able to probe for the other information
  252. // in debug mode.
  253. #if CONFIG_ESP_DEBUG_OCDAWARE
  254. if (esp_cpu_dbgr_is_attached()) {
  255. char *panic_reason_str = NULL;
  256. if (info->pseudo_excause) {
  257. panic_reason_str = (char *)info->reason;
  258. } else if (g_panic_abort && strlen(g_panic_abort_details)) {
  259. panic_reason_str = g_panic_abort_details;
  260. }
  261. if (panic_reason_str) {
  262. /* OpenOCD will print the halt cause when target is stopped at the below breakpoint (info->addr) */
  263. long args[] = {(long)panic_reason_str, strlen(panic_reason_str)};
  264. semihosting_call_noerrno(ESP_SEMIHOSTING_SYS_PANIC_REASON, args);
  265. }
  266. panic_print_str("Setting breakpoint at 0x");
  267. panic_print_hex((uint32_t)info->addr);
  268. panic_print_str(" and returning...\r\n");
  269. disable_all_wdts();
  270. #if CONFIG_APPTRACE_ENABLE
  271. #if CONFIG_APPTRACE_SV_ENABLE
  272. SEGGER_RTT_ESP_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  273. #else
  274. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH,
  275. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  276. #endif
  277. #endif
  278. esp_cpu_set_breakpoint(0, info->addr); // use breakpoint 0
  279. return;
  280. }
  281. #endif //CONFIG_ESP_DEBUG_OCDAWARE
  282. // start panic WDT to restart system if we hang in this handler
  283. if (!wdt_hal_is_enabled(&rtc_wdt_ctx)) {
  284. wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
  285. uint32_t stage_timeout_ticks = (uint32_t)(7000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
  286. wdt_hal_write_protect_disable(&rtc_wdt_ctx);
  287. wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_SYSTEM);
  288. // 64KB of core dump data (stacks of about 30 tasks) will produce ~85KB base64 data.
  289. // @ 115200 UART speed it will take more than 6 sec to print them out.
  290. wdt_hal_enable(&rtc_wdt_ctx);
  291. wdt_hal_write_protect_enable(&rtc_wdt_ctx);
  292. }
  293. esp_panic_handler_reconfigure_wdts(1000); // Restart WDT again
  294. PANIC_INFO_DUMP(info, state);
  295. panic_print_str("\r\n");
  296. /* No matter if we come here from abort or an exception, this variable must be reset.
  297. * Else, any exception/error occurring during the current panic handler would considered
  298. * an abort. Do this after PANIC_INFO_DUMP(info, state) as it also checks this variable.
  299. * For example, if coredump triggers a stack overflow and this variable is not reset,
  300. * the second panic would be still be marked as the result of an abort, even the previous
  301. * message reason would be kept. */
  302. g_panic_abort = false;
  303. #ifdef WITH_ELF_SHA256
  304. panic_print_str("\r\nELF file SHA256: ");
  305. panic_print_str(esp_app_get_elf_sha256_str());
  306. panic_print_str("\r\n");
  307. #endif // WITH_ELF_SHA256
  308. panic_print_str("\r\n");
  309. #if CONFIG_APPTRACE_ENABLE
  310. disable_all_wdts();
  311. #if CONFIG_APPTRACE_SV_ENABLE
  312. SEGGER_RTT_ESP_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  313. #else
  314. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH,
  315. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  316. #endif
  317. esp_panic_handler_reconfigure_wdts(1000); // restore WDT config
  318. #endif // CONFIG_APPTRACE_ENABLE
  319. #if CONFIG_ESP_COREDUMP_ENABLE
  320. static bool s_dumping_core;
  321. if (s_dumping_core) {
  322. panic_print_str("Re-entered core dump! Exception happened during core dump!\r\n");
  323. } else {
  324. disable_all_wdts();
  325. s_dumping_core = true;
  326. #if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
  327. esp_core_dump_to_flash(info);
  328. #endif
  329. #if CONFIG_ESP_COREDUMP_ENABLE_TO_UART && !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  330. esp_core_dump_to_uart(info);
  331. #endif
  332. s_dumping_core = false;
  333. esp_panic_handler_reconfigure_wdts(1000);
  334. }
  335. #endif /* CONFIG_ESP_COREDUMP_ENABLE */
  336. #if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB
  337. disable_all_wdts();
  338. wdt_hal_write_protect_disable(&rtc_wdt_ctx);
  339. wdt_hal_disable(&rtc_wdt_ctx);
  340. wdt_hal_write_protect_enable(&rtc_wdt_ctx);
  341. panic_print_str("Entering gdb stub now.\r\n");
  342. esp_gdbstub_panic_handler((void *)info->frame);
  343. #else
  344. #if CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS
  345. // start RTC WDT if it hasn't been started yet and set the timeout to more than the delay time
  346. wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
  347. uint32_t stage_timeout_ticks = (uint32_t)(((CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS + 1) * 1000
  348. * rtc_clk_slow_freq_get_hz()) / 1000ULL);
  349. wdt_hal_write_protect_disable(&rtc_wdt_ctx);
  350. wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_SYSTEM);
  351. // 64KB of core dump data (stacks of about 30 tasks) will produce ~85KB base64 data.
  352. // @ 115200 UART speed it will take more than 6 sec to print them out.
  353. wdt_hal_enable(&rtc_wdt_ctx);
  354. wdt_hal_write_protect_enable(&rtc_wdt_ctx);
  355. esp_panic_handler_reconfigure_wdts((CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS + 1) * 1000);
  356. panic_print_str("Rebooting in ");
  357. panic_print_dec(CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS);
  358. panic_print_str(" seconds...\r\n");
  359. esp_rom_delay_us(CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS * 1000000);
  360. esp_panic_handler_reconfigure_wdts(1000);
  361. #endif /* CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS */
  362. wdt_hal_write_protect_disable(&rtc_wdt_ctx);
  363. wdt_hal_disable(&rtc_wdt_ctx);
  364. wdt_hal_write_protect_enable(&rtc_wdt_ctx);
  365. #if CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT || CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  366. if (esp_reset_reason_get_hint() == ESP_RST_UNKNOWN) {
  367. switch (info->exception) {
  368. case PANIC_EXCEPTION_IWDT:
  369. esp_reset_reason_set_hint(ESP_RST_INT_WDT);
  370. break;
  371. case PANIC_EXCEPTION_TWDT:
  372. esp_reset_reason_set_hint(ESP_RST_TASK_WDT);
  373. break;
  374. case PANIC_EXCEPTION_ABORT:
  375. case PANIC_EXCEPTION_FAULT:
  376. default:
  377. esp_reset_reason_set_hint(ESP_RST_PANIC);
  378. break; // do not touch the previously set reset reason hint
  379. }
  380. }
  381. panic_print_str("Rebooting...\r\n");
  382. panic_restart();
  383. #else /* CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT || CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT */
  384. disable_all_wdts();
  385. panic_print_str("CPU halted.\r\n");
  386. esp_system_reset_modules_on_exit();
  387. while (1);
  388. #endif /* CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT || CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT */
  389. #endif /* CONFIG_ESP_SYSTEM_PANIC_GDBSTUB */
  390. }
  391. void IRAM_ATTR __attribute__((noreturn, no_sanitize_undefined)) panic_abort(const char *details)
  392. {
  393. g_panic_abort = true;
  394. g_panic_abort_details = (char *) details;
  395. #if CONFIG_APPTRACE_ENABLE
  396. #if CONFIG_APPTRACE_SV_ENABLE
  397. SEGGER_RTT_ESP_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  398. #else
  399. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH,
  400. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  401. #endif
  402. #endif
  403. *((volatile int *) 0) = 0; // NOLINT(clang-analyzer-core.NullDereference) should be an invalid operation on targets
  404. while (1);
  405. }
  406. /* Weak versions of reset reason hint functions.
  407. * If these weren't provided, reset reason code would be linked into the app
  408. * even if the app never called esp_reset_reason().
  409. */
  410. void IRAM_ATTR __attribute__((weak)) esp_reset_reason_set_hint(esp_reset_reason_t hint)
  411. {
  412. }
  413. esp_reset_reason_t IRAM_ATTR __attribute__((weak)) esp_reset_reason_get_hint(void)
  414. {
  415. return ESP_RST_UNKNOWN;
  416. }