flipperzero-firmware_official 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. commit 984d89c6d072a9c4c1955299b46f793ddf69cdd4
  2. Author: あく <alleteam@gmail.com>
  3. Date: Mon Oct 24 19:50:34 2022 +0900
  4. Furi: smaller crash routine (#1912)
  5. * Furi: smaller crash routine
  6. * Furi: small fixes
  7. * Furi: cleanup check routines, more assembly code, force inline of __furi_halt_mcu
  8. * SubGhz: cleanup residual line mess
  9. * Documentation
  10. * Dap-link: fix help
  11. * Furi: replace __furi_halt_mcu with HALT_MCU macros
  12. * Furi: disable IRQ earlier in crash handler
  13. * Furi: properly handle masked mode when detecting ISR
  14. * Ble: allow 0 length feed in rpc_session_feed
  15. * Format sources
  16. * Furi: better crash logic explanation.
  17. * Furi: some grammar in check.h
  18. Co-authored-by: SG <who.just.the.doctor@gmail.com>
  19. diff --git a/applications/plugins/dap_link/gui/scenes/dap_scene_help.c b/applications/plugins/dap_link/gui/scenes/dap_scene_help.c
  20. index 7193f4f4b..d8d70e7ff 100644
  21. --- a/applications/plugins/dap_link/gui/scenes/dap_scene_help.c
  22. +++ b/applications/plugins/dap_link/gui/scenes/dap_scene_help.c
  23. @@ -72,13 +72,13 @@ void dap_scene_help_on_enter(void* context) {
  24. if(config->uart_swap == DapUartTXRXNormal) {
  25. furi_string_cat(
  26. string,
  27. - " TX: 15 [С1]\r\n"
  28. - " RX: 16 [С0]\r\n");
  29. + " TX: 15 [C1]\r\n"
  30. + " RX: 16 [C0]\r\n");
  31. } else {
  32. furi_string_cat(
  33. string,
  34. - " RX: 15 [С1]\r\n"
  35. - " TX: 16 [С0]\r\n");
  36. + " RX: 15 [C1]\r\n"
  37. + " TX: 16 [C0]\r\n");
  38. }
  39. break;
  40. default:
  41. diff --git a/applications/services/rpc/rpc.c b/applications/services/rpc/rpc.c
  42. index 06c05173c..73eaadfb1 100644
  43. --- a/applications/services/rpc/rpc.c
  44. +++ b/applications/services/rpc/rpc.c
  45. @@ -148,7 +148,8 @@ size_t
  46. rpc_session_feed(RpcSession* session, uint8_t* encoded_bytes, size_t size, TickType_t timeout) {
  47. furi_assert(session);
  48. furi_assert(encoded_bytes);
  49. - furi_assert(size > 0);
  50. +
  51. + if(!size) return 0;
  52. size_t bytes_sent = furi_stream_buffer_send(session->stream, encoded_bytes, size, timeout);
  53. diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv
  54. index 188cd7484..4c48d9abd 100644
  55. --- a/firmware/targets/f7/api_symbols.csv
  56. +++ b/firmware/targets/f7/api_symbols.csv
  57. @@ -1,5 +1,5 @@
  58. entry,status,name,type,params
  59. -Version,+,4.0,,
  60. +Version,+,5.0,,
  61. Header,+,applications/services/bt/bt_service/bt.h,,
  62. Header,+,applications/services/cli/cli.h,,
  63. Header,+,applications/services/cli/cli_vcp.h,,
  64. @@ -2843,7 +2843,6 @@ Variable,+,I_update_10px,const Icon,
  65. Variable,-,MSIRangeTable,const uint32_t[16],
  66. Variable,-,SmpsPrescalerTable,const uint32_t[4][6],
  67. Variable,+,SystemCoreClock,uint32_t,
  68. -Variable,+,__furi_check_message,const char*,
  69. Variable,+,_ctype_,const char[],
  70. Variable,+,_global_impure_ptr,_reent*,
  71. Variable,+,_impure_ptr,_reent*,
  72. diff --git a/furi/core/check.c b/furi/core/check.c
  73. index ed38038a5..00c20575a 100644
  74. --- a/furi/core/check.c
  75. +++ b/furi/core/check.c
  76. @@ -14,6 +14,28 @@
  77. PLACE_IN_SECTION("MB_MEM2") const char* __furi_check_message = NULL;
  78. PLACE_IN_SECTION("MB_MEM2") uint32_t __furi_check_registers[12] = {0};
  79. +/** Load r12 value to __furi_check_message and store registers to __furi_check_registers */
  80. +#define GET_MESSAGE_AND_STORE_REGISTERS() \
  81. + asm volatile("ldr r11, =__furi_check_message \n" \
  82. + "str r12, [r11] \n" \
  83. + "ldr r12, =__furi_check_registers \n" \
  84. + "stm r12, {r0-r11} \n" \
  85. + : \
  86. + : \
  87. + : "memory");
  88. +
  89. +// Restore registers and halt MCU
  90. +#define RESTORE_REGISTERS_AND_HALT_MCU() \
  91. + asm volatile("ldr r12, =__furi_check_registers \n" \
  92. + "ldm r12, {r0-r11} \n" \
  93. + "loop%=: \n" \
  94. + "bkpt 0x00 \n" \
  95. + "wfi \n" \
  96. + "b loop%= \n" \
  97. + : \
  98. + : \
  99. + : "memory");
  100. +
  101. extern size_t xPortGetTotalHeapSize(void);
  102. extern size_t xPortGetFreeHeapSize(void);
  103. extern size_t xPortGetMinimumEverFreeHeapSize(void);
  104. @@ -55,32 +77,11 @@ static void __furi_print_name(bool isr) {
  105. }
  106. }
  107. -static FURI_NORETURN void __furi_halt_mcu() {
  108. - register const void* r12 asm ("r12") = (void*)__furi_check_registers;
  109. - asm volatile(
  110. - "ldm r12, {r0-r11} \n"
  111. -#ifdef FURI_DEBUG
  112. - "bkpt 0x00 \n"
  113. -#endif
  114. - "loop%=: \n"
  115. - "wfi \n"
  116. - "b loop%= \n"
  117. - :
  118. - : "r" (r12)
  119. - : "memory");
  120. - __builtin_unreachable();
  121. -}
  122. -
  123. FURI_NORETURN void __furi_crash() {
  124. - register const void* r12 asm ("r12") = (void*)__furi_check_registers;
  125. - asm volatile(
  126. - "stm r12, {r0-r11} \n"
  127. - :
  128. - : "r" (r12)
  129. - : "memory");
  130. -
  131. - bool isr = FURI_IS_ISR();
  132. __disable_irq();
  133. + GET_MESSAGE_AND_STORE_REGISTERS();
  134. +
  135. + bool isr = FURI_IS_IRQ_MODE();
  136. if(__furi_check_message == NULL) {
  137. __furi_check_message = "Fatal Error";
  138. @@ -98,7 +99,7 @@ FURI_NORETURN void __furi_crash() {
  139. #ifdef FURI_DEBUG
  140. furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n");
  141. furi_hal_console_puts("\033[0m\r\n");
  142. - __furi_halt_mcu();
  143. + RESTORE_REGISTERS_AND_HALT_MCU();
  144. #else
  145. furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message);
  146. furi_hal_console_puts("\r\nRebooting system.\r\n");
  147. @@ -109,15 +110,10 @@ FURI_NORETURN void __furi_crash() {
  148. }
  149. FURI_NORETURN void __furi_halt() {
  150. - register const void* r12 asm ("r12") = (void*)__furi_check_registers;
  151. - asm volatile(
  152. - "stm r12, {r0-r11} \n"
  153. - :
  154. - : "r" (r12)
  155. - : "memory");
  156. -
  157. - bool isr = FURI_IS_ISR();
  158. __disable_irq();
  159. + GET_MESSAGE_AND_STORE_REGISTERS();
  160. +
  161. + bool isr = FURI_IS_IRQ_MODE();
  162. if(__furi_check_message == NULL) {
  163. __furi_check_message = "System halt requested.";
  164. @@ -128,5 +124,6 @@ FURI_NORETURN void __furi_halt() {
  165. furi_hal_console_puts(__furi_check_message);
  166. furi_hal_console_puts("\r\nSystem halted. Bye-bye!\r\n");
  167. furi_hal_console_puts("\033[0m\r\n");
  168. - __furi_halt_mcu();
  169. + RESTORE_REGISTERS_AND_HALT_MCU();
  170. + __builtin_unreachable();
  171. }
  172. diff --git a/furi/core/check.h b/furi/core/check.h
  173. index e77891f70..78efc1451 100644
  174. --- a/furi/core/check.h
  175. +++ b/furi/core/check.h
  176. @@ -1,3 +1,16 @@
  177. +/**
  178. + * @file check.h
  179. + *
  180. + * Furi crash and assert functions.
  181. + *
  182. + * The main problem with crashing is that you can't do anything without disturbing registers,
  183. + * and if you disturb registers, you won't be able to see the correct register values in the debugger.
  184. + *
  185. + * Current solution works around it by passing the message through r12 and doing some magic with registers in crash function.
  186. + * r0-r10 are stored in the ram2 on crash routine start and restored at the end.
  187. + * The only register that is going to be lost is r11.
  188. + *
  189. + */
  190. #pragma once
  191. #ifdef __cplusplus
  192. @@ -8,9 +21,6 @@ extern "C" {
  193. #define FURI_NORETURN noreturn
  194. #endif
  195. -/** Pointer to pass message to __furi_crash and __furi_halt */
  196. -extern const char* __furi_check_message;
  197. -
  198. /** Crash system */
  199. FURI_NORETURN void __furi_crash();
  200. @@ -18,39 +28,41 @@ FURI_NORETURN void __furi_crash();
  201. FURI_NORETURN void __furi_halt();
  202. /** Crash system with message. Show message after reboot. */
  203. -#define furi_crash(message) \
  204. - do { \
  205. - __furi_check_message = message; \
  206. - __furi_crash(); \
  207. +#define furi_crash(message) \
  208. + do { \
  209. + register const void* r12 asm("r12") = (void*)message; \
  210. + asm volatile("sukima%=:" : : "r"(r12)); \
  211. + __furi_crash(); \
  212. } while(0)
  213. /** Halt system with message. */
  214. -#define furi_halt(message) \
  215. - do { \
  216. - __furi_check_message = message; \
  217. - __furi_halt(); \
  218. +#define furi_halt(message) \
  219. + do { \
  220. + register const void* r12 asm("r12") = (void*)message; \
  221. + asm volatile("sukima%=:" : : "r"(r12)); \
  222. + __furi_halt(); \
  223. } while(0)
  224. /** Check condition and crash if check failed */
  225. -#define furi_check(__e) \
  226. - do { \
  227. - if ((__e) == 0) { \
  228. - furi_crash("furi_check failed\r\n"); \
  229. - } \
  230. +#define furi_check(__e) \
  231. + do { \
  232. + if((__e) == 0) { \
  233. + furi_crash("furi_check failed\r\n"); \
  234. + } \
  235. } while(0)
  236. /** Only in debug build: Assert condition and crash if assert failed */
  237. #ifdef FURI_DEBUG
  238. -#define furi_assert(__e) \
  239. - do { \
  240. - if ((__e) == 0) { \
  241. - furi_crash("furi_assert failed\r\n"); \
  242. - } \
  243. +#define furi_assert(__e) \
  244. + do { \
  245. + if((__e) == 0) { \
  246. + furi_crash("furi_assert failed\r\n"); \
  247. + } \
  248. } while(0)
  249. #else
  250. -#define furi_assert(__e) \
  251. - do { \
  252. - ((void)(__e)); \
  253. +#define furi_assert(__e) \
  254. + do { \
  255. + ((void)(__e)); \
  256. } while(0)
  257. #endif