source: rtems/cpukit/score/cpu/arm/arm_exc_interrupt.S @ f2f211c5

4.11
Last change on this file since f2f211c5 was f2f211c5, checked in by Sebastian Huber <sebastian.huber@…>, on May 31, 2013 at 11:59:34 AM

smp: Add ARM support

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreCPU
5 *
6 * @brief ARM interrupt exception prologue and epilogue.
7 */
8
9/*
10 * Copyright (c) 2009-2013 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.com/license/LICENSE.
21 */
22
23/*
24 * The upper EXCHANGE_SIZE bytes of the INT stack area are used for data
25 * exchange between INT and SVC mode.  Below of this is the actual INT stack.
26 * The exchange area is only accessed if INT is disabled.
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <rtems/asm.h>
34#include <rtems/score/percpu.h>
35
36#ifdef ARM_MULTILIB_ARCH_V4
37
38#define EXCHANGE_LR r4
39#define EXCHANGE_SPSR r5
40#define EXCHANGE_CPSR r6
41#define EXCHANGE_INT_SP r7
42
43#define EXCHANGE_LIST {EXCHANGE_LR, EXCHANGE_SPSR, EXCHANGE_CPSR, EXCHANGE_INT_SP}
44#define EXCHANGE_SIZE 16
45
46#define CONTEXT_LIST {r0, r1, r2, r3, EXCHANGE_LR, EXCHANGE_SPSR, r12}
47#define CONTEXT_SIZE 28
48
49#ifdef ARM_MULTILIB_VFP_D32
50  #define VFP_CONTEXT_WITH_ALIGNMENT_SPACE (24 * 8 + 4 + 4)
51#endif
52
53.extern _Thread_Dispatch_disable_level
54
55.extern bsp_interrupt_dispatch
56
57.arm
58.globl _ARMV4_Exception_interrupt
59_ARMV4_Exception_interrupt:
60
61        /* Save exchange registers to exchange area */
62        stmdb   sp, EXCHANGE_LIST
63
64        /* Set exchange registers */
65        mov     EXCHANGE_LR, lr
66        mrs     EXCHANGE_SPSR, SPSR
67        mrs     EXCHANGE_CPSR, CPSR
68        sub     EXCHANGE_INT_SP, sp, #EXCHANGE_SIZE
69
70        /* Switch to SVC mode */
71        orr     EXCHANGE_CPSR, EXCHANGE_CPSR, #0x1
72        msr     CPSR_c, EXCHANGE_CPSR
73
74        /*
75         * Save context.  We save the LR separately because it has to be
76         * restored in SVC mode.  The other registers can be restored in INT
77         * mode.
78         */
79        stmdb   sp!, CONTEXT_LIST
80        stmdb   sp!, {lr}
81
82#ifdef ARM_MULTILIB_VFP_D32
83        /* Save VFP context */
84        sub     sp, #VFP_CONTEXT_WITH_ALIGNMENT_SPACE
85        add     r1, sp, #4
86        vmrs    r0, FPSCR
87        bic     r1, r1, #7
88        vstmia  r1!, {d0-d7}
89        vstmia  r1!, {d16-d31}
90        str     r0, [r1]
91#endif
92
93#ifdef RTEMS_SMP
94        /* ISR enter */
95        blx     _ISR_SMP_Enter
96
97        /* Remember INT stack pointer */
98        mov     r1, EXCHANGE_INT_SP
99
100        /* Restore exchange registers from exchange area */
101        ldmia   r1, EXCHANGE_LIST
102
103        /* Switch stack if necessary and save original stack pointer */
104        mov     r2, sp
105        cmp     r0, #0
106        moveq   sp, r1
107        stmdb   sp!, {r2}
108
109        /* Call BSP dependent interrupt dispatcher */
110        blx     bsp_interrupt_dispatch
111
112        /* Restore stack pointer */
113        ldr     sp, [sp]
114
115        /* ISR exit */
116        blx     _ISR_SMP_Exit
117        cmp     r0, #0
118        beq     thread_dispatch_done
119
120        /* Thread dispatch */
121        blx     _Thread_Dispatch
122
123thread_dispatch_done:
124#else /* RTEMS_SMP */
125        /* Remember INT stack pointer */
126        mov     r1, EXCHANGE_INT_SP
127
128        /* Restore exchange registers from exchange area */
129        ldmia   r1, EXCHANGE_LIST
130
131        /* Get interrupt nest level */
132        ldr     r0, =ISR_NEST_LEVEL
133        ldr     r2, [r0]
134
135        /* Switch stack if necessary and save original stack pointer */
136        mov     r3, sp
137        cmp     r2, #0
138        moveq   sp, r1
139        stmdb   sp!, {r3}
140
141        /* Switch to THUMB instructions if necessary */
142        SWITCH_FROM_ARM_TO_THUMB        r1
143
144        /* Increment interrupt nest and thread dispatch disable level */
145        ldr     r1, =_Thread_Dispatch_disable_level
146        ldr     r3, [r1]
147        add     r2, #1
148        add     r3, #1
149        str     r2, [r0]
150        str     r3, [r1]
151
152        /* Call BSP dependent interrupt dispatcher */
153        bl      bsp_interrupt_dispatch
154
155        /* Decrement interrupt nest and thread dispatch disable level */
156        ldr     r0, =ISR_NEST_LEVEL
157        ldr     r1, =_Thread_Dispatch_disable_level
158        ldr     r2, [r0]
159        ldr     r3, [r1]
160        sub     r2, #1
161        sub     r3, #1
162        str     r2, [r0]
163        str     r3, [r1]
164
165        /* Restore stack pointer */
166        SWITCH_FROM_THUMB_TO_ARM
167        ldr     sp, [sp]
168        SWITCH_FROM_ARM_TO_THUMB        r0
169
170        /* Check thread dispatch disable level */
171        cmp     r3, #0
172        bne     thread_dispatch_done
173
174        /* Check context switch necessary */
175        ldr     r0, =DISPATCH_NEEDED
176        ldrb    r1, [r0]
177        cmp     r1, #0
178        beq     thread_dispatch_done
179
180        /* This aligns thread_dispatch_done on a 4 byte boundary */
181#ifdef __thumb__
182        nop
183#endif /* __thumb__ */
184
185        /* Thread dispatch */
186        bl      _Thread_Dispatch
187
188thread_dispatch_done:
189
190        /* Switch to ARM instructions if necessary */
191        SWITCH_FROM_THUMB_TO_ARM
192#endif /* RTEMS_SMP */
193
194#ifdef ARM_MULTILIB_VFP_D32
195        /* Restore VFP context */
196        add     r1, sp, #4
197        bic     r1, r1, #7
198        vldmia  r1!, {d0-d7}
199        vldmia  r1!, {d16-d31}
200        ldr     r0, [r1]
201        add     sp, #VFP_CONTEXT_WITH_ALIGNMENT_SPACE
202        vmsr    FPSCR, r0
203#endif
204
205        /* Restore link register */
206        ldmia   sp!, {lr}
207
208        /*
209         * XXX: Remember and restore stack pointer.  The data on the stack is
210         * still in use.  So the stack is now in an inconsistent state.  The
211         * FIQ handler implementation must not use this area.
212         */
213        mov     r0, sp
214        add     sp, #CONTEXT_SIZE
215
216        /* Get INT mode program status register */
217        mrs     r1, CPSR
218        bic     r1, r1, #0x1
219
220        /* Switch to INT mode */
221        msr     CPSR_c, r1
222
223        /* Save EXCHANGE_LR and EXCHANGE_SPSR registers to exchange area */
224        stmdb   sp!, {EXCHANGE_LR, EXCHANGE_SPSR}
225
226        /* Restore context */
227        ldmia   r0, CONTEXT_LIST
228
229        /* Set return address and program status */
230        mov     lr, EXCHANGE_LR
231        msr     SPSR_fsxc, EXCHANGE_SPSR
232
233        /* Restore EXCHANGE_LR and EXCHANGE_SPSR registers from exchange area */
234        ldmia   sp!, {EXCHANGE_LR, EXCHANGE_SPSR}
235
236        /* Return from interrupt */
237        subs    pc, lr, #4
238
239#endif /* ARM_MULTILIB_ARCH_V4 */
Note: See TracBrowser for help on using the repository browser.