panic.c 14 KB

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