source: rtems/cpukit/score/cpu/nios2/nios2-iic-low-level.S @ a385489

4.115
Last change on this file since a385489 was a385489, checked in by Chris Johns <chrisj@…>, on 08/18/11 at 09:00:14

2011-08-18 Chris Johns <chrisj@…>

  • cpu.c: Fix the ISR get level for the IIC. Make _CPU_Context_Initialize a function rather than inlined.
  • cpu_asm.S: Do not enable interrupt on return, rather resume the state on entry to the ISR.
  • irq.c, nios2/nios2-iic-low-level.S: Change the ISR handler so the ipending decoding is in C and within the interrupt context. This is usable with the Altera HAL directly.
  • rtems/score/cpu.h: Add ienable and ipending interfaces. Add some comments. Remove _CPU_Context_Initialize.
  • Property mode set to 100644
File size: 6.8 KB
Line 
1/*
2 *  $Id$
3 *
4 *  This file contains all assembly code for the
5 *  NIOS2 implementation of RTEMS.
6 *
7 *  Copyright (c) 2006 Kolja Waschk (rtemsdev/ixo.de)
8 *
9 *  Derived from no_cpu/cpu_asm.S, copyright (c) 1989-1999,
10 *    On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 *
16 */
17
18#ifdef HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <rtems/asm.h>
23#include <rtems/score/cpu_asm.h>
24
25    .set noat
26
27    .globl _exception_vector
28
29_exception_vector:
30
31    /*
32     * First, re-wind so we're pointed to the instruction where the exception
33     * occurred.
34     */
35
36    addi ea, ea, -4
37
38    /*
39     * Now test to determine the cause of the exception.
40     */
41
42    /* TODO: Look at [ea] if there was an unknown/trap instruction */
43
44    /* If interrupts are globally disabled, it certainly was no interrupt */
45    rdctl et, estatus
46    andi et, et, 1
47    beq et, zero, _Exception_Handler
48
49    /* If no interrupts are pending, it was a software exception */
50    rdctl et, ipending
51    beq et, zero, _Exception_Handler
52
53    /*
54     * Falling through to here means that this was a hardware interrupt.
55     */
56
57    br _ISR_Handler
58
59/* =====================================================================
60 * Exception handler:
61 *   Responsible for unimplemented instructions and other software
62 *   exceptions. Not responsible for hardware interrupts. Currently,
63 *   software exceptions are regarded as error conditions, and the
64 *   handling isn't perfect. */
65
66_Exception_Handler:
67
68    /* stw et, 108(sp') => stw et, -20(sp) */
69    stw et, -20(sp)
70    mov et, sp
71    addi sp, sp, -128
72
73    stw r1,   0(sp)
74    stw r2,   4(sp)
75    stw r3,   8(sp)
76
77    rdctl r1, estatus
78    rdctl r2, ienable
79    rdctl r3, ipending
80
81    stw r4,   12(sp)
82    stw r5,   16(sp)
83    stw r6,   20(sp)
84    stw r7,   24(sp)
85    stw r8,   28(sp)
86    stw r9,   32(sp)
87    stw r10,  36(sp)
88    stw r11,  40(sp)
89    stw r12,  44(sp)
90    stw r13,  48(sp)
91    stw r14,  52(sp)
92    stw r15,  56(sp)
93    stw r16,  60(sp)
94    stw r17,  64(sp)
95    stw r18,  68(sp)
96    stw r19,  72(sp)
97    stw r20,  76(sp)
98    stw r21,  80(sp)
99    stw r22,  84(sp)
100    stw r23,  88(sp)
101    stw gp,   92(sp)
102    stw fp,   96(sp)
103    /* sp */
104    stw et,  100(sp)
105    stw ra,  104(sp)
106    /* stw et,  108(sp) */
107    stw ea,  112(sp)
108
109    /* status */
110    stw r1, 116(sp)
111    /* ienable */
112    stw r2, 120(sp)
113    /* ipending */
114    stw r3, 124(sp)
115
116    /*
117     * Restore the global pointer.
118     */
119
120    movhi gp, %hiadj(_gp)
121    addi gp, gp, %lo(_gp)
122
123    /*
124     * Pass a pointer to the stack frame as the input argument of the
125     * exception handler (CPU_Exception_frame *).
126     */
127
128    mov r4, sp
129
130    /*
131     * Call the exception handler.
132     */
133
134    .extern __Exception_Handler
135    call __Exception_Handler
136
137stuck_in_exception:
138    br stuck_in_exception
139
140    /*
141     * Restore the saved registers, so that all general purpose registers
142     * have been restored to their state at the time the interrupt occured.
143     */
144
145    ldw r1,   0(sp)
146    ldw r2,   4(sp)
147    ldw r3,   8(sp)
148    ldw r4,   12(sp)
149    ldw r5,   16(sp)
150    ldw r6,   20(sp)
151    ldw r7,   24(sp)
152    ldw r8,   28(sp)
153    ldw r9,   32(sp)
154    ldw r10,  36(sp)
155    ldw r11,  40(sp)
156    ldw r12,  44(sp)
157    ldw r13,  48(sp)
158    ldw r14,  52(sp)
159    ldw r15,  56(sp)
160    ldw r16,  60(sp)
161    ldw r17,  64(sp)
162    ldw r18,  68(sp)
163    ldw r19,  72(sp)
164    ldw r20,  76(sp)
165    ldw r21,  80(sp)
166    ldw r22,  84(sp)
167    ldw r23,  88(sp)
168    ldw gp,   92(sp)
169    ldw fp,   96(sp)
170    ldw ra,  104(sp)
171
172    /* Disable interrupts */
173    wrctl status, r0
174
175    ldw ea,  112(sp)
176    ldw et,  116(sp)
177
178    /* FIXME: Enable interrupts after exception processing */
179    ori et, et, 1
180    wrctl estatus, et
181    ldw et,  108(sp)
182
183    /* Restore stack pointer */
184    ldw sp,  100(sp)
185
186    eret
187
188/* ===================================================================== */
189
190    .section .text
191
192_ISR_Handler:
193
194    /*
195     * Process an external hardware interrupt.
196     *
197     * First, preserve all callee saved registers on
198     * the stack. (See the Nios2 ABI documentation for details).
199     *
200     * Do we really need to save all?
201     *
202     * If this is interrupting a task (and not another interrupt),
203     * everything is saved into the task's stack, thus putting us
204     * in a situation similar to when the task calls a subroutine
205     * (and only the CPU_Context_Control subset needs to be changed)
206     */
207
208    rdctl et, estatus
209
210    /* Keep this in the same order as CPU_Interrupt_frame: */
211
212    addi sp, sp, -76
213    stw r1,  0(sp)
214    stw r2,  4(sp)
215    stw r3,  8(sp)
216    stw r4,  12(sp)
217    stw r5,  16(sp)
218    stw r6,  20(sp)
219    stw r7,  24(sp)
220    stw r8,  28(sp)
221    stw r9,  32(sp)
222    stw r10, 36(sp)
223    stw r11, 40(sp)
224    stw r12, 44(sp)
225    stw r13, 48(sp)
226    stw r14, 52(sp)
227    stw r15, 56(sp)
228    stw ra,  60(sp)
229    stw gp,  64(sp)
230    /* et contains status */
231    stw et,  68(sp)
232    stw ea,  72(sp)
233
234#if REMOVED_BY_CCJ
235    /*
236     * Obtain a bitlist of the pending interrupts.
237     */
238
239    rdctl et, ipending
240
241    /*
242     * Restore the global pointer to the expected value.
243     */
244
245    movhi gp, %hiadj(_gp)
246    addi gp, gp, %lo(_gp)
247
248    /*
249     * Search through the bit list stored in r24(et) to find the first enabled
250     * bit. The offset of this bit is the index of the interrupt that is
251     * to be handled.
252     */
253
254    mov r4, zero
2556:
256    andi r3, r24, 1
257    bne r3, zero, 7f
258    addi r4, r4, 1
259    srli r24, r24, 1
260    br 6b
2617:
262
263    /*
264     * Having located the interrupt source, r4 contains the index of the
265     * interrupt to be handled. r5, the 2nd argument to the function,
266     * will point to the CPU_Interrupt_frame.
267     */
268
269    mov     r5, sp
270#endif
271       
272    .extern __ISR_Handler
273    call    __ISR_Handler
274
275    /*
276     * Now that the interrupt processing is complete, prepare to return to
277     * the interrupted code.
278     */
279
280    /*
281     * Restore the saved registers, so that all general purpose registers
282     * have been restored to their state at the time the interrupt occured.
283     */
284
285    ldw r1,   0(sp)
286    ldw r2,   4(sp)
287    ldw r3,   8(sp)
288    ldw r4,  12(sp)
289    ldw r5,  16(sp)
290    ldw r6,  20(sp)
291    ldw r7,  24(sp)
292    ldw r8,  28(sp)
293    ldw r9,  32(sp)
294    ldw r10, 36(sp)
295    ldw r11, 40(sp)
296    ldw r12, 44(sp)
297    ldw r13, 48(sp)
298    ldw r14, 52(sp)
299    ldw r15, 56(sp)
300    ldw ra,  60(sp)
301    ldw gp,  64(sp)
302
303    /* Disable interrupts */
304    wrctl status, r0
305
306    /* Restore the exception registers */
307
308    /* load saved ea into ea */
309    ldw ea,  72(sp)
310    /* load saved estatus into et */
311    ldw et,  68(sp)
312    /* Always have interrupts enabled when we return from interrupt */
313    ori et, et, 1
314    wrctl estatus, et
315    /* Restore the stack pointer */
316    addi sp, sp, 76
317
318    /*
319     * Return to the interrupted instruction.
320     */
321    eret
322
323
Note: See TracBrowser for help on using the repository browser.