SingingCat 0
application
fatal-error.c
1#include "main-header.h"
2#include "loader-api.h"
3#include "constants.h"
4#include "led.h"
5#include "multiram.h"
6
7/* These are volatile to try and prevent the compiler/linker optimising them
8 * away as the variables never actually get used. If the debugger won't show the
9 * values of the variables, make them global my moving their declaration outside
10 * of this function. */
11static volatile uint32_t r0;
12static volatile uint32_t r1;
13static volatile uint32_t r2;
14static volatile uint32_t r3;
15static volatile uint32_t r12;
16static volatile uint32_t lr; /* Link register. */
17static volatile uint32_t pc; /* Program counter. */
18static volatile uint32_t psr; /* Program status register. */
19
20static void stdHandler(uint32_t *pulFaultStackAddress) __attribute__((naked, no_instrument_function));
21
22static char fatalerrorbuf[512];
27void fatal_error(const char *format, ...) {
28 char *buf;
29 va_list args;
30
31 printf("Fatal error handler invoked\r\n");
32 buf = (char *)&fatalerrorbuf;
33 va_start(args, format);
34 vsnprintf(buf, 511, format, args);
35 va_end(args);
36
37 void *padr = constants()->last_return_address;
38 void *dadr = constants()->failing_address;
39 int user = (int)constants()->in_user_app;
40 long z = mculib_get_seconds_since_boot();
41
42 led_indicate(LED_FATALERROR);
43 for (;;) {
44 printf("FATAL ERROR: %s @ %p (failing address: %p) (usermode:%i)\r\n", buf, padr, dadr, user);
45 long l = mculib_get_seconds_since_boot();
46 while (l == mculib_get_seconds_since_boot()) {
47 }
48 if ((mculib_get_seconds_since_boot() - z) > 10) {
49 break;
50 }
51 }
52 constants_validate();
53 reboot_hard();
54 stdHandler(NULL); // keeps gcc happy (function is used)
55}
56
57void prvGetRegistersFromStack(uint32_t *pulFaultStackAddress) {
58 if (!is_stack(pulFaultStackAddress)) {
59 r0 = 0;
60 r1 = 0;
61 r2 = 0;
62 r3 = 0;
63 r12 = 0;
64 lr = 0xFFFFFFFF;
65 pc = 0xFFFFFFFF;
66 psr = 0;
67 return;
68 }
69 r0 = pulFaultStackAddress[0];
70 r1 = pulFaultStackAddress[1];
71 r2 = pulFaultStackAddress[2];
72 r3 = pulFaultStackAddress[3];
73
74 r12 = pulFaultStackAddress[4];
75 lr = pulFaultStackAddress[5];
76 pc = pulFaultStackAddress[6];
77 psr = pulFaultStackAddress[7];
78}
79
80static void printRegisters() {
81 printf("r0: %p\r\n", r0);
82 printf("r1: %p\r\n", r1);
83 printf("r2: %p\r\n", r2);
84 printf("r3: %p\r\n", r3);
85 printf("r12: %p\r\n", r12);
86 printf("lr: %p\r\n", lr);
87 printf("pc: %p\r\n", pc);
88 printf("psr: %p\r\n", psr);
89 printf("fct: %p\r\n", constants()->last_return_address);
90}
91
92
93static void stdHandler(uint32_t *pulFaultStackAddress) {
94 if (!is_stack(pulFaultStackAddress)) {
95 fatal_error("hardfault, no stack");
96 }
97 prvGetRegistersFromStack(pulFaultStackAddress);
98 printf("Vector: %p\r\n", *((uint32_t *)0xE000ED08));
99 constants()->CFSR = *(uint32_t *)0xE000ED28;
100 constants()->SHCSR = *((uint32_t *)0xE000ED24);
101 constants()->MMFAR = *((uint32_t *)0xE000ED34);
102 constants()->HFSR = *((uint32_t *)0xE000ED2C);
103 constants()->BFAR = *((uint32_t *)0xE000ED38);
104 printf("CFSR : %p\r\n", constants()->CFSR); // ufsr, mmfsr, bfsr
105 printf("SHCSR: %p\r\n", constants()->SHCSR);
106 printf("MMFAR: %p\r\n", constants()->MMFAR);
107 printf("HFSR : %p\r\n", constants()->HFSR);
108 printf("BFAR : %p\r\n", constants()->BFAR);
109 printRegisters();
110 constants()->last_return_address = (void *)pc;
111 constants()->failing_address = (void *)r3;
112 fatal_error("hardfault");
113}
114void UsageFault_Handler() __attribute__((no_instrument_function));
115void BusFault_Handler() __attribute__((no_instrument_function));
116void MemManage_Handler() __attribute__((no_instrument_function));
117void HardFault_Handler() __attribute__((naked, no_instrument_function));
118
119void UsageFault_Handler() {
120 fatal_error("eeeeks usagefault");
121}
122
123void BusFault_Handler() {
124 fatal_error("busfault");
125}
126void MemManage_Handler() {
127 fatal_error("memmanagefault");
128}
129
130void HardFault_Handler() {
131#ifdef __unix__
132 printf("Hardfault in posix???\n");
133#else
134 __asm volatile
135 (
136 " tst lr, #4 \n"
137 " ite eq \n"
138 " mrseq r0, msp \n"
139 " mrsne r0, psp \n"
140 " ldr r1, [r0, #24] \n"
141 " ldr r2, handler2_address_const \n"
142 " bx r2 \n"
143 " ldr r1, [r0, #24] \n"
144 " handler2_address_const: .word stdHandler \n"
145 );
146#endif
147}