1 | /* |
---|
2 | * Copyright (c) 2013 embedded brains GmbH. All rights reserved. |
---|
3 | * |
---|
4 | * embedded brains GmbH |
---|
5 | * Obere Lagerstr. 30 |
---|
6 | * 82178 Puchheim |
---|
7 | * Germany |
---|
8 | * <rtems@embedded-brains.de> |
---|
9 | * |
---|
10 | * The license and distribution terms for this file may be |
---|
11 | * found in the file LICENSE in this distribution or at |
---|
12 | * http://www.rtems.org/license/LICENSE. |
---|
13 | */ |
---|
14 | |
---|
15 | #ifdef HAVE_CONFIG_H |
---|
16 | #include "config.h" |
---|
17 | #endif |
---|
18 | |
---|
19 | #include <rtems/score/armv7m.h> |
---|
20 | |
---|
21 | #ifdef ARM_MULTILIB_ARCH_V7M |
---|
22 | |
---|
23 | void __attribute__((naked)) _ARMV7M_Exception_default( void ) |
---|
24 | { |
---|
25 | /* On exception entry, ARMv7M saves context state onto a stack pointed to |
---|
26 | * by either MSP or PSP. The value stored in LR indicates whether we were |
---|
27 | * in Thread or Handler mode, whether we were using the FPU (if any), |
---|
28 | * and which stack pointer we were using. |
---|
29 | * In particular, bit 2 of LR will be 0 if we were using MSP. |
---|
30 | * |
---|
31 | * For a more detailed explanation, see the Exception Entry Behavior |
---|
32 | * section of the ARMv7M Architecture Reference Manual. |
---|
33 | */ |
---|
34 | |
---|
35 | /* As we're in Handler mode here, we'll always operate on MSP. |
---|
36 | * However, we need to store the right SP in our CPU_Exception_frame. |
---|
37 | */ |
---|
38 | __asm__ volatile ( |
---|
39 | "sub sp, %[cpufsz]\n" /* Allocate space for a CPU_Exception_frame. */ |
---|
40 | "stm sp, {r0-r12}\n" |
---|
41 | "tst lr, #4\n" /* Check if bit 2 of LR is zero. If so, PSR.Z = 1 */ |
---|
42 | "itte eq\n" /* IF bit 2 of LR is zero... (PSR.Z == 1) */ |
---|
43 | "mrseq r0, msp\n" /* THEN we were using MSP. */ |
---|
44 | "addeq r0, %[cpufsz]\n" /* THEN, set r0 = old MSP value. */ |
---|
45 | "mrsne r0, psp\n" /* ELSE it's not zero; we were using PSP. */ |
---|
46 | "add r2, r0, %[v7mlroff]\n" |
---|
47 | "add r1, sp, %[cpulroff]\n" |
---|
48 | "ldm r2, {r3-r5}\n" /* Grab LR, PC and PSR from the stack.. */ |
---|
49 | "stm r1, {r3-r5}\n" /* ..and store them in our CPU_Exception_frame. */ |
---|
50 | "mrs r1, ipsr\n" |
---|
51 | "str r1, [sp, %[cpuvecoff]]\n" |
---|
52 | |
---|
53 | /* Argument for high level handler */ |
---|
54 | "mov r0, sp\n" |
---|
55 | |
---|
56 | /* Clear VFP context pointer */ |
---|
57 | "add r3, sp, %[cpuvfpoff]\n" |
---|
58 | "mov r1, #0\n" |
---|
59 | "str r1, [r3]\n" |
---|
60 | |
---|
61 | #ifdef ARM_MULTILIB_VFP |
---|
62 | /* Ensure that the FPU is enabled */ |
---|
63 | "ldr r4, =%[cpacr]\n" |
---|
64 | "tst r4, #(0xf << 20)\n" |
---|
65 | "bne 1f\n" |
---|
66 | |
---|
67 | /* Save VFP context */ |
---|
68 | "sub sp, %[vfpsz]\n" |
---|
69 | "add r4, sp, #4\n" |
---|
70 | "bic r4, r4, #7\n" |
---|
71 | "str r4, [r3]\n" |
---|
72 | "vmrs r2, FPSCR\n" |
---|
73 | "stmia r4!, {r1-r2}\n" |
---|
74 | "vstmia r4!, {d0-d15}\n" |
---|
75 | "mov r1, #0\n" |
---|
76 | "mov r2, #0\n" |
---|
77 | "adds r3, r4, #128\n" |
---|
78 | "2:\n" |
---|
79 | "stmia r4!, {r1-r2}\n" |
---|
80 | "cmp r4, r3\n" |
---|
81 | "bne 2b\n" |
---|
82 | "1:\n" |
---|
83 | #endif |
---|
84 | |
---|
85 | "b _ARM_Exception_default\n" |
---|
86 | : |
---|
87 | : [cpufsz] "i" (sizeof(CPU_Exception_frame)), |
---|
88 | [cpulroff] "i" (offsetof(CPU_Exception_frame, register_lr)), |
---|
89 | [v7mlroff] "i" (offsetof(ARMV7M_Exception_frame, register_lr)), |
---|
90 | [cpuvecoff] "J" (offsetof(CPU_Exception_frame, vector)), |
---|
91 | [cpuvfpoff] "i" (ARM_EXCEPTION_FRAME_VFP_CONTEXT_OFFSET), |
---|
92 | [cpacr] "i" (ARMV7M_CPACR), |
---|
93 | [vfpsz] "i" (ARM_VFP_CONTEXT_SIZE) |
---|
94 | ); |
---|
95 | } |
---|
96 | |
---|
97 | #endif /* ARM_MULTILIB_ARCH_V7M */ |
---|