source: rtems/c/src/lib/libbsp/mips/genmongoosev/irq/vectorisrs.c @ 8536b67

4.115
Last change on this file since 8536b67 was 8536b67, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 8, 2014 at 8:06:52 PM

Move Mongoose-V specific devices into BSP.

Putting the duart in libcpu was very optimistic and presumptuous.
It has never been used again on another SoC and is BSP specific.

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