panic.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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 "esp_err.h"
  15. #include "esp_attr.h"
  16. #include "esp_spi_flash.h"
  17. #include "esp_private/system_internal.h"
  18. #include "esp_private/gdbstub.h"
  19. #include "esp_ota_ops.h"
  20. #if CONFIG_APPTRACE_ENABLE
  21. #include "esp_app_trace.h"
  22. #if CONFIG_SYSVIEW_ENABLE
  23. #include "SEGGER_RTT.h"
  24. #endif
  25. #endif // CONFIG_APPTRACE_ENABLE
  26. #include "esp_core_dump.h"
  27. #include "soc/rtc_wdt.h"
  28. #include "soc/cpu.h"
  29. #include "hal/timer_hal.h"
  30. #include "hal/cpu_hal.h"
  31. #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  32. #include <string.h>
  33. #include "hal/uart_hal.h"
  34. #endif
  35. #include "panic_internal.h"
  36. #include "sdkconfig.h"
  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. static bool s_abort = false;
  43. static char *s_abort_details = NULL;
  44. #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  45. static uart_hal_context_t s_panic_uart = { .dev = CONFIG_ESP_CONSOLE_UART_NUM == 0 ? &UART0 : &UART1 };
  46. void panic_print_char(const char c)
  47. {
  48. uint32_t sz = 0;
  49. while(!uart_hal_get_txfifo_len(&s_panic_uart));
  50. uart_hal_write_txfifo(&s_panic_uart, (uint8_t*) &c, 1, &sz);
  51. }
  52. void panic_print_str(const char *str)
  53. {
  54. for(int i = 0; str[i] != 0; i++) {
  55. panic_print_char(str[i]);
  56. }
  57. }
  58. void panic_print_hex(int h)
  59. {
  60. int x;
  61. int c;
  62. // Does not print '0x', only the digits (8 digits to print)
  63. for (x = 0; x < 8; x++) {
  64. c = (h >> 28) & 0xf; // extract the leftmost byte
  65. if (c < 10) {
  66. panic_print_char('0' + c);
  67. } else {
  68. panic_print_char('a' + c - 10);
  69. }
  70. h <<= 4; // move the 2nd leftmost byte to the left, to be extracted next
  71. }
  72. }
  73. void panic_print_dec(int d)
  74. {
  75. // can print at most 2 digits!
  76. int n1, n2;
  77. n1 = d % 10; // extract ones digit
  78. n2 = d / 10; // extract tens digit
  79. if (n2 == 0) {
  80. panic_print_char(' ');
  81. } else {
  82. panic_print_char(n2 + '0');
  83. }
  84. panic_print_char(n1 + '0');
  85. }
  86. #endif // CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  87. /*
  88. If watchdogs are enabled, the panic handler runs the risk of getting aborted pre-emptively because
  89. an overzealous watchdog decides to reset it. On the other hand, if we disable all watchdogs, we run
  90. the risk of somehow halting in the panic handler and not resetting. That is why this routine kills
  91. all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after
  92. one second.
  93. */
  94. static void reconfigure_all_wdts(void)
  95. {
  96. timer_ll_wdt_set_protect(&TIMERG0, false);
  97. timer_ll_wdt_feed(&TIMERG0);
  98. timer_ll_wdt_init(&TIMERG0);
  99. timer_ll_wdt_set_tick(&TIMERG0, TG0_WDT_TICK_US); //Prescaler: wdt counts in ticks of TG0_WDT_TICK_US
  100. //1st stage timeout: reset system
  101. timer_ll_wdt_set_timeout_behavior(&TIMERG0, 0, TIMER_WDT_RESET_SYSTEM);
  102. //1 second before reset
  103. timer_ll_wdt_set_timeout(&TIMERG0, 0, 1000*1000/TG0_WDT_TICK_US);
  104. timer_ll_wdt_set_enable(&TIMERG0, true);
  105. timer_ll_wdt_set_protect(&TIMERG0, true);
  106. //Disable wdt 1
  107. timer_ll_wdt_set_protect(&TIMERG1, false);
  108. timer_ll_wdt_set_enable(&TIMERG1, false);
  109. timer_ll_wdt_set_protect(&TIMERG1, true);
  110. }
  111. /*
  112. This disables all the watchdogs for when we call the gdbstub.
  113. */
  114. static inline void disable_all_wdts(void)
  115. {
  116. timer_ll_wdt_set_protect(&TIMERG0, false);
  117. timer_ll_wdt_set_enable(&TIMERG0, false);
  118. timer_ll_wdt_set_protect(&TIMERG0, true);
  119. timer_ll_wdt_set_protect(&TIMERG1, false);
  120. timer_ll_wdt_set_enable(&TIMERG1, false);
  121. timer_ll_wdt_set_protect(&TIMERG1, true);
  122. }
  123. static void print_abort_details(const void *f)
  124. {
  125. panic_print_str(s_abort_details);
  126. }
  127. // Control arrives from chip-specific panic handler, environment prepared for
  128. // the 'main' logic of panic handling. This means that chip-specific stuff have
  129. // already been done, and panic_info_t has been filled.
  130. void esp_panic_handler(panic_info_t *info)
  131. {
  132. // If the exception was due to an abort, override some of the panic info
  133. if (s_abort) {
  134. info->description = NULL;
  135. info->details = s_abort_details ? print_abort_details : NULL;
  136. info->state = NULL; // do not display state, since it is not a 'real' crash
  137. info->reason = "SoftwareAbort";
  138. info->exception = PANIC_EXCEPTION_ABORT;
  139. }
  140. /*
  141. * For any supported chip, the panic handler prints the contents of panic_info_t in the following format:
  142. *
  143. *
  144. * Guru Meditation Error: Core <core> (<exception>). <description>
  145. * <details>
  146. *
  147. * <state>
  148. *
  149. * <elf_info>
  150. *
  151. *
  152. * ----------------------------------------------------------------------------------------
  153. * core - core where exception was triggered
  154. * exception - what kind of exception occured
  155. * description - a short description regarding the exception that occured
  156. * details - more details about the exception
  157. * state - processor state like register contents, and backtrace
  158. * elf_info - details about the image currently running
  159. *
  160. * NULL fields in panic_info_t are not printed.
  161. *
  162. * */
  163. panic_print_str("Guru Meditation Error: Core ");
  164. panic_print_dec(info->core);
  165. panic_print_str(" panic'ed (");
  166. panic_print_str(info->reason);
  167. panic_print_str("). ");
  168. if (info->description) {
  169. panic_print_str(info->description);
  170. }
  171. panic_print_str("\r\n");
  172. PANIC_INFO_DUMP(info, details);
  173. panic_print_str("\r\n");
  174. // If on-chip-debugger is attached, and system is configured to be aware of this,
  175. // then only print up to details. Users should be able to probe for the other information
  176. // in debug mode.
  177. if (esp_cpu_in_ocd_debug_mode()) {
  178. panic_print_str("Setting breakpoint at 0x");
  179. panic_print_hex((uint32_t)info->addr);
  180. panic_print_str(" and returning...\r\n");
  181. disable_all_wdts();
  182. #if CONFIG_APPTRACE_ENABLE
  183. #if CONFIG_SYSVIEW_ENABLE
  184. SEGGER_RTT_ESP32_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  185. #else
  186. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH,
  187. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  188. #endif
  189. #endif
  190. cpu_hal_set_breakpoint(0, info->addr); // use breakpoint 0
  191. return;
  192. }
  193. // start panic WDT to restart system if we hang in this handler
  194. if (!rtc_wdt_is_on()) {
  195. rtc_wdt_protect_off();
  196. rtc_wdt_disable();
  197. rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us);
  198. rtc_wdt_set_length_of_reset_signal(RTC_WDT_CPU_RESET_SIG, RTC_WDT_LENGTH_3_2us);
  199. rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_SYSTEM);
  200. // 64KB of core dump data (stacks of about 30 tasks) will produce ~85KB base64 data.
  201. // @ 115200 UART speed it will take more than 6 sec to print them out.
  202. rtc_wdt_set_time(RTC_WDT_STAGE0, 7000);
  203. rtc_wdt_enable();
  204. rtc_wdt_protect_on();
  205. }
  206. //Feed the watchdogs, so they will give us time to print out debug info
  207. reconfigure_all_wdts();
  208. PANIC_INFO_DUMP(info, state);
  209. panic_print_str("\r\n");
  210. panic_print_str("\r\nELF file SHA256: ");
  211. char sha256_buf[65];
  212. esp_ota_get_app_elf_sha256(sha256_buf, sizeof(sha256_buf));
  213. panic_print_str(sha256_buf);
  214. panic_print_str("\r\n");
  215. panic_print_str("\r\n");
  216. #if CONFIG_APPTRACE_ENABLE
  217. disable_all_wdts();
  218. #if CONFIG_SYSVIEW_ENABLE
  219. SEGGER_RTT_ESP32_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  220. #else
  221. esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH,
  222. APPTRACE_ONPANIC_HOST_FLUSH_TMO);
  223. #endif
  224. reconfigure_all_wdts();
  225. #endif
  226. #if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB
  227. disable_all_wdts();
  228. rtc_wdt_disable();
  229. panic_print_str("Entering gdb stub now.\r\n");
  230. esp_gdbstub_panic_handler((XtExcFrame*) info->frame);
  231. #else
  232. #if CONFIG_ESP32_ENABLE_COREDUMP
  233. static bool s_dumping_core;
  234. if (s_dumping_core) {
  235. panic_print_str("Re-entered core dump! Exception happened during core dump!\r\n");
  236. } else {
  237. disable_all_wdts();
  238. s_dumping_core = true;
  239. #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
  240. esp_core_dump_to_flash((XtExcFrame*) info->frame);
  241. #endif
  242. #if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART && !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  243. esp_core_dump_to_uart((XtExcFrame*) info->frame);
  244. #endif
  245. s_dumping_core = false;
  246. reconfigure_all_wdts();
  247. }
  248. #endif /* CONFIG_ESP32_ENABLE_COREDUMP */
  249. rtc_wdt_disable();
  250. #if CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT || CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
  251. if (esp_reset_reason_get_hint() == ESP_RST_UNKNOWN) {
  252. switch (info->exception)
  253. {
  254. case PANIC_EXCEPTION_IWDT:
  255. esp_reset_reason_set_hint(ESP_RST_INT_WDT);
  256. break;
  257. case PANIC_EXCEPTION_TWDT:
  258. esp_reset_reason_set_hint(ESP_RST_TASK_WDT);
  259. break;
  260. case PANIC_EXCEPTION_ABORT:
  261. case PANIC_EXCEPTION_FAULT:
  262. default:
  263. esp_reset_reason_set_hint(ESP_RST_PANIC);
  264. break; // do not touch the previously set reset reason hint
  265. }
  266. }
  267. panic_print_str("Rebooting...\r\n");
  268. esp_restart_noos();
  269. #else
  270. disable_all_wdts();
  271. panic_print_str("CPU halted.\r\n");
  272. while (1);
  273. #endif /* CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT || CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT */
  274. #endif /* CONFIG_ESP_SYSTEM_PANIC_GDBSTUB */
  275. }
  276. void __attribute__((noreturn)) panic_abort(const char *details)
  277. {
  278. s_abort = true;
  279. s_abort_details = (char*) details;
  280. #if CONFIG_APPTRACE_ENABLE
  281. #if CONFIG_SYSVIEW_ENABLE
  282. SEGGER_RTT_ESP32_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. #endif
  288. while (1) {
  289. if (esp_cpu_in_ocd_debug_mode()) {
  290. cpu_hal_break();
  291. }
  292. *((int *) 0) = 0; // should be an invalid operation on targets
  293. }
  294. }