source: rtems/c/src/lib/libcpu/mips/mongoosev/vectorisrs/vectorisrs.c @ 2835b3a5

4.104.114.84.95
Last change on this file since 2835b3a5 was 2835b3a5, checked in by Joel Sherrill <joel.sherrill@…>, on 02/01/02 at 15:15:02

2001-02-01 Greg Menke <gregory.menke@…>

  • Lots of tinkering and tuning as part of improving interrupt latency and improving the per-task interrupt level control and FP mask handling. With these modifications interrupt latency was measured at a worst-case of 100us, average below 60 us on a 12 Mhz R3000 class CPU with 50 RTEMS tasks in the application.
  • mongoosev/README: Updated.
  • mongoosev/include/mongoose-v.h: Masks modified.
  • mongoosev/vectorisrs/vectorisrs.c: Significant overhaul to address software prioritization of interrupts. If a higher priority interrupt occurs while we are looking for new interrupts, we will reinitiate the scan of all interrupts.
  • shared/interrupts/vectorexceptions.c: Removed warning and deleted blank lines.
  • 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.OARcorp.com/rtems/license.html.
10 *
11 *  $Id$
12 */
13
14#include <rtems.h>
15#include <stdlib.h>
16#include <libcpu/mongoose-v.h>
17
18#include "iregdef.h"
19#include "idtcpu.h"
20
21
22#include <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 & ~0xff;
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( unsigned32 n )
45{
46   if( n<2 )
47   {
48      unsigned32 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 1
79#define SET_ISR_FLAG( offset )  *((unsigned32 *)(0x8001e000+offset)) = 1;
80#define CLR_ISR_FLAG( offset )  *((unsigned32 *)(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 unsigned32 _ivcause, _ivsr;
92
93
94static unsigned32 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   unsigned32   cshifted;
120
121   /* mips_get_sr( sr ); */
122   _ivsr = frame->regs[ R_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      /* unset both software int cause bits */
137      mips_set_cause( _ivcause & ~(3 << CAUSE_IPSHIFT) );
138
139      if ( cshifted & 0x01 )       /* SW[0] */
140      {
141         CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_1, frame );
142      }
143      if ( cshifted & 0x02 )       /* SW[1] */
144      {
145         CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_2, frame );
146      }
147      cshifted = READ_CAUSE();
148   }
149
150
151   if ( cshifted & 0x04 )       /* IP[0] ==> INT0 == TIMER1 */
152   {
153      SET_ISR_FLAG( 0x4 );
154      CALL_ISR( MONGOOSEV_IRQ_TIMER1, frame );
155      CLR_ISR_FLAG( 0x4 );
156      if( (cshifted = READ_CAUSE()) & 0x3 ) goto intvect;
157   }
158   
159   if ( cshifted & 0x08 )       /* IP[1] ==> INT1 == TIMER2*/
160   {
161      SET_ISR_FLAG( 0x8 );
162      CALL_ISR( MONGOOSEV_IRQ_TIMER2, frame );
163      CLR_ISR_FLAG( 0x8 );
164      if( (cshifted = READ_CAUSE()) & 0x7 ) goto intvect;
165   }
166   
167   if ( cshifted & 0x10 )       /* IP[2] ==> INT2 */
168   {
169      SET_ISR_FLAG( 0x10 );
170      CALL_ISR( MONGOOSEV_IRQ_INT2, frame );
171      CLR_ISR_FLAG( 0x10 );
172      if( (cshifted = READ_CAUSE()) & 0xf ) goto intvect;
173   }
174   
175   if ( cshifted & 0x20 )       /* IP[3] ==> INT3 == FPU interrupt */
176   {
177      SET_ISR_FLAG( 0x20 );
178      CALL_ISR( MONGOOSEV_IRQ_INT3, frame );
179      CLR_ISR_FLAG( 0x20 );
180      if( (cshifted = READ_CAUSE()) & 0x1f ) goto intvect;
181   }
182   
183   if ( cshifted & 0x40 )       /* IP[4] ==> INT4, external interrupt */
184   {
185      SET_ISR_FLAG( 0x40 );
186      CALL_ISR( MONGOOSEV_IRQ_INT4, frame );
187      CLR_ISR_FLAG( 0x40 );
188      if( (cshifted = READ_CAUSE()) & 0x3f ) goto intvect;
189   }
190
191   if ( cshifted & 0x80 )       /* IP[5] ==> INT5, peripheral interrupt */
192   {
193      unsigned32  bit;
194      unsigned32  pf_icr, pf_mask, pf_reset = 0;
195      unsigned32  i, m;
196
197      pf_icr = MONGOOSEV_READ( MONGOOSEV_PERIPHERAL_FUNCTION_INTERRUPT_CAUSE_REGISTER );
198
199/*
200      for (bit=0, pf_mask = 1;    bit < 32;     bit++, pf_mask <<= 1 )
201      {
202         if ( pf_icr & pf_mask )
203         {
204            SET_ISR_FLAG( 0x80 + (bit*4) );
205            CALL_ISR( MONGOOSEV_IRQ_PERIPHERAL_BASE + bit, frame );
206            CLR_ISR_FLAG( 0x80 + (bit*4) );
207            pf_reset |= pf_mask;
208            if( (cshifted = READ_CAUSE()) & 0xff ) break;
209         }
210      }
211*/
212
213      //
214      // iterate thru 32 bits in 4 chunks of 8 bits each.  This lets us
215      // quickly get past unasserted interrupts instead of flogging our
216      // way thru a full 32 bits.  pf_mask shifts left 8 bits at a time
217      // to serve as a interrupt cause test mask.
218      //
219      for( bit=0, pf_mask = 0xff;    (bit < 32 && pf_icr);     (bit+=8, pf_mask <<= 8) )
220      {
221         if ( pf_icr & pf_mask )
222         {
223            // one or more of the 8 bits we're testing is high
224
225            m = (1 << bit);
226
227            // iterate thru the 8 bits, servicing any of the interrupts
228            for(i=0; (i<8 && pf_icr); (i++, m <<= 1))
229            {
230               if( pf_icr & m )
231               {
232                  SET_ISR_FLAG( 0x80 + ((bit + i) * 4) );
233                  CALL_ISR( MONGOOSEV_IRQ_PERIPHERAL_BASE + bit + i, frame );
234                  CLR_ISR_FLAG( 0x80 + ((bit + i) * 4) );
235
236                  // or each serviced interrupt into our interrupt clear
237                  // 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                  pf_icr   %= m;
243
244                  // if another interrupt has arrived, jump out right
245                  // away but be sure to reset all the interrupts we've
246                  // already serviced
247                  //if( READ_CAUSE() & 0xff ) goto pfexit;
248               }
249            }
250         }
251      }
252     pfexit:
253      MONGOOSEV_WRITE( MONGOOSEV_PERIPHERAL_STATUS_REGISTER, pf_reset );
254   }
255
256   //
257   // this is a last ditch interrupt check, if an interrupt arrives
258   // after this step, servicing it will incur the entire interrupt
259   // overhead cost.
260   //
261   if( (cshifted = READ_CAUSE()) & 0xff ) goto intvect;
262}
263
264
265
266// eof
Note: See TracBrowser for help on using the repository browser.