source: rtems/c/src/lib/libcpu/mips/mongoosev/vectorisrs/vectorisrs.c @ 359e537

4.104.115
Last change on this file since 359e537 was 359e537, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/30/09 at 05:09:41

Whitespace removal.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/*
2 *  ISR Vectoring support for the Synova Mongoose-V.
3 *
4 *  COPYRIGHT (c) 1989-2001.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *  $Id$
12 */
13
14#include <rtems.h>
15#include <stdlib.h>
16#include <libcpu/mongoose-v.h>
17
18#include <rtems/mips/iregdef.h>
19#include <rtems/mips/idtcpu.h>
20
21
22#include <rtems/bspIo.h>  /* for printk */
23
24
25
26int mips_default_isr( int vector )
27{
28  unsigned int sr, sr2;
29  unsigned int cause;
30
31  mips_get_sr( sr );
32  mips_get_cause( cause );
33
34  sr2 = sr & ~0xffff;
35  mips_set_sr(sr2);
36
37  printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", vector, cause, sr );
38  rtems_fatal_error_occurred(1);
39  return 0;
40}
41
42/* userspace routine to assert either software interrupt */
43
44int assertSoftwareInterrupt( uint32_t   n )
45{
46   if( n<2 )
47   {
48      uint32_t   c;
49
50      mips_get_cause(c);
51      c = ((n+1) << CAUSE_IPSHIFT);
52      mips_set_cause(c);
53
54      return n;
55   }
56   else return -1;
57}
58
59
60
61
62
63
64#define CALL_ISR(_vector,_frame) \
65  do { \
66    if( _ISR_Vector_table[_vector] ) \
67      (_ISR_Vector_table[_vector])(_vector,_frame); \
68    else \
69      mips_default_isr(_vector); \
70  } while (0)
71
72
73/*
74 * Instrumentation tweaks for isr timing measurement, turning them off
75 * via this #if will remove the code entirely from the RTEMS kernel.
76 */
77
78#if 0
79#define SET_ISR_FLAG( offset )  *((uint32_t*)(0x8001e000+offset)) = 1;
80#define CLR_ISR_FLAG( offset )  *((uint32_t*)(0x8001e000+offset)) = 0;
81#else
82#define SET_ISR_FLAG( offset )
83#define CLR_ISR_FLAG( offset )
84#endif
85
86
87
88
89
90
91static volatile uint32_t   _ivcause, _ivsr;
92
93
94static uint32_t   READ_CAUSE(void)
95{
96   mips_get_cause( _ivcause );
97   _ivcause &= SR_IMASK;        /* mask off everything other than the interrupt bits */
98
99   return ((_ivcause & (_ivsr & SR_IMASK)) >> CAUSE_IPSHIFT);
100}
101
102
103
104/*
105 * This rather strangely coded routine enforces an interrupt priority
106 * scheme.  As it runs thru finding whichever interrupt caused it to get
107 * here, it test for other interrupts arriving in the meantime (maybe it
108 * occured while the vector code is executing for instance).  Each new
109 * interrupt will be served in order of its priority.  In an effort to
110 * minimize overhead, the cause register is only fetched after an
111 * interrupt is serviced.  Because of the intvect goto's, this routine
112 * will only exit when all interrupts have been serviced and no more
113 * have arrived, this improves interrupt latency at the cost of
114 * increasing scheduling jitter; though scheduling jitter should only
115 * become apparent in high interrupt load conditions.
116 */
117void mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
118{
119   uint32_t     cshifted;
120
121   /* mips_get_sr( sr ); */
122   _ivsr = frame->c0_sr;
123
124   cshifted = READ_CAUSE();
125
126  intvect:
127
128   if( cshifted & 0x3 )
129   {
130      /* making the software interrupt the highest priority is kind of
131       * stupid, but it makes the bit testing lots easier.  On the other
132       * hand, these ints are infrequently used and the testing overhead
133       * is minimal.  Who knows, high-priority software ints might be
134       * handy in some situation.
135       */
136
137      /* unset both software int cause bits */
138      mips_set_cause( _ivcause & ~(3 << CAUSE_IPSHIFT) );
139
140      if ( cshifted & 0x01 )       /* SW[0] */
141      {
142         CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_1, frame );
143      }
144      if ( cshifted & 0x02 )       /* SW[1] */
145      {
146         CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_2, frame );
147      }
148      cshifted = READ_CAUSE();
149   }
150
151
152   if ( cshifted & 0x04 )       /* IP[0] ==> INT0 == TIMER1 */
153   {
154      SET_ISR_FLAG( 0x4 );
155      CALL_ISR( MONGOOSEV_IRQ_TIMER1, frame );
156      CLR_ISR_FLAG( 0x4 );
157      if( (cshifted = READ_CAUSE()) & 0x3 ) goto intvect;
158   }
159
160   if ( cshifted & 0x08 )       /* IP[1] ==> INT1 == TIMER2*/
161   {
162      SET_ISR_FLAG( 0x8 );
163      CALL_ISR( MONGOOSEV_IRQ_TIMER2, frame );
164      CLR_ISR_FLAG( 0x8 );
165      if( (cshifted = READ_CAUSE()) & 0x7 ) goto intvect;
166   }
167
168   if ( cshifted & 0x10 )       /* IP[2] ==> INT2 */
169   {
170      SET_ISR_FLAG( 0x10 );
171      CALL_ISR( MONGOOSEV_IRQ_INT2, frame );
172      CLR_ISR_FLAG( 0x10 );
173      if( (cshifted = READ_CAUSE()) & 0xf ) goto intvect;
174   }
175
176   if ( cshifted & 0x20 )       /* IP[3] ==> INT3 == FPU interrupt */
177   {
178      SET_ISR_FLAG( 0x20 );
179      CALL_ISR( MONGOOSEV_IRQ_INT3, frame );
180      CLR_ISR_FLAG( 0x20 );
181      if( (cshifted = READ_CAUSE()) & 0x1f ) goto intvect;
182   }
183
184   if ( cshifted & 0x40 )       /* IP[4] ==> INT4, external interrupt */
185   {
186      SET_ISR_FLAG( 0x40 );
187      CALL_ISR( MONGOOSEV_IRQ_INT4, frame );
188      CLR_ISR_FLAG( 0x40 );
189      if( (cshifted = READ_CAUSE()) & 0x3f ) goto intvect;
190   }
191
192   if ( cshifted & 0x80 )       /* IP[5] ==> INT5, peripheral interrupt */
193   {
194      uint32_t    bit;
195      uint32_t    pf_icr, pf_mask, pf_reset = 0;
196      uint32_t    i, m;
197
198      pf_icr = MONGOOSEV_READ( MONGOOSEV_PERIPHERAL_FUNCTION_INTERRUPT_CAUSE_REGISTER );
199
200/*
201      for (bit=0, pf_mask = 1;    bit < 32;     bit++, pf_mask <<= 1 )
202      {
203         if ( pf_icr & pf_mask )
204         {
205            SET_ISR_FLAG( 0x80 + (bit*4) );
206            CALL_ISR( MONGOOSEV_IRQ_PERIPHERAL_BASE + bit, frame );
207            CLR_ISR_FLAG( 0x80 + (bit*4) );
208            pf_reset |= pf_mask;
209            if( (cshifted = READ_CAUSE()) & 0xff ) break;
210         }
211      }
212*/
213
214      /*
215       * iterate thru 32 bits in 4 chunks of 8 bits each.  This lets us
216       * quickly get past unasserted interrupts instead of flogging our
217       * way thru a full 32 bits.  pf_mask shifts left 8 bits at a time
218       * to serve as a interrupt cause test mask.
219       */
220      for( bit=0, pf_mask = 0xff;    (bit < 32 && pf_icr);     (bit+=8, pf_mask <<= 8) )
221      {
222         if ( pf_icr & pf_mask )
223         {
224            /* one or more of the 8 bits we're testing is high */
225
226            m = (1 << bit);
227
228            /* iterate thru the 8 bits, servicing any of the interrupts */
229            for(i=0; (i<8 && pf_icr); (i++, m <<= 1))
230            {
231               if( pf_icr & m )
232               {
233                  SET_ISR_FLAG( 0x80 + ((bit + i) * 4) );
234                  CALL_ISR( MONGOOSEV_IRQ_PERIPHERAL_BASE + bit + i, frame );
235                  CLR_ISR_FLAG( 0x80 + ((bit + i) * 4) );
236
237                  /* or each serviced interrupt into our interrupt clear mask */
238                  pf_reset |= m;
239
240                  /* xor off each int we service so we can immediately
241                   * exit once we get the last one
242                   */
243                  pf_icr   %= m;
244
245                  /* if another interrupt has arrived, jump out right
246                   * away but be sure to reset all the interrupts we've
247                   * already serviced
248                   */
249                  if( READ_CAUSE() & 0xff ) goto pfexit;
250               }
251            }
252         }
253      }
254     pfexit:
255      MONGOOSEV_WRITE( MONGOOSEV_PERIPHERAL_STATUS_REGISTER, pf_reset );
256   }
257
258   /*
259    * this is a last ditch interrupt check, if an interrupt arrives
260    * after this step, servicing it will incur the entire interrupt
261    * overhead cost.
262    */
263   if( (cshifted = READ_CAUSE()) & 0xff ) goto intvect;
264}
Note: See TracBrowser for help on using the repository browser.