source: rtems/c/src/lib/libbsp/mips/shared/irq/exception.S @ 03b7789

4.115
Last change on this file since 03b7789 was 03b7789, checked in by Sebastian Huber <sebastian.huber@…>, on 04/26/14 at 13:09:10

score: Statically initialize _ISR_Vector_table

  • Property mode set to 100644
File size: 15.3 KB
Line 
1/*  exception.S
2 *
3 *  This file contains a customized MIPS exception handler.
4 *  It hooks into the exception handler present in the resident
5 *  PMON debug monitor.
6 *
7 *  Author: Bruce Robinson
8 *
9 *  This code was derived from cpu_asm.S with the following copyright:
10 *
11 *  COPYRIGHT (c) 1996 by Transition Networks Inc.
12 *
13 *  To anyone who acknowledges that this file is provided "AS IS"
14 *  without any express or implied warranty:
15 *      permission to use, copy, modify, and distribute this file
16 *      for any purpose is hereby granted without fee, provided that
17 *      the above copyright notice and this notice appears in all
18 *      copies, and that the name of Transition Networks not be used in
19 *      advertising or publicity pertaining to distribution of the
20 *      software without specific, written prior permission.
21 *      Transition Networks makes no representations about the suitability
22 *      of this software for any purpose.
23 *
24 *  Derived from c/src/exec/score/cpu/no_cpu/cpu_asm.s:
25 *
26 *  COPYRIGHT (c) 1989-2010.
27 *  On-Line Applications Research Corporation (OAR).
28 *
29 *  The license and distribution terms for this file may be
30 *  found in the file LICENSE in this distribution or at
31 *  http://www.rtems.org/license/LICENSE.
32 */
33
34#include <bspopts.h>
35#include <rtems/asm.h>
36#include <rtems/score/percpu.h>
37#include <rtems/mips/iregdef.h>
38#include <rtems/mips/idtcpu.h>
39#if BSP_HAS_USC320
40  #include <usc.h>
41#endif
42
43#if __mips == 3
44/* 64 bit register operations */
45#define NOP     nop
46#define ADD     dadd
47#define STREG   sd
48#define LDREG   ld
49#define ADDU    addu
50#define ADDIU   addiu
51#define STREGC1 sdc1
52#define LDREGC1 ldc1
53#define R_SZ    8
54#define F_SZ    8
55#define SZ_INT  8
56#define SZ_INT_POW2 3
57
58/* XXX if we don't always want 64 bit register ops, then another ifdef */
59
60#elif __mips == 1
61/* 32 bit register operations*/
62#define NOP     nop
63#define ADD     add
64#define STREG   sw
65#define LDREG   lw
66#define ADDU    add
67#define ADDIU   addi
68#define STREGC1 swc1
69#define LDREGC1 lwc1
70#define R_SZ    4
71#define F_SZ    4
72#define SZ_INT  4
73#define SZ_INT_POW2 2
74#else
75#error "mips assembly: what size registers do I deal with?"
76#endif
77
78
79#define ISR_VEC_SIZE    4
80#define EXCP_STACK_SIZE (NREGS*R_SZ)
81
82
83#ifdef __GNUC__
84#define EXTERN(x,size) .extern x,size
85#else
86#define EXTERN(x,size)
87#endif
88
89
90.extern _Thread_Dispatch
91
92/*  void __ISR_Handler()
93 *
94 *  This routine provides the RTEMS interrupt management.
95 *
96 */
97
98#if 0
99void _ISR_Handler()
100{
101   /*
102    *  This discussion ignores a lot of the ugly details in a real
103    *  implementation such as saving enough registers/state to be
104    *  able to do something real.  Keep in mind that the goal is
105    *  to invoke a user's ISR handler which is written in C and
106    *  uses a certain set of registers.
107    *
108    *  Also note that the exact order is to a large extent flexible.
109    *  Hardware will dictate a sequence for a certain subset of
110    *  _ISR_Handler while requirements for setting
111    */
112
113  /*
114   *  At entry to "common" _ISR_Handler, the vector number must be
115   *  available.  On some CPUs the hardware puts either the vector
116   *  number or the offset into the vector table for this ISR in a
117   *  known place.  If the hardware does not give us this information,
118   *  then the assembly portion of RTEMS for this port will contain
119   *  a set of distinct interrupt entry points which somehow place
120   *  the vector number in a known place (which is safe if another
121   *  interrupt nests this one) and branches to _ISR_Handler.
122   *
123   */
124#endif
125FRAME(bsp_ISR_Handler,sp,0,ra)
126        .set noreorder
127
128#if 0
129/* Activate TX49xx PIO19 signal for diagnostics */
130        lui     k0,0xff1f
131        ori     k0,k0,0xf500
132        lw      k0,(k0)
133        lui     k1,0x8
134        or      k1,k1,k0
135        lui     k0,0xff1f
136        ori     k0,k0,0xf500
137        sw      k1,(k0)
138#endif
139        mfc0 k0,C0_CAUSE        /* Determine if an interrupt generated this exception */
140        nop
141        and k1,k0,CAUSE_EXCMASK
142        beq k1,zero,_chk_int    /* If so, branch to service here */
143        nop
144        la  k0,_int_esr_link    /* Otherwise, jump to next exception handler in PMON exception chain */
145        lw  k0,(k0)
146        lw  k0,4(k0)
147        j   k0
148        nop
149_chk_int:
150        mfc0 k1,C0_SR
151        nop
152        and k0,k1
153#if HAS_RM52xx
154        and k0,CAUSE_IPMASK
155#elif HAS_TX49xx
156        and k0,(SR_IBIT1 | SR_IBIT2 | SR_IBIT3)
157#endif
158        /* external interrupt not enabled, ignore */
159        beq k0,zero,_ISR_Handler_quick_exit
160        nop
161
162/* For debugging interrupts, clear EXL to allow breakpoints */
163#if 0
164        MFC0    k0, C0_SR
165#if __mips == 3
166        li      k1,SR_EXL       /* Clear EXL and Set IE to enable interrupts */
167        not     k1
168        and     k0,k1
169        li      k1,SR_IE
170#elif __mips == 1
171        li      k1,SR_IEC
172#endif
173        or      k0, k1
174        mtc0    k0, C0_SR
175        NOP
176#endif
177
178
179  /*
180   *  save some or all context on stack
181   *  may need to save some special interrupt information for exit
182   */
183
184        /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */
185
186        /* wastes a lot of stack space for context?? */
187        ADDIU    sp,sp,-EXCP_STACK_SIZE
188
189        STREG ra, R_RA*R_SZ(sp)  /* store ra on the stack */
190        STREG v0, R_V0*R_SZ(sp)
191        STREG v1, R_V1*R_SZ(sp)
192        STREG a0, R_A0*R_SZ(sp)
193        STREG a1, R_A1*R_SZ(sp)
194        STREG a2, R_A2*R_SZ(sp)
195        STREG a3, R_A3*R_SZ(sp)
196        STREG t0, R_T0*R_SZ(sp)
197        STREG t1, R_T1*R_SZ(sp)
198        STREG t2, R_T2*R_SZ(sp)
199        STREG t3, R_T3*R_SZ(sp)
200        STREG t4, R_T4*R_SZ(sp)
201        STREG t5, R_T5*R_SZ(sp)
202        STREG t6, R_T6*R_SZ(sp)
203        STREG t7, R_T7*R_SZ(sp)
204        mflo  t0
205        STREG t8, R_T8*R_SZ(sp)
206        STREG t0, R_MDLO*R_SZ(sp)
207        STREG t9, R_T9*R_SZ(sp)
208        mfhi  t0
209        STREG gp, R_GP*R_SZ(sp)
210        STREG t0, R_MDHI*R_SZ(sp)
211        STREG fp, R_FP*R_SZ(sp)
212
213        .set noat
214        STREG AT, R_AT*R_SZ(sp)
215        .set at
216
217        mfc0     t0,C0_SR
218        dmfc0    t1,C0_EPC
219        STREG    t0,R_SR*R_SZ(sp)
220        STREG    t1,R_EPC*R_SZ(sp)
221
222  /*
223   *
224   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
225   *    if ( _ISR_Nest_level == 0 )
226   *      switch to software interrupt stack
227   *  #endif
228   */
229
230  /*
231   *  _ISR_Nest_level++;
232   */
233        lw      t0,ISR_NEST_LEVEL
234        NOP
235        add     t0,t0,1
236        sw      t0,ISR_NEST_LEVEL
237  /*
238   *  _Thread_Dispatch_disable_level++;
239   */
240        lw      t1,THREAD_DISPATCH_DISABLE_LEVEL
241        NOP
242        add     t1,t1,1
243        sw      t1,THREAD_DISPATCH_DISABLE_LEVEL
244
245        /* DEBUG - Add the following code to disable interrupts and clear
246         *         EXL in status register, this will allow memory
247         *         exceptions to occur while servicing the current interrupt
248         */
249#if 0
250        /* Disable interrupts from internal interrupt controller */
251        li t0,~CAUSE_IP2_MASK
252        mfc0 t1,C0_SR
253        nop
254        and t1,t0
255        mtc0 t1,C0_SR
256        nop
257        /* Clear EXL in status register to allow memory exceptions to occur */
258        li t0,~SR_EXL
259        mfc0 t1,C0_SR
260        nop
261        and t1,t0
262        mtc0 t1,C0_SR
263        nop
264#endif
265
266  /*
267   *  Call the CPU model or BSP specific routine to decode the
268   *  interrupt source and actually vector to device ISR handlers.
269   */
270        move     a0,sp
271        jal      mips_vector_isr_handlers
272        NOP
273
274        /* Add the following code to disable interrupts (see DEBUG above) */
275#if 0
276        li t0,SR_EXL            /* Set EXL to hold off interrupts */
277        mfc0 t1,C0_SR
278        nop
279        or t1,t0
280        mtc0 t1,C0_SR
281        nop
282        /* Enable interrupts from internal interrupt controller */
283        li t0,CAUSE_IP2_MASK
284        mfc0 t1,C0_SR
285        nop
286        or t1,t0
287        mtc0 t1,C0_SR
288        nop
289#endif
290
291_ISR_Handler_cleanup:
292
293  /*
294   *  --_ISR_Nest_level;
295   */
296        lw      t2,ISR_NEST_LEVEL
297        NOP
298        add     t2,t2,-1
299        sw      t2,ISR_NEST_LEVEL
300  /*
301   *  --_Thread_Dispatch_disable_level;
302   */
303        lw      t1,THREAD_DISPATCH_DISABLE_LEVEL
304        NOP
305        add     t1,t1,-1
306        sw      t1,THREAD_DISPATCH_DISABLE_LEVEL
307  /*
308   *  if ( _Thread_Dispatch_disable_level || _ISR_Nest_level )
309   *    goto the label "exit interrupt (simple case)"
310   */
311        or  t0,t2,t1
312        bne t0,zero,_ISR_Handler_exit
313        NOP
314
315
316  /*
317   *  #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
318   *    restore stack
319   *  #endif
320   *
321   *  if ( !_Thread_Dispatch_necessary )
322   *    goto the label "exit interrupt (simple case)"
323   */
324        lb      t0,DISPATCH_NEEDED
325        NOP
326        or      t0,t0,t0
327        beq     t0,zero,_ISR_Handler_exit
328        NOP
329
330/*
331** Turn on interrupts before entering Thread_Dispatch which
332** will run for a while, thus allowing new interrupts to
333** be serviced.  Observe the Thread_Dispatch_disable_level interlock
334** that prevents recursive entry into Thread_Dispatch.
335*/
336
337        mfc0    t0, C0_SR
338#if __mips == 3
339        li      t1,SR_EXL       /* Clear EXL and Set IE to enable interrupts */
340        not     t1
341        and     t0,t1
342        li      t1,SR_IE
343#elif __mips == 1
344        li      t1,SR_IEC
345#endif
346        or      t0, t1
347        mtc0    t0, C0_SR
348        NOP
349
350        /* save off our stack frame so the context switcher can get to it */
351        la      t0,__exceptionStackFrame
352        STREG   sp,(t0)
353
354        jal     _Thread_Dispatch
355        NOP
356
357        /* and make sure its clear in case we didn't dispatch.  if we did, its
358        ** already cleared */
359        la      t0,__exceptionStackFrame
360        STREG   zero,(t0)
361        NOP
362
363/*
364** turn interrupts back off while we restore context so
365** a badly timed interrupt won't accidentally mess things up
366*/
367        mfc0    t0, C0_SR
368#if __mips == 3
369        li      t1,SR_IE                /* Clear IE first (recommended) */
370        not     t1
371        and     t0,t1
372        mtc0    t0, C0_SR
373        li      t1,SR_EXL | SR_IE       /* Set EXL and IE, this puts status register bits back to interrupted state */
374        or      t0,t1
375#elif __mips == 1
376        /* ints off, current & prev kernel mode on (kernel mode enabled is bit clear..argh!) */
377        li      t1,SR_IEC | SR_KUP | SR_KUC
378        not     t1
379        and     t0, t1
380#endif
381        mtc0    t0, C0_SR
382        NOP
383
384  /*
385   *  prepare to get out of interrupt
386   *  return from interrupt  (maybe to _ISR_Dispatch)
387   *
388   *  LABEL "exit interrupt (simple case):"
389   *  prepare to get out of interrupt
390   *  return from interrupt
391   */
392
393_ISR_Handler_exit:
394
395/* restore interrupt context from stack */
396        LDREG t8, R_MDLO*R_SZ(sp)
397        LDREG t0, R_T0*R_SZ(sp)
398        mtlo  t8
399        LDREG t8, R_MDHI*R_SZ(sp)
400        LDREG t1, R_T1*R_SZ(sp)
401        mthi  t8
402        LDREG t2, R_T2*R_SZ(sp)
403        LDREG t3, R_T3*R_SZ(sp)
404        LDREG t4, R_T4*R_SZ(sp)
405        LDREG t5, R_T5*R_SZ(sp)
406        LDREG t6, R_T6*R_SZ(sp)
407        LDREG t7, R_T7*R_SZ(sp)
408        LDREG t8, R_T8*R_SZ(sp)
409        LDREG t9, R_T9*R_SZ(sp)
410        LDREG gp, R_GP*R_SZ(sp)
411        LDREG fp, R_FP*R_SZ(sp)
412        LDREG ra, R_RA*R_SZ(sp)
413        LDREG a0, R_A0*R_SZ(sp)
414        LDREG a1, R_A1*R_SZ(sp)
415        LDREG a2, R_A2*R_SZ(sp)
416        LDREG a3, R_A3*R_SZ(sp)
417        LDREG v1, R_V1*R_SZ(sp)
418        LDREG v0, R_V0*R_SZ(sp)
419
420        LDREG k1, R_EPC*R_SZ(sp)
421        mtc0  k1,C0_EPC
422
423        .set noat
424        LDREG     AT, R_AT*R_SZ(sp)
425        .set at
426
427        ADDIU     sp,sp,EXCP_STACK_SIZE
428
429_ISR_Handler_quick_exit:
430        eret
431        nop
432
433
434#if BSP_HAS_USC320
435        /* Interrupts from USC320 are serviced here */
436        .global USC_isr
437        .extern Clock_isr
438USC_isr:
439        /* check if it's a USC320 heartbeat interrupt */
440        la      k0,INT_STAT     /* read INT_STAT register */
441        lw      k0,(k0)
442        nop                     /* reading from external device */
443        sll     k0,(31-21)      /* test bit 21 (HBI) */
444
445        bgez    k0,USC_isr2     /* branch if not a heartbeat interrupt */
446        NOP
447
448        /* clear the heartbeat interrupt */
449        la      k0,INT_STAT
450        li      t0,HBI_MASK
451        sw      t0,(k0)
452        /* wait for interrupt to clear */
453USC_isr1:
454        la      k0,INT_STAT     /* read INT_STAT register */
455        lw      k0,(k0)
456        nop                     /* reading from external device */
457        sll     k0,(31-21)      /* test bit 21 (HBI) */
458        bltz    k0,USC_isr1     /* branch if bit set */
459        nop
460        j       Clock_isr       /* Jump to clock isr */
461        nop
462USC_isr2:
463        j       ra              /* no serviceable interrupt, return without doing anything */
464        nop
465#endif
466
467#if 0
468        .global int7_isr
469        .extern Interrupt_7_isr
470int7_isr:
471        /* Verify interrupt is from Timer */
472        la      k0,IRCS         /* read Interrupt Current Status register */
473        lw      k0,(k0)
474        nop                     /* reading from external device */
475        li      k1,IRCS_CAUSE_MASK
476        and     k0,k0,k1        /* isolate interrupt cause  */
477
478        li      k1,INT7INT      /* test for interrupt 7 */
479        subu    k1,k0,k1
480        beq     k1,zero,int7_isr1
481        nop
482        j       ra              /* interrupt 7 no longer valid, return without doing anything */
483        nop
484int7_isr1:
485        j       Interrupt_7_isr /* Jump to Interrupt 7 isr */
486        nop
487#endif
488
489       .set    reorder
490
491ENDFRAME(bsp_ISR_Handler)
492
493
494FRAME(_BRK_Handler,sp,0,ra)
495        .set noreorder
496
497#if BSP_HAS_USC320
498        la      k0,INT_CFG3     /* Disable heartbeat interrupt in USC320, it interferes with PMON exception handler */
499        lw      k1,(k0)
500        li      k0,~HBI_MASK
501        and     k1,k1,k0
502        la      k0,INT_CFG3
503        sw      k1,(k0)
504#endif
505
506        la  k0,_brk_esr_link    /* Jump to next exception handler in PMON exception chain */
507        lw  k0,(k0)
508        lw  k0,4(k0)
509        j   k0
510        nop
511
512        .set reorder
513ENDFRAME(_BRK_Handler)
514
515
516/**************************************************************************
517**
518**      init_exc_vecs() - moves the exception code into the addresses
519**                        reserved for exception vectors
520**
521**      UTLB Miss exception vector at address 0x80000000
522**
523**      General exception vector at address 0x80000080
524**
525**      RESET exception vector is at address 0xbfc00000
526**
527***************************************************************************/
528
529FRAME(init_exc_vecs,sp,0,ra)
530        .set noreorder
531
532        .extern mon_onintr
533
534/* Install interrupt handler in PMON exception handling chain */
535
536        addiu   sp,sp,-8
537        sw      ra,(sp)                 /* Save ra contents on stack */
538        move    a0,zero
539        la      a1,_int_esr_link
540        jal     mon_onintr              /* Make PMON system call to install interrupt exception handler */
541        nop
542        li      a0,9
543        la      a1,_brk_esr_link
544        jal     mon_onintr              /* Make PMON system call to install break exception handler */
545        nop
546        lw      ra,(sp)
547        addiu   sp,sp,8                 /* Restore ra contents from stack */
548        j       ra
549        nop
550
551        .set reorder
552ENDFRAME(init_exc_vecs)
553
554
555#if 0           /* Unused code below */
556
557/*************************************************************
558*  enable_int7(ints)
559*       Enable interrupt 7
560*/
561FRAME(enable_int7,sp,0,ra)
562        .set noreorder
563
564        la      t0,IRDM1        # Set interrupt controller detection mode (bits 2-3 = 0 for int 7 active low)
565        li      t1,0x0
566        sw      t1,(t0)
567
568        la      t0,IRLVL4       # Set interrupt controller level (bit 8-10 = 2 for int 7 at level 2)
569        li      t1,0x200
570        sw      t1,(t0)
571
572        la      t0,IRMSK        # Set interrupt controller mask
573        li      t1,0x0
574        sw      t1,(t0)
575
576        la      t0,IRDEN        # Enable interrupts from controller
577        li      t1,0x1
578        sw      t1,(t0)
579
580        j       ra
581        nop
582        .set reorder
583ENDFRAME(enable_int7)
584
585/*************************************************************
586*  disable_int7(ints)
587*       Disable interrupt 7
588*/
589FRAME(disable_int7,sp,0,ra)
590        .set noreorder
591
592        la      t0,IRLVL4       # Set interrupt controller level (bit 8-10 = 0 to diasble int 7)
593        li      t1,0x200
594        sw      t1,(t0)
595
596        j       ra
597        nop
598        .set reorder
599ENDFRAME(disable_int7)
600#endif
601
602/*************************************************************
603*  exception:
604*       Diagnostic code that can be hooked to PMON interrupt handler.
605*       Generates pulse on PIO22 pin.
606*       Called from _exception code in PMON (see mips.s of PMON).
607*       Return address is located in k1.
608*/
609FRAME(tx49xxexception,sp,0,ra)
610        .set noreorder
611        la      k0,k1tmp
612        sw      k1,(k0)
613
614/* Activate TX49xx PIO22 signal for diagnostics */
615        lui     k0,0xff1f
616        ori     k0,k0,0xf500
617        lw      k0,(k0)
618        lui     k1,0x40
619        or      k1,k1,k0
620        lui     k0,0xff1f
621        ori     k0,k0,0xf500
622        sw      k1,(k0)
623        nop
624
625/* De-activate TX49xx PIO22 signal for diagnostics */
626        lui     k0,0xff1f
627        ori     k0,k0,0xf500
628        lw      k0,(k0)
629        lui     k1,0x40
630        not     k1
631        and     k1,k1,k0
632        lui     k0,0xff1f
633        ori     k0,k0,0xf500
634        sw      k1,(k0)
635        nop
636
637        la      k0,k1tmp
638        lw      k1,(k0)
639        j       k1
640        .set reorder
641ENDFRAME(tx49xxexception)
642
643
644
645
646        .data
647
648k1tmp:  .word   0       /* Temporary strage for K1 during interrupt service */
649
650/*************************************************************
651*
652* Exception handler links, used in PMON exception handler chains
653*/
654        /* Interrupt exception service routine link */
655        .global _int_esr_link
656_int_esr_link:
657        .word   0
658        .word   bsp_ISR_Handler
659
660        /* Break exception service routine link */
661        .global _brk_esr_link
662_brk_esr_link:
663        .word   0
664        .word   _BRK_Handler
665
666
667
668
Note: See TracBrowser for help on using the repository browser.