flabbergast's ARM/STM32 examples using libopencm3
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

hardfault.c 3.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /**
  2. * HardFault_HandlerAsm:
  3. * Alternative Hard Fault handler to help debug the reason for a fault.
  4. * To use, edit the vector table to reference this function in the HardFault vector
  5. * This code is suitable for Cortex-M3 and Cortex-M0 cores
  6. */
  7. #pragma weak hard_fault_handler = HardFault_Handler
  8. // Use the 'naked' attribute so that C stacking is not used.
  9. __attribute__((naked))
  10. void HardFault_Handler(void){
  11. /*
  12. * Get the appropriate stack pointer, depending on our mode,
  13. * and use it as the parameter to the C handler. This function
  14. * will never return
  15. */
  16. // ".syntax unified\n"
  17. __asm(
  18. "MOVS R0, #4 \n"
  19. "MOV R1, LR \n"
  20. "TST R0, R1 \n"
  21. "BEQ _MSP \n"
  22. "MRS R0, PSP \n"
  23. "B HardFault_HandlerC \n"
  24. "_MSP: \n"
  25. "MRS R0, MSP \n"
  26. "B HardFault_HandlerC \n"
  27. );
  28. // ".syntax divided\n"
  29. }
  30. /**
  31. * HardFaultHandler_C:
  32. * This is called from the HardFault_HandlerAsm with a pointer the Fault stack
  33. * as the parameter. We can then read the values from the stack and place them
  34. * into local variables for ease of reading.
  35. * We then read the various Fault Status and Address Registers to help decode
  36. * cause of the fault.
  37. * The function ends with a BKPT instruction to force control back into the debugger
  38. */
  39. void HardFault_HandlerC(unsigned long *hardfault_args){
  40. volatile unsigned long stacked_r0 ;
  41. volatile unsigned long stacked_r1 ;
  42. volatile unsigned long stacked_r2 ;
  43. volatile unsigned long stacked_r3 ;
  44. volatile unsigned long stacked_r12 ;
  45. volatile unsigned long stacked_lr ;
  46. volatile unsigned long stacked_pc ;
  47. volatile unsigned long stacked_psr ;
  48. volatile unsigned long _CFSR ;
  49. volatile unsigned long _HFSR ;
  50. volatile unsigned long _DFSR ;
  51. volatile unsigned long _AFSR ;
  52. volatile unsigned long _BFAR ;
  53. volatile unsigned long _MMAR ;
  54. stacked_r0 = ((unsigned long)hardfault_args[0]) ;
  55. stacked_r1 = ((unsigned long)hardfault_args[1]) ;
  56. stacked_r2 = ((unsigned long)hardfault_args[2]) ;
  57. stacked_r3 = ((unsigned long)hardfault_args[3]) ;
  58. stacked_r12 = ((unsigned long)hardfault_args[4]) ;
  59. stacked_lr = ((unsigned long)hardfault_args[5]) ;
  60. stacked_pc = ((unsigned long)hardfault_args[6]) ;
  61. stacked_psr = ((unsigned long)hardfault_args[7]) ;
  62. // Configurable Fault Status Register
  63. // Consists of MMSR, BFSR and UFSR
  64. _CFSR = (*((volatile unsigned long *)(0xE000ED28))) ;
  65. // Hard Fault Status Register
  66. _HFSR = (*((volatile unsigned long *)(0xE000ED2C))) ;
  67. // Debug Fault Status Register
  68. _DFSR = (*((volatile unsigned long *)(0xE000ED30))) ;
  69. // Auxiliary Fault Status Register
  70. _AFSR = (*((volatile unsigned long *)(0xE000ED3C))) ;
  71. // Read the Fault Address Registers. These may not contain valid values.
  72. // Check BFARVALID/MMARVALID to see if they are valid values
  73. // MemManage Fault Address Register
  74. _MMAR = (*((volatile unsigned long *)(0xE000ED34))) ;
  75. // Bus Fault Address Register
  76. _BFAR = (*((volatile unsigned long *)(0xE000ED38))) ;
  77. __asm("BKPT #0\n") ; // Break into the debugger
  78. }