check.h 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /**
  2. * @file check.h
  3. *
  4. * Furi crash and assert functions.
  5. *
  6. * The main problem with crashing is that you can't do anything without disturbing registers,
  7. * and if you disturb registers, you won't be able to see the correct register values in the debugger.
  8. *
  9. * Current solution works around it by passing the message through r12 and doing some magic with registers in crash function.
  10. * r0-r10 are stored in the ram2 on crash routine start and restored at the end.
  11. * The only register that is going to be lost is r11.
  12. *
  13. */
  14. #pragma once
  15. #ifdef __cplusplus
  16. extern "C" {
  17. #define FURI_NORETURN [[noreturn]]
  18. #else
  19. #include <stdnoreturn.h>
  20. #define FURI_NORETURN noreturn
  21. #endif
  22. /** Crash system */
  23. FURI_NORETURN void __furi_crash();
  24. /** Halt system */
  25. FURI_NORETURN void __furi_halt();
  26. /** Crash system with message. Show message after reboot. */
  27. #define furi_crash(message) \
  28. do { \
  29. register const void* r12 asm("r12") = (void*)message; \
  30. asm volatile("sukima%=:" : : "r"(r12)); \
  31. __furi_crash(); \
  32. } while(0)
  33. /** Halt system with message. */
  34. #define furi_halt(message) \
  35. do { \
  36. register const void* r12 asm("r12") = (void*)message; \
  37. asm volatile("sukima%=:" : : "r"(r12)); \
  38. __furi_halt(); \
  39. } while(0)
  40. /** Check condition and crash if check failed */
  41. #define furi_check(__e) \
  42. do { \
  43. if(!(__e)) { \
  44. furi_crash("furi_check failed\r\n"); \
  45. } \
  46. } while(0)
  47. /** Only in debug build: Assert condition and crash if assert failed */
  48. #ifdef FURI_DEBUG
  49. #define furi_assert(__e) \
  50. do { \
  51. if(!(__e)) { \
  52. furi_crash("furi_assert failed\r\n"); \
  53. } \
  54. } while(0)
  55. #else
  56. #define furi_assert(__e) \
  57. do { \
  58. ((void)(__e)); \
  59. } while(0)
  60. #endif
  61. #ifdef __cplusplus
  62. }
  63. #endif