check.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "check.h"
  2. #include "common_defines.h"
  3. #include <furi_hal_console.h>
  4. #include <furi_hal_power.h>
  5. #include <furi_hal_rtc.h>
  6. #include <stdio.h>
  7. #include <FreeRTOS.h>
  8. #include <task.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. PLACE_IN_SECTION("MB_MEM2") const char* __furi_check_message = NULL;
  12. PLACE_IN_SECTION("MB_MEM2") uint32_t __furi_check_registers[12] = {0};
  13. extern size_t xPortGetTotalHeapSize(void);
  14. extern size_t xPortGetFreeHeapSize(void);
  15. extern size_t xPortGetMinimumEverFreeHeapSize(void);
  16. static void __furi_put_uint32_as_text(uint32_t data) {
  17. char tmp_str[] = "-2147483648";
  18. itoa(data, tmp_str, 10);
  19. furi_hal_console_puts(tmp_str);
  20. }
  21. static void __furi_print_stack_info() {
  22. furi_hal_console_puts("\r\n\tstack watermark: ");
  23. __furi_put_uint32_as_text(uxTaskGetStackHighWaterMark(NULL) * 4);
  24. }
  25. static void __furi_print_heap_info() {
  26. furi_hal_console_puts("\r\n\t heap total: ");
  27. __furi_put_uint32_as_text(xPortGetTotalHeapSize());
  28. furi_hal_console_puts("\r\n\t heap free: ");
  29. __furi_put_uint32_as_text(xPortGetFreeHeapSize());
  30. furi_hal_console_puts("\r\n\t heap watermark: ");
  31. __furi_put_uint32_as_text(xPortGetMinimumEverFreeHeapSize());
  32. }
  33. static void __furi_print_name(bool isr) {
  34. if(isr) {
  35. furi_hal_console_puts("[ISR ");
  36. __furi_put_uint32_as_text(__get_IPSR());
  37. furi_hal_console_puts("] ");
  38. } else {
  39. const char* name = pcTaskGetName(NULL);
  40. if(name == NULL) {
  41. furi_hal_console_puts("[main] ");
  42. } else {
  43. furi_hal_console_puts("[");
  44. furi_hal_console_puts(name);
  45. furi_hal_console_puts("] ");
  46. }
  47. }
  48. }
  49. static FURI_NORETURN void __furi_halt_mcu() {
  50. register const void* r12 asm ("r12") = (void*)__furi_check_registers;
  51. asm volatile(
  52. "ldm r12, {r0-r11} \n"
  53. #ifdef FURI_DEBUG
  54. "bkpt 0x00 \n"
  55. #endif
  56. "loop%=: \n"
  57. "wfi \n"
  58. "b loop%= \n"
  59. :
  60. : "r" (r12)
  61. : "memory");
  62. __builtin_unreachable();
  63. }
  64. FURI_NORETURN void __furi_crash() {
  65. register const void* r12 asm ("r12") = (void*)__furi_check_registers;
  66. asm volatile(
  67. "stm r12, {r0-r11} \n"
  68. :
  69. : "r" (r12)
  70. : "memory");
  71. bool isr = FURI_IS_ISR();
  72. __disable_irq();
  73. if(__furi_check_message == NULL) {
  74. __furi_check_message = "Fatal Error";
  75. }
  76. furi_hal_console_puts("\r\n\033[0;31m[CRASH]");
  77. __furi_print_name(isr);
  78. furi_hal_console_puts(__furi_check_message);
  79. if(!isr) {
  80. __furi_print_stack_info();
  81. }
  82. __furi_print_heap_info();
  83. #ifdef FURI_DEBUG
  84. furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n");
  85. furi_hal_console_puts("\033[0m\r\n");
  86. __furi_halt_mcu();
  87. #else
  88. furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message);
  89. furi_hal_console_puts("\r\nRebooting system.\r\n");
  90. furi_hal_console_puts("\033[0m\r\n");
  91. furi_hal_power_reset();
  92. #endif
  93. __builtin_unreachable();
  94. }
  95. FURI_NORETURN void __furi_halt() {
  96. register const void* r12 asm ("r12") = (void*)__furi_check_registers;
  97. asm volatile(
  98. "stm r12, {r0-r11} \n"
  99. :
  100. : "r" (r12)
  101. : "memory");
  102. bool isr = FURI_IS_ISR();
  103. __disable_irq();
  104. if(__furi_check_message == NULL) {
  105. __furi_check_message = "System halt requested.";
  106. }
  107. furi_hal_console_puts("\r\n\033[0;31m[HALT]");
  108. __furi_print_name(isr);
  109. furi_hal_console_puts(__furi_check_message);
  110. furi_hal_console_puts("\r\nSystem halted. Bye-bye!\r\n");
  111. furi_hal_console_puts("\033[0m\r\n");
  112. __furi_halt_mcu();
  113. }