fault-handlers-assertion.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #include "all-headers.h"
  2. #define LED_DELAY 1000
  3. static void configureFaultRegisters (BOOT_MODE) {
  4. // ACTLR register (reset value: 0)
  5. // Bit 1: Disables write buffer use during default memory map accesses. This causes all bus faults to be
  6. // precise, but decreases the performance of the processor because stores to memory must complete before
  7. // the next instruction can be executed.
  8. // Bit 0: Disables interruption of multi-cycle instructions. This increases the interrupt latency of the processor
  9. // because load/store and multiply/divide operations complete before interrupt stacking occurs.
  10. // SCB_ACTLR = (1 << 1) ;
  11. // SHCSR register
  12. // SHCSR |=
  13. // (1 << 16) | // Memory Management Fault exception enable bit, set to 1 to enable; set to 0 to disable
  14. // (1 << 17) | // BusFault exception enable bit, set to 1 to enable; set to 0 to disable
  15. // (1 << 18) ; // UsageFault exception enable bit, set to 1 to enable; set to 0 to disable
  16. // SCB_CCR register
  17. SCB_CCR |=
  18. (1 << 4) | // Enable UsageFault when the processor executes an SDIV or UDIV instruction with a divisor of 0
  19. (1 << 3) ; // Enable UsageFault when a memory access to unaligned addresses are performed
  20. }
  21. MACRO_BOOT_ROUTINE (configureFaultRegisters) ;
  22. static void endlessLoop (FAULT_MODE) {
  23. pinMode (L0_LED, DigitalMode::OUTPUT) ;
  24. pinMode (L1_LED, DigitalMode::OUTPUT) ;
  25. pinMode (L2_LED, DigitalMode::OUTPUT) ;
  26. pinMode (L3_LED, DigitalMode::OUTPUT) ;
  27. pinMode (L4_LED, DigitalMode::OUTPUT) ;
  28. digitalWrite (L0_LED, true) ;
  29. digitalWrite (L1_LED, true) ;
  30. while (1) {
  31. digitalToggle (L0_LED) ;
  32. digitalToggle (L1_LED) ;
  33. digitalToggle (L3_LED) ;
  34. digitalToggle (L4_LED) ;
  35. busyWaitDuring_faultMode (MODE_ LED_DELAY);
  36. }
  37. }
  38. #define MMFSR (* ((volatile uint8_t *) 0xE000ED28))
  39. #define MMFAR (* ((volatile uint32_t *) 0xE000ED34))
  40. #define BFSR (* ((volatile uint8_t *) 0xE000ED29))
  41. #define BFAR (* ((volatile uint32_t *) 0xE000ED38))
  42. #define UFSR (* ((volatile uint16_t *) 0xE000ED2A))
  43. #define AFSR (* ((volatile uint32_t *) 0xE000ED3C))
  44. static void handleFault (FAULT_MODE_ const char * inTitle, const uint32_t inLinkRegisterValue) {
  45. // Init Systick (LCD display requires an 1 ms timer)
  46. configureSystick_faultMode (MODE) ;
  47. pinMode (L0_LED, DigitalMode::OUTPUT) ;
  48. pinMode (L1_LED, DigitalMode::OUTPUT) ;
  49. pinMode (L2_LED, DigitalMode::OUTPUT) ;
  50. pinMode (L3_LED, DigitalMode::OUTPUT) ;
  51. pinMode (L4_LED, DigitalMode::OUTPUT) ;
  52. digitalWrite (L0_LED, true) ;
  53. digitalWrite (L1_LED, true) ;
  54. uint32_t displayedPage = 0 ;
  55. uint32_t displayCounter = 0 ;
  56. bool encoderA = false ;
  57. bool display = true ;
  58. pinMode (ENCODER_A, DigitalMode::INPUT_PULLUP) ;
  59. pinMode (ENCODER_B, DigitalMode::INPUT_PULLUP) ;
  60. while (1) {
  61. // Wait
  62. busyWaitDuring_faultMode (MODE_ 1);
  63. // Handle encoder
  64. const bool currentEncoderA = digitalRead (ENCODER_A) ;
  65. if (encoderA && !currentEncoderA) {
  66. display = true ;
  67. if (digitalRead (ENCODER_B)) {
  68. displayedPage = (displayedPage + 1) % 4 ;
  69. }else{
  70. displayedPage = (displayedPage + 3) % 4 ;
  71. }
  72. }
  73. encoderA = currentEncoderA ;
  74. // Display
  75. if (displayCounter > 0) {
  76. displayCounter -= 1 ;
  77. }else{
  78. displayCounter = LED_DELAY;
  79. digitalToggle (L0_LED) ;
  80. digitalToggle (L1_LED) ;
  81. digitalToggle (L3_LED) ;
  82. digitalToggle (L4_LED) ;
  83. if (display) {
  84. display = false ;
  85. initScreen_faultMode (MODE) ;
  86. printString_faultMode (MODE_ inTitle) ;
  87. gotoLineColumn_faultMode (MODE_ 0, 19) ;
  88. printUnsigned_faultMode (MODE_ displayedPage) ;
  89. gotoLineColumn_faultMode (MODE_ 1, 0) ;
  90. switch (displayedPage) {
  91. case 0 :
  92. printString_faultMode (MODE_ "SHCSR: 0x") ;
  93. printHex8_faultMode (MODE_ SCB_SHCSR) ;
  94. gotoLineColumn_faultMode (MODE_ 2, 0) ;
  95. printString_faultMode (MODE_ "MMFSR: 0x") ;
  96. printHex2_faultMode (MODE_ MMFSR) ;
  97. gotoLineColumn_faultMode (MODE_ 3, 0) ;
  98. printString_faultMode (MODE_ "MMFAR: 0x") ;
  99. printHex8_faultMode (MODE_ MMFAR) ;
  100. break ;
  101. case 1 :
  102. printString_faultMode (MODE_ "BFSR: 0x") ;
  103. printHex2_faultMode (MODE_ BFSR) ;
  104. gotoLineColumn_faultMode (MODE_ 2, 0) ;
  105. printString_faultMode (MODE_ "BFAR: 0x") ;
  106. printHex8_faultMode (MODE_ BFAR) ;
  107. gotoLineColumn_faultMode (MODE_ 3, 0) ;
  108. printString_faultMode (MODE_ "CCR: 0x") ;
  109. printHex8_faultMode (MODE_ SCB_CCR) ;
  110. break ;
  111. case 2 :
  112. printString_faultMode (MODE_ "AFSR: 0x") ;
  113. printHex8_faultMode (MODE_ AFSR) ;
  114. gotoLineColumn_faultMode (MODE_ 2, 0) ;
  115. printString_faultMode (MODE_ "UFSR: 0x") ;
  116. printHex4_faultMode (MODE_ UFSR) ;
  117. break ;
  118. case 3 :
  119. printString_faultMode (MODE_ "LR: 0x") ;
  120. printHex8_faultMode (MODE_ inLinkRegisterValue) ;
  121. gotoLineColumn_faultMode (MODE_ 2, 0) ;
  122. if ((inLinkRegisterValue & (1 << 2)) != 0) { // Fault occurs in user mode
  123. uint32_t psp ;
  124. asm ("mrs %[result], psp" : [result] "=r" (psp) ) ;
  125. printString_faultMode (MODE_ "PSP: 0x") ;
  126. printHex8_faultMode (MODE_ psp) ;
  127. uint32_t * framePtr = (uint32_t *) psp ;
  128. const uint32_t pc = framePtr [6] ;
  129. gotoLineColumn_faultMode (MODE_ 3, 0) ;
  130. printString_faultMode (MODE_ "PC: 0x") ;
  131. printHex8_faultMode (MODE_ pc) ;
  132. }else{ // Fault occurs in system mode
  133. uint32_t msp ;
  134. asm ("mrs %[result], msp" : [result] "=r" (msp) ) ;
  135. printString_faultMode (MODE_ "MSP: 0x") ;
  136. printHex8_faultMode (MODE_ msp) ;
  137. uint32_t * framePtr = (uint32_t *) msp ;
  138. const uint32_t pc = framePtr [6] ;
  139. gotoLineColumn_faultMode (MODE_ 3, 0) ;
  140. printString_faultMode (MODE_ "PC: 0x") ;
  141. printHex8_faultMode (MODE_ pc) ;
  142. }
  143. break ;
  144. }
  145. }
  146. }
  147. }
  148. }
  149. void HardFault_handler (FAULT_MODE) {
  150. // Init display
  151. uint32_t linkRegisterValue ;
  152. asm ("mov %[result], lr" : [result] "=r" (linkRegisterValue) ) ;
  153. handleFault (MODE_ "HardFault", linkRegisterValue) ;
  154. }
  155. void MemManage_handler (FAULT_MODE) {
  156. // Init display
  157. uint32_t linkRegisterValue ;
  158. asm ("mov %[result], lr" : [result] "=r" (linkRegisterValue) ) ;
  159. handleFault (MODE_ "MemManage", linkRegisterValue) ;
  160. }
  161. void BusFault_handler (FAULT_MODE) {
  162. // Init display
  163. uint32_t linkRegisterValue ;
  164. asm ("mov %[result], lr" : [result] "=r" (linkRegisterValue) ) ;
  165. handleFault (MODE_ "BusFault", linkRegisterValue) ;
  166. }
  167. void UsageFault_handler (FAULT_MODE) {
  168. // Init display
  169. uint32_t linkRegisterValue ;
  170. asm ("mov %[result], lr" : [result] "=r" (linkRegisterValue) ) ;
  171. handleFault (MODE_ "UsageFault", linkRegisterValue) ;
  172. }
  173. // UNUSED INTERRUPT
  174. void unusedInterrupt (FAULT_MODE_ const uint32_t inInterruptIndex) asm ("unused.interrupt") ;
  175. void unusedInterrupt (FAULT_MODE_ const uint32_t inInterruptIndex) {
  176. // Init Systick (LCD display requires an 1 ms timer)
  177. configureSystick_faultMode (MODE) ;
  178. // Init display
  179. initScreen_faultMode (MODE) ;
  180. // Title
  181. printString_faultMode (MODE_ "Unhandled interrupt") ;
  182. gotoLineColumn_faultMode (MODE_ 1, 0) ;
  183. printUnsigned_faultMode (MODE_ inInterruptIndex) ;
  184. // Endless loop
  185. endlessLoop (MODE) ;
  186. }
  187. // ASSERTION
  188. void section_assertionFailure (FAULT_MODE_
  189. const uint32_t inMessageValue,
  190. const char * inFileName,
  191. const int inLine) {
  192. // Init Systick (LCD display requires an 1 ms timer)
  193. configureSystick_faultMode (MODE) ;
  194. // Init display
  195. initScreen_faultMode (MODE) ;
  196. // Title
  197. printString_faultMode (MODE_ "Assertion Failure") ;
  198. // Associated value
  199. gotoLineColumn_faultMode (MODE_ 1, 0) ;
  200. printString_faultMode (MODE_ "Value: ") ;
  201. printUnsigned_faultMode (MODE_ inMessageValue) ;
  202. // File
  203. int32_t idx = (int32_t) strlen (inFileName) ;
  204. bool loop = true ;
  205. while ((idx > 0) && loop) {
  206. idx -= 1 ;
  207. loop = inFileName [idx] != '/' ;
  208. }
  209. gotoLineColumn_faultMode (MODE_ 2, 0) ;
  210. printString_faultMode (MODE_ & inFileName [idx + 1]) ;
  211. // Line
  212. gotoLineColumn_faultMode (MODE_ 3, 0) ;
  213. printString_faultMode (MODE_ "Line: ") ;
  214. printUnsigned_faultMode (MODE_ (uint32_t) inLine) ;
  215. // Endless loop
  216. endlessLoop (MODE) ;
  217. }
  218. void assertion (const bool inAssertion,
  219. const uint32_t inMessageValue,
  220. const char * inFileName,
  221. const int inLine) {
  222. if (!inAssertion) {
  223. assertionFailure (inMessageValue, inFileName, inLine) ;
  224. }
  225. }
  226. void assertNonNullPointer (const void * inPointer,
  227. const char * inFileName,
  228. const int inLine) {
  229. if (nullptr == inPointer) {
  230. assertionFailure (0, inFileName, inLine) ;
  231. }
  232. }