1 /*
2  * Copyright (c) 2012-2013 Travis Geiselbrecht
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #include <debug.h>
24 #include <stdio.h>
25 #include <compiler.h>
26 #include <stdint.h>
27 #include <bits.h>
28 #include <kernel/thread.h>
29 #include <arch/arm/cm.h>
30 #include <platform.h>
31 
dump_frame(const struct arm_cm_exception_frame * frame)32 static void dump_frame(const struct arm_cm_exception_frame *frame)
33 {
34 
35     printf("exception frame at %p\n", frame);
36     printf("\tr0  0x%08x r1  0x%08x r2  0x%08x r3 0x%08x r4 0x%08x\n",
37            frame->r0, frame->r1, frame->r2, frame->r3, frame->r4);
38     printf("\tr5  0x%08x r6  0x%08x r7  0x%08x r8 0x%08x r9 0x%08x\n",
39            frame->r5, frame->r6, frame->r7, frame->r8, frame->r9);
40     printf("\tr10 0x%08x r11 0x%08x r12 0x%08x\n",
41            frame->r10, frame->r11, frame->r12);
42     printf("\tlr  0x%08x pc  0x%08x psr 0x%08x\n",
43            frame->lr, frame->pc, frame->psr);
44 }
45 
hardfault(struct arm_cm_exception_frame * frame)46 static void hardfault(struct arm_cm_exception_frame *frame)
47 {
48     printf("hardfault: ");
49     dump_frame(frame);
50 
51 #if     (__CORTEX_M >= 0X03) || (__CORTEX_SC >= 300)
52     printf("HFSR 0x%x\n", SCB->HFSR);
53 #endif
54 
55     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
56 }
57 
memmanage(struct arm_cm_exception_frame * frame)58 static void memmanage(struct arm_cm_exception_frame *frame)
59 {
60     printf("memmanage: ");
61     dump_frame(frame);
62 
63 #if     (__CORTEX_M >= 0X03) || (__CORTEX_SC >= 300)
64     uint32_t mmfsr = SCB->CFSR & 0xff;
65 
66     if (mmfsr & (1<<0)) { // IACCVIOL
67         printf("instruction fault\n");
68     }
69     if (mmfsr & (1<<1)) { // DACCVIOL
70         printf("data fault\n");
71     }
72     if (mmfsr & (1<<3)) { // MUNSTKERR
73         printf("fault on exception return\n");
74     }
75     if (mmfsr & (1<<4)) { // MSTKERR
76         printf("fault on exception entry\n");
77     }
78     if (mmfsr & (1<<5)) { // MLSPERR
79         printf("fault on lazy fpu preserve\n");
80     }
81     if (mmfsr & (1<<7)) { // MMARVALID
82         printf("fault address 0x%x\n", SCB->MMFAR);
83     }
84 #endif
85     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
86 }
87 
88 
usagefault(struct arm_cm_exception_frame * frame)89 static void usagefault(struct arm_cm_exception_frame *frame)
90 {
91     printf("usagefault: ");
92     dump_frame(frame);
93 
94 #if  (__CORTEX_M >= 0x03)
95     uint32_t ufsr = BITS_SHIFT(SCB->CFSR, 31, 16);
96     printf("UFSR 0x%x: ", ufsr);
97 
98     if (ufsr & (1<<0))
99         printf("undefined instruction\n");
100     if (ufsr & (1<<1))
101         printf("ESPR invalid\n");
102     if (ufsr & (1<<2))
103         printf("integrity check failed on EXC_RETURN\n");
104     if (ufsr & (1<<3))
105         printf("coprocessor access error\n");
106     if (ufsr & (1<<8))
107         printf("unaligned error\n");
108     if (ufsr & (1<<9))
109         printf("division by zero\n");
110 #endif
111 
112     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
113 }
114 
busfault(struct arm_cm_exception_frame * frame)115 static void busfault(struct arm_cm_exception_frame *frame)
116 {
117     printf("busfault: ");
118     dump_frame(frame);
119 
120     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
121 }
122 
123 /* raw exception vectors */
124 
_nmi(void)125 void _nmi(void)
126 {
127     printf("nmi\n");
128     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
129 }
130 #if     (__CORTEX_M >= 0X03) || (__CORTEX_SC >= 300)
131 
_hardfault(void)132 __NAKED void _hardfault(void)
133 {
134     __asm__ volatile(
135         "push	{r4-r11};"
136         "mov	r0, sp;"
137         "b		%0;"
138         :: "i" (hardfault)
139     );
140     __UNREACHABLE;
141 }
142 
_memmanage(void)143 void _memmanage(void)
144 {
145     __asm__ volatile(
146         "push	{r4-r11};"
147         "mov	r0, sp;"
148         "b		%0;"
149         :: "i" (memmanage)
150     );
151     __UNREACHABLE;
152 }
153 
_busfault(void)154 void _busfault(void)
155 {
156     __asm__ volatile(
157         "push	{r4-r11};"
158         "mov	r0, sp;"
159         "b		%0;"
160         :: "i" (busfault)
161     );
162     __UNREACHABLE;
163 }
164 
_usagefault(void)165 void _usagefault(void)
166 {
167     __asm__ volatile(
168         "push	{r4-r11};"
169         "mov	r0, sp;"
170         "b		%0;"
171         :: "i" (usagefault)
172     );
173     __UNREACHABLE;
174 }
175 #else
176 
_hardfault(void)177 __NAKED void _hardfault(void)
178 {
179     struct arm_cm_exception_frame *frame;
180     __asm__ volatile(
181         "push	{r4-r7};"
182         "mov   r4, r8;"
183         "mov   r5, r9;"
184         "mov   r6, r10;"
185         "mov   r7, r11;"
186         "push   {r4-r7};"
187         "mov	%0, sp;"
188         : "=r" (frame):
189     );
190 
191     printf("hardfault: ");
192     dump_frame(frame);
193 
194     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
195     __UNREACHABLE;
196 }
197 
_memmanage(void)198 void _memmanage(void)
199 {
200     struct arm_cm_exception_frame *frame;
201     __asm__ volatile(
202         "push	{r4-r7};"
203         "mov   r4, r8;"
204         "mov   r5, r9;"
205         "mov   r6, r10;"
206         "mov   r7, r11;"
207         "push   {r4-r7};"
208         "mov	%0, sp;"
209         : "=r" (frame):
210     );
211     printf("memmanage: ");
212     dump_frame(frame);
213 
214     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
215     __UNREACHABLE;
216 }
217 
_busfault(void)218 void _busfault(void)
219 {
220     struct arm_cm_exception_frame *frame;
221     __asm__ volatile(
222         "push	{r4-r7};"
223         "mov   r4, r8;"
224         "mov   r5, r9;"
225         "mov   r6, r10;"
226         "mov   r7, r11;"
227         "push   {r4-r7};"
228         "mov	%0, sp;"
229         : "=r" (frame):
230     );
231     printf("busfault: ");
232     dump_frame(frame);
233 
234     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
235     __UNREACHABLE;
236 }
237 
_usagefault(void)238 void _usagefault(void)
239 {
240     struct arm_cm_exception_frame *frame;
241     __asm__ volatile(
242         "push	{r4-r7};"
243         "mov   r4, r8;"
244         "mov   r5, r9;"
245         "mov   r6, r10;"
246         "mov   r7, r11;"
247         "push   {r4-r7};"
248         "mov	%0, sp;"
249         : "=r" (frame):
250     );
251     printf("usagefault: ");
252     dump_frame(frame);
253     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
254     __UNREACHABLE;
255 }
256 #endif
257 /* systick handler */
_systick(void)258 void __WEAK _systick(void)
259 {
260     printf("systick\n");
261     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
262 }
263 
_debugmonitor(void)264 void __WEAK _debugmonitor(void)
265 {
266     printf("debugmonitor\n");
267     platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
268 }
269