source: rtems/c/src/lib/libbsp/arm/shared/irq/irq_asm.S @ 3762222

4.104.114.84.95
Last change on this file since 3762222 was 3762222, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 4, 2002 at 1:24:40 PM

2002-10-04 Jay Monkman <jtm@…>

  • irq/irq_asm.S: Add FIQ support.
  • Property mode set to 100644
File size: 5.8 KB
Line 
1/* irq_asm.S
2 *
3 *  This file contains the implementation of the IRQ handler
4 *
5 *  Copyright (c) 2002 Advent Networks, Inc.
6 *      Jay Monkman <jmonkman@adventnetworks.com>
7 *
8 *  CopyRight (C) 2000 Canon Research France SA.
9 *  Emmanuel Raguet,  mailto:raguet@crf.canon.fr
10 *
11 *  Modified Andy Dachs <a.dachs@sstl.co.uk>
12 *  Copyright (c) 2001 Surrey Satellite Technolgy Limited
13 *
14 *  The license and distribution terms for this file may be
15 *  found in found in the file LICENSE in this distribution or at
16 *  http://www.OARcorp.com/rtems/license.html.
17 *
18 *  $Id$
19 */
20
21#include "asm.h"
22#define __asm__
23
24        .globl _ISR_Handler
25_ISR_Handler:
26        stmdb   sp!, {r0, r1, r2, r3, r12}   /* save regs on INT stack */
27        stmdb   sp!, {lr}               /*    now safe to call C funcs */
28       
29
30/* one nest level deeper */
31        ldr     r0, =_ISR_Nest_level
32        ldr     r1, [r0]
33        add     r1, r1,#1
34        str     r1, [r0]
35       
36/* disable multitasking */
37        ldr     r0, =_Thread_Dispatch_disable_level         
38        ldr     r1, [r0]
39        add     r1, r1,#1
40        str     r1, [r0]
41
42/* BSP specific function to INT handler */
43        /* FIXME: I'm not sure why I can't save just r12. I'm also  */
44        /*     not sure which of r1-r3 are important.               */
45        bl      ExecuteITHandler
46
47/* one less nest level  */     
48        ldr     r0, =_ISR_Nest_level
49        ldr     r1, [r0]
50        sub     r1, r1,#1
51        str     r1, [r0]
52       
53/* unnest multitasking */
54        ldr     r0, =_Thread_Dispatch_disable_level
55        ldr     r1, [r0]
56        sub     r1, r1,#1
57        str     r1, [r0]
58
59/* check to see if we interrupted and INT (with FIQ?) */
60        mrs   r0, spsr
61        and   r0, r0, #0x1f
62        cmp   r0, #0x12        /* is it INT mode? */ 
63        beq   exitit
64
65/* If thread dispatching is disabled, exit */
66        cmp     r1, #0
67        bne     exitit
68
69/* If a task switch is necessary, call scheduler */
70        ldr     r0, =_Context_Switch_necessary
71        ldr     r1, [r0]
72        cmp     r1, #0
73       
74        /* since bframe is going to clear _ISR_Signals_to_thread_executing, */
75        /*    we need to load it here */
76        ldr     r0, =_ISR_Signals_to_thread_executing   
77        ldr     r1, [r0]
78        bne     bframe
79       
80/* If a signals to be sent (_ISR_Signals_to_thread_executing != 0),        */
81/*  call scheduler */
82        cmp     r1, #0
83        beq     exitit
84       
85/* _ISR_Signals_to_thread_executing = FALSE */
86        mov     r1, #0
87        str     r1, [r0]
88
89bframe:
90
91/* Now we need to set up the return from this ISR to be _ISR_Dispatch */
92/* To do that, we need to save the current lr_int and spsr_int on the */
93/* SVC stack                                                          */
94        mrs     r0, spsr
95        ldmia   sp!, {r1}       /* get lr off stack */
96        stmdb   sp!, {r1}
97        mrs     r2, cpsr   
98        orr     r3, r2, #0x1    /* change to SVC mode */
99        msr     cpsr_c, r3
100
101        /* now in SVC mode */
102        stmdb   sp!, {r0, r1}   /* put spsr_int and lr_int on SVC stack */
103        msr     cpsr_c, r2      /* change back to INT mode */
104
105        /* now in INT mode */
106
107        /* replace lr with address of _ISR_Dispatch */
108        ldr     lr, =_ISR_Dispatch_p_4    /* On entry to an ISR, the lr is */
109                                          /*    the return address + 4, so */
110                                          /*    we have to emulate that    */
111        ldmia   sp!, {r1}                 /* out with the old          */
112        stmdb   sp!, {lr}                 /*    in with the new (lr) */
113
114       
115        orr     r0, r0, #0xc0
116        msr     spsr, r0
117                                       
118exitit:
119        ldmia   sp!, {lr}                     /* restore regs from INT stack */
120        ldmia   sp!, {r0, r1, r2, r3, r12}    /* restore regs from INT stack */
121        subs    pc, lr, #4                /* return */
122
123
124
125        /* on entry to _ISR_Dispatch, we're in SVC mode */     
126        .globl _ISR_Dispatch
127_ISR_Dispatch:
128        stmdb   sp!, {r0-r3, r12,lr}      /* save regs on SVC stack */
129                                          /*    (now safe to call C funcs) */
130                                          /*    we don't save lr, since  */
131                                          /*    it's just going to get   */
132                                          /*    overwritten              */
133_ISR_Dispatch_p_4:     
134        bl      _Thread_Dispatch
135        ldmia   sp!, {r0-r3, r12, lr}
136
137        stmdb   sp!, {r0-r2}
138        /* Now we have to screw with the stack */
139        mov     r0, sp                  /* copy the SVC stack pointer */
140       
141        mrs     r1, cpsr   
142        bic     r2, r1, #0x1            /* change to INT mode */
143        orr     r2, r2, #0xc0           /* disable interrupts */
144        msr     cpsr_c, r2
145
146        /* now in INT mode */
147        stmdb   sp!, {r4, r5, r6}   /* save temp vars on INT stack */
148        ldmia   r0!, {r4, r5, r6}   /* Get r0-r3 from SVC stack */
149        stmdb   sp!, {r4, r5, r6}   /*    and save them on INT stack */
150       
151        ldmia   r0!, {r4, r5}           /* get saved values from SVC stack */
152                                        /*      r4=spsr, r5=lr */
153        mov     lr,   r5                /* restore lr_int */
154        msr     spsr, r4                /* restore spsr_int */
155
156        /* switch to SVC mode, update sp, then return to INT mode */
157        msr     cpsr_c, r1              /* switch to SVC mode */
158        mov     sp, r0                  /* update sp_svc */
159        msr     cpsr_c, r2              /* switch back to INT mode */
160
161        /* pop all the registers from the stack */
162        ldmia   sp!, {r0, r1, r2}
163        ldmia   sp!, {r4, r5, r6}
164
165        /* Finally, we can return to the interrupted task */
166        subs    pc, lr, #4
167
168
169
170
171
Note: See TracBrowser for help on using the repository browser.