fault-handlers-assertion.cpp 8.1 KB

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