panic.c 13 KB

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