source: rtems/c/src/lib/libbsp/mips/genmongoosev/irq/vectorisrs.c @ 0c0181d

4.115
Last change on this file since 0c0181d was 0c0181d, checked in by Jennifer Averett <jennifer.averett@…>, on 04/04/12 at 13:39:46

PR 1993 - Convert MIPS to PIC IRQ model

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