forked from Imagelibrary/rtems
2001-02-01 Greg Menke <gregory.menke@gsfc.nasa.gov>
* 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.
This commit is contained in:
@@ -1,3 +1,19 @@
|
||||
2001-02-01 Greg Menke <gregory.menke@gsfc.nasa.gov>
|
||||
|
||||
* 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.
|
||||
|
||||
2002-01-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||
|
||||
* mongoosev/vectorisrs/vectorisrs.c: Include rtems/bspIo.h instead of bspIo.h.
|
||||
|
||||
@@ -4,3 +4,57 @@
|
||||
|
||||
The Synova Mongoose-V is a radiation hardened derivative of the
|
||||
LSI 33K with on-CPU peripherals.
|
||||
|
||||
Status
|
||||
======
|
||||
|
||||
Per-task floating point enable/disable is supported for both immediate
|
||||
and deferred FPU context swaps.
|
||||
|
||||
Interrupt Levels are adapted reasonably well to the MIPS interrupt
|
||||
model. Bit 0 of the int level is a global enable/disable, corresponding
|
||||
to bit 0 of the processor's SR register. Bits 1 thru 6 are configured
|
||||
as masks for the Int0 thru Int5 interrupts. The 2 software interrupt
|
||||
bits are always enabled by default. Each task maintains its own
|
||||
Interrupt Level setting, reconfiguring the SR register's interrupt bits
|
||||
whenever scheduled in. The software ints, though not addressable via
|
||||
the various Interrupt Level functions, are maintained on a per-task
|
||||
basis, so if software manipulates them directly, things should behave as
|
||||
expected. At the time of these udpates, the Interrupt Level was only 8
|
||||
bits, and completely supporting the global enable, software ints and the
|
||||
hardware ints would require 9 bits. When more than 8 bits are
|
||||
available, there is no reason the software interrupts could not be added
|
||||
to the Interrupt Level.
|
||||
|
||||
While supporting the Int0 thru Int5 bits in this way doesn't seem
|
||||
wonderfully useful, it does increase the level of compliance with the
|
||||
RTEMS spec.
|
||||
|
||||
Interrupt Level 0 corresponds to interrupts globally enabled, software
|
||||
ints enabled and Int0 thru Int5 enabled. If values other than 0 are
|
||||
supplied, they should be formulated to impose the desired bitmask.
|
||||
Interrupt priority is not a strong concept on this bsp, it is provided
|
||||
only by the order in which interrupts are checked.
|
||||
|
||||
If during the vectoring of an interrupt, others arrive, they will all be
|
||||
processed in accordance with their ordering in SR & the peripheral
|
||||
register. For example, if while we're vectoring Int4, Int3 and Int5 are
|
||||
asserted, Int3 will be serviced before Int5. The peripheral interrupts
|
||||
are individually vectored as a consequence of Int5 being asserted,
|
||||
however Int5 is not itself vectored. Within the set of peripheral
|
||||
interrupts, bit 0 is vectored first, 31 is last.
|
||||
|
||||
Interrupts are not nested for MIPS1 or MIPS3 processors, but are
|
||||
processed serially as possible. On an unloaded 50 task RTEMS program,
|
||||
runnning on a 12mhz MIPS1 processor, worst-case latencies of 100us were
|
||||
observed, the average being down at 60us or below.
|
||||
|
||||
|
||||
These features are principally a consequence of fixes and tweaks to the
|
||||
MIPS1 and MIPS3 processor support, and should be equally effective on
|
||||
both levels of MIPS processors for any of their bsp's.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -98,19 +98,19 @@
|
||||
(MONGOOSEV_UART_CMD_PARITY_ODD << MONGOOSEV_UART0_CMD_SHIFT)
|
||||
|
||||
#define MONGOOSEV_UART_CMD_TX_ENABLE_1 \
|
||||
(MONGOOSEV_UART_CMD_TX_ENABLE << MONGOOSEV_UART0_CMD_SHIFT)
|
||||
(MONGOOSEV_UART_CMD_TX_ENABLE << MONGOOSEV_UART1_CMD_SHIFT)
|
||||
#define MONGOOSEV_UART_CMD_RX_ENABLE_1 \
|
||||
(MONGOOSEV_UART_CMD_RX_ENABLE << MONGOOSEV_UART0_CMD_SHIFT)
|
||||
(MONGOOSEV_UART_CMD_RX_ENABLE << MONGOOSEV_UART1_CMD_SHIFT)
|
||||
#define MONGOOSEV_UART_CMD_TX_READY_1 \
|
||||
(MONGOOSEV_UART_CMD_TX_READY << MONGOOSEV_UART0_CMD_SHIFT)
|
||||
(MONGOOSEV_UART_CMD_TX_READY << MONGOOSEV_UART1_CMD_SHIFT)
|
||||
#define MONGOOSEV_UART_CMD_PARITY_ENABLE_1 \
|
||||
(MONGOOSEV_UART_CMD_PARITY_ENABLE << MONGOOSEV_UART0_CMD_SHIFT)
|
||||
(MONGOOSEV_UART_CMD_PARITY_ENABLE << MONGOOSEV_UART1_CMD_SHIFT)
|
||||
#define MONGOOSEV_UART_CMD_PARITY_DISABLE_1 \
|
||||
(MONGOOSEV_UART_CMD_PARITY_DISABLE << MONGOOSEV_UART0_CMD_SHIFT)
|
||||
(MONGOOSEV_UART_CMD_PARITY_DISABLE << MONGOOSEV_UART1_CMD_SHIFT)
|
||||
#define MONGOOSEV_UART_CMD_PARITY_EVEN_1 \
|
||||
(MONGOOSEV_UART_CMD_PARITY_EVEN << MONGOOSEV_UART0_CMD_SHIFT)
|
||||
(MONGOOSEV_UART_CMD_PARITY_EVEN << MONGOOSEV_UART1_CMD_SHIFT)
|
||||
#define MONGOOSEV_UART_CMD_PARITY_ODD_1 \
|
||||
(MONGOOSEV_UART_CMD_PARITY_ODD << MONGOOSEV_UART0_CMD_SHIFT)
|
||||
(MONGOOSEV_UART_CMD_PARITY_ODD << MONGOOSEV_UART1_CMD_SHIFT)
|
||||
|
||||
/* UART Bits in Peripheral Status and Interrupt Cause Register */
|
||||
#define MONGOOSEV_UART_RX_FRAME_ERROR 0x0001
|
||||
@@ -131,6 +131,17 @@
|
||||
#define MONGOOSEV_UART0_IRQ_SHIFT 11
|
||||
#define MONGOOSEV_UART1_IRQ_SHIFT 17
|
||||
|
||||
#define MONGOOSEV_UART_FRAME_ERROR_0 \
|
||||
(MONGOOSEV_UART_FRAME_ERROR << MONGOOSEV_UART0_IRQ_SHIFT)
|
||||
#define MONGOOSEV_UART_RX_OVERRUN_ERROR_0 \
|
||||
(MONGOOSEV_UART_RX_OVERRUN_ERROR << MONGOOSEV_UART0_IRQ_SHIFT)
|
||||
#define MONGOOSEV_UART_TX_EMPTY_0 \
|
||||
(MONGOOSEV_UART_TX_EMPTY << MONGOOSEV_UART0_IRQ_SHIFT)
|
||||
#define MONGOOSEV_UART_TX_READY_0 \
|
||||
(MONGOOSEV_UART_TX_READY << MONGOOSEV_UART0_IRQ_SHIFT)
|
||||
#define MONGOOSEV_UART_RX_READY_0 \
|
||||
(MONGOOSEV_UART_RX_READY << MONGOOSEV_UART0_IRQ_SHIFT)
|
||||
|
||||
#define MONGOOSEV_UART_FRAME_ERROR_1 \
|
||||
(MONGOOSEV_UART_FRAME_ERROR << MONGOOSEV_UART1_IRQ_SHIFT)
|
||||
#define MONGOOSEV_UART_RX_OVERRUN_ERROR_1 \
|
||||
@@ -142,17 +153,6 @@
|
||||
#define MONGOOSEV_UART_RX_READY_1 \
|
||||
(MONGOOSEV_UART_RX_READY << MONGOOSEV_UART1_IRQ_SHIFT)
|
||||
|
||||
#define MONGOOSEV_UART_FRAME_ERROR_0 \
|
||||
(MONGOOSEV_UART_FRAME_ERROR << MONGOOSEV_UART1_IRQ_SHIFT)
|
||||
#define MONGOOSEV_UART_RX_OVERRUN_ERROR_0 \
|
||||
(MONGOOSEV_UART_RX_OVERRUN_ERROR << MONGOOSEV_UART1_IRQ_SHIFT)
|
||||
#define MONGOOSEV_UART_TX_EMPTY_0 \
|
||||
(MONGOOSEV_UART_TX_EMPTY << MONGOOSEV_UART1_IRQ_SHIFT)
|
||||
#define MONGOOSEV_UART_TX_READY_0 \
|
||||
(MONGOOSEV_UART_TX_READY << MONGOOSEV_UART1_IRQ_SHIFT)
|
||||
#define MONGOOSEV_UART_RX_READY_0 \
|
||||
(MONGOOSEV_UART_RX_READY << MONGOOSEV_UART1_IRQ_SHIFT)
|
||||
|
||||
/*
|
||||
* Bits in the Peripheral Interrupt Mask Register
|
||||
*/
|
||||
@@ -162,9 +162,9 @@
|
||||
*/
|
||||
#define MONGOOSEV_EDAC_SERR_BIT 0x80000000
|
||||
#define MONGOOSEV_EDAC_MERR_BIT 0x40000000
|
||||
/* 29 - 24 reserved */
|
||||
#define MONGOOSEV_MAVN_WRITE_ACCESS 0x00800000
|
||||
#define MONGOOSEV_MAVN_READ_ACCESS 0x00400000
|
||||
/* 29 - 24 reserved */
|
||||
#define MONGOOSEV_UART_1_RX_READY 0x00200000
|
||||
#define MONGOOSEV_UART_1_TX_READY 0x00100000
|
||||
#define MONGOOSEV_UART_1_TX_EMPTY 0x00080000
|
||||
@@ -189,6 +189,14 @@
|
||||
#define MONGOOSEV_EXTERN_INT_0 0x00000001
|
||||
|
||||
|
||||
/*
|
||||
** Peripheral Command bits (non-uart, those are defined above)
|
||||
*/
|
||||
#define MONGOOSEV_COMMAND_ENABLE_EDAC MONGOOSEV_EDAC_SERR_BIT
|
||||
#define MONGOOSEV_COMMAND_OVERRIDE_EDAC MONGOOSEV_EDAC_MERR_BIT
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* EDAC Registers
|
||||
*/
|
||||
|
||||
@@ -19,122 +19,36 @@
|
||||
#include "idtcpu.h"
|
||||
|
||||
|
||||
#define CALL_ISR(_vector,_frame) \
|
||||
do { \
|
||||
if ( _ISR_Vector_table[_vector] ) \
|
||||
(_ISR_Vector_table[_vector])(_vector,_frame); \
|
||||
else \
|
||||
mips_default_isr(_vector); \
|
||||
} while (0)
|
||||
#include <bspIo.h> /* for printk */
|
||||
|
||||
#include <rtems/bspIo.h> /* for printk */
|
||||
|
||||
void mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
|
||||
|
||||
int mips_default_isr( int vector )
|
||||
{
|
||||
unsigned32 sr, srmaskoff;
|
||||
unsigned32 cause, cshifted;
|
||||
unsigned32 bit;
|
||||
unsigned32 pf_icr;
|
||||
|
||||
/* mips_get_sr( sr ); */
|
||||
sr = frame->regs[ R_SR ];
|
||||
|
||||
mips_get_cause( cause );
|
||||
|
||||
/* mask off everything other than the interrupt bits */
|
||||
cause &= SR_IMASK;
|
||||
|
||||
/* mask off the pending interrupts in the status register */
|
||||
srmaskoff = sr & ~cause;
|
||||
mips_set_sr( srmaskoff );
|
||||
|
||||
/* allow nesting for all non-pending interrupts */
|
||||
asm volatile( "rfe" );
|
||||
|
||||
cshifted = (cause & (sr & SR_IMASK)) >> CAUSE_IPSHIFT;
|
||||
|
||||
if ( cshifted & 0x04 ) /* IP[0] ==> INT0 == TIMER1 */
|
||||
CALL_ISR( MONGOOSEV_IRQ_TIMER1, frame );
|
||||
|
||||
if ( cshifted & 0x08 ) /* IP[1] ==> INT1 == TIMER2*/
|
||||
CALL_ISR( MONGOOSEV_IRQ_TIMER2, frame );
|
||||
|
||||
if ( cshifted & 0x10 ) /* IP[2] ==> INT2 */
|
||||
CALL_ISR( MONGOOSEV_IRQ_INT2, frame );
|
||||
|
||||
if ( cshifted & 0x20 ) /* IP[3] ==> INT3 == FPU interrupt */
|
||||
CALL_ISR( MONGOOSEV_IRQ_INT3, frame );
|
||||
|
||||
if ( cshifted & 0x40 ) /* IP[4] ==> INT4, external interrupt */
|
||||
CALL_ISR( MONGOOSEV_IRQ_INT4, frame );
|
||||
|
||||
if ( cshifted & 0x80 ) /* IP[5] ==> INT5, peripheral interrupt */
|
||||
{
|
||||
pf_icr = MONGOOSEV_READ( MONGOOSEV_PERIPHERAL_FUNCTION_INTERRUPT_CAUSE_REGISTER );
|
||||
|
||||
/* if !pf_icr */
|
||||
for ( bit=0 ; bit <= 31 ; bit++, pf_icr >>= 1 )
|
||||
{
|
||||
if ( pf_icr & 1 )
|
||||
{
|
||||
CALL_ISR( MONGOOSEV_IRQ_PERIPHERAL_BASE + bit, frame );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* all the pending interrupts were serviced, now re-enable them */
|
||||
mips_get_sr( sr );
|
||||
|
||||
/* we allow the 2 software interrupts to nest freely, under the
|
||||
* assumption that the program knows what its doing...
|
||||
*/
|
||||
|
||||
if( cshifted & 0x3 )
|
||||
{
|
||||
sr |= (SR_IBIT1 | SR_IBIT1);
|
||||
cause &= ~(SR_IBIT1 | SR_IBIT1);
|
||||
|
||||
mips_set_cause(cause);
|
||||
mips_set_sr(sr);
|
||||
|
||||
if ( cshifted & 0x01 ) /* SW[0] */
|
||||
{
|
||||
CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_1, frame );
|
||||
}
|
||||
if ( cshifted & 0x02 ) /* SW[1] */
|
||||
{
|
||||
CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_2, frame );
|
||||
}
|
||||
}
|
||||
|
||||
sr |= cause;
|
||||
mips_set_sr( sr );
|
||||
}
|
||||
|
||||
void mips_default_isr( int vector )
|
||||
{
|
||||
unsigned int sr;
|
||||
unsigned int sr, sr2;
|
||||
unsigned int cause;
|
||||
|
||||
mips_get_sr( sr );
|
||||
mips_get_cause( cause );
|
||||
|
||||
printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n",
|
||||
vector, cause, sr );
|
||||
sr2 = sr & ~0xff;
|
||||
mips_set_sr(sr2);
|
||||
|
||||
printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", vector, cause, sr );
|
||||
rtems_fatal_error_occurred(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* userspace routine to assert either software interrupt */
|
||||
|
||||
int assertSoftwareInterrupt( unsigned32 n )
|
||||
{
|
||||
if( n >= 0 && n<2 )
|
||||
if( n<2 )
|
||||
{
|
||||
unsigned32 c;
|
||||
|
||||
mips_get_cause(c);
|
||||
c = ((n+1) << 8);
|
||||
c = ((n+1) << CAUSE_IPSHIFT);
|
||||
mips_set_cause(c);
|
||||
|
||||
return n;
|
||||
@@ -142,3 +56,211 @@ int assertSoftwareInterrupt( unsigned32 n )
|
||||
else return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define CALL_ISR(_vector,_frame) \
|
||||
do { \
|
||||
if( _ISR_Vector_table[_vector] ) \
|
||||
(_ISR_Vector_table[_vector])(_vector,_frame); \
|
||||
else \
|
||||
mips_default_isr(_vector); \
|
||||
} while (0)
|
||||
|
||||
|
||||
//
|
||||
// Instrumentation tweaks for isr timing measurement, turning them off
|
||||
// via this #if will remove the code entirely from the RTEMS kernel.
|
||||
//
|
||||
|
||||
#if 1
|
||||
#define SET_ISR_FLAG( offset ) *((unsigned32 *)(0x8001e000+offset)) = 1;
|
||||
#define CLR_ISR_FLAG( offset ) *((unsigned32 *)(0x8001e000+offset)) = 0;
|
||||
#else
|
||||
#define SET_ISR_FLAG( offset )
|
||||
#define CLR_ISR_FLAG( offset )
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static volatile unsigned32 _ivcause, _ivsr;
|
||||
|
||||
|
||||
static unsigned32 READ_CAUSE(void)
|
||||
{
|
||||
mips_get_cause( _ivcause );
|
||||
_ivcause &= SR_IMASK; // mask off everything other than the interrupt bits
|
||||
|
||||
return ((_ivcause & (_ivsr & SR_IMASK)) >> CAUSE_IPSHIFT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// This rather strangely coded routine enforces an interrupt priority
|
||||
// scheme. As it runs thru finding whichever interrupt caused it to get
|
||||
// here, it test for other interrupts arriving in the meantime (maybe it
|
||||
// occured while the vector code is executing for instance). Each new
|
||||
// interrupt will be served in order of its priority. In an effort to
|
||||
// minimize overhead, the cause register is only fetched after an
|
||||
// interrupt is serviced. Because of the intvect goto's, this routine
|
||||
// will only exit when all interrupts have been serviced and no more
|
||||
// have arrived, this improves interrupt latency at the cost of
|
||||
// increasing scheduling jitter; though scheduling jitter should only
|
||||
// become apparent in high interrupt load conditions.
|
||||
//
|
||||
void mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
|
||||
{
|
||||
unsigned32 cshifted;
|
||||
|
||||
/* mips_get_sr( sr ); */
|
||||
_ivsr = frame->regs[ R_SR ];
|
||||
|
||||
cshifted = READ_CAUSE();
|
||||
|
||||
intvect:
|
||||
|
||||
if( cshifted & 0x3 )
|
||||
{
|
||||
// making the software interrupt the highest priority is kind of
|
||||
// stupid, but it makes the bit testing lots easier. On the other
|
||||
// hand, these ints are infrequently used and the testing overhead
|
||||
// is minimal. Who knows, high-priority software ints might be
|
||||
// handy in some situation.
|
||||
|
||||
/* unset both software int cause bits */
|
||||
mips_set_cause( _ivcause & ~(3 << CAUSE_IPSHIFT) );
|
||||
|
||||
if ( cshifted & 0x01 ) /* SW[0] */
|
||||
{
|
||||
CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_1, frame );
|
||||
}
|
||||
if ( cshifted & 0x02 ) /* SW[1] */
|
||||
{
|
||||
CALL_ISR( MONGOOSEV_IRQ_SOFTWARE_2, frame );
|
||||
}
|
||||
cshifted = READ_CAUSE();
|
||||
}
|
||||
|
||||
|
||||
if ( cshifted & 0x04 ) /* IP[0] ==> INT0 == TIMER1 */
|
||||
{
|
||||
SET_ISR_FLAG( 0x4 );
|
||||
CALL_ISR( MONGOOSEV_IRQ_TIMER1, frame );
|
||||
CLR_ISR_FLAG( 0x4 );
|
||||
if( (cshifted = READ_CAUSE()) & 0x3 ) goto intvect;
|
||||
}
|
||||
|
||||
if ( cshifted & 0x08 ) /* IP[1] ==> INT1 == TIMER2*/
|
||||
{
|
||||
SET_ISR_FLAG( 0x8 );
|
||||
CALL_ISR( MONGOOSEV_IRQ_TIMER2, frame );
|
||||
CLR_ISR_FLAG( 0x8 );
|
||||
if( (cshifted = READ_CAUSE()) & 0x7 ) goto intvect;
|
||||
}
|
||||
|
||||
if ( cshifted & 0x10 ) /* IP[2] ==> INT2 */
|
||||
{
|
||||
SET_ISR_FLAG( 0x10 );
|
||||
CALL_ISR( MONGOOSEV_IRQ_INT2, frame );
|
||||
CLR_ISR_FLAG( 0x10 );
|
||||
if( (cshifted = READ_CAUSE()) & 0xf ) goto intvect;
|
||||
}
|
||||
|
||||
if ( cshifted & 0x20 ) /* IP[3] ==> INT3 == FPU interrupt */
|
||||
{
|
||||
SET_ISR_FLAG( 0x20 );
|
||||
CALL_ISR( MONGOOSEV_IRQ_INT3, frame );
|
||||
CLR_ISR_FLAG( 0x20 );
|
||||
if( (cshifted = READ_CAUSE()) & 0x1f ) goto intvect;
|
||||
}
|
||||
|
||||
if ( cshifted & 0x40 ) /* IP[4] ==> INT4, external interrupt */
|
||||
{
|
||||
SET_ISR_FLAG( 0x40 );
|
||||
CALL_ISR( MONGOOSEV_IRQ_INT4, frame );
|
||||
CLR_ISR_FLAG( 0x40 );
|
||||
if( (cshifted = READ_CAUSE()) & 0x3f ) goto intvect;
|
||||
}
|
||||
|
||||
if ( cshifted & 0x80 ) /* IP[5] ==> INT5, peripheral interrupt */
|
||||
{
|
||||
unsigned32 bit;
|
||||
unsigned32 pf_icr, pf_mask, pf_reset = 0;
|
||||
unsigned32 i, m;
|
||||
|
||||
pf_icr = MONGOOSEV_READ( MONGOOSEV_PERIPHERAL_FUNCTION_INTERRUPT_CAUSE_REGISTER );
|
||||
|
||||
/*
|
||||
for (bit=0, pf_mask = 1; bit < 32; bit++, pf_mask <<= 1 )
|
||||
{
|
||||
if ( pf_icr & pf_mask )
|
||||
{
|
||||
SET_ISR_FLAG( 0x80 + (bit*4) );
|
||||
CALL_ISR( MONGOOSEV_IRQ_PERIPHERAL_BASE + bit, frame );
|
||||
CLR_ISR_FLAG( 0x80 + (bit*4) );
|
||||
pf_reset |= pf_mask;
|
||||
if( (cshifted = READ_CAUSE()) & 0xff ) break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
// iterate thru 32 bits in 4 chunks of 8 bits each. This lets us
|
||||
// quickly get past unasserted interrupts instead of flogging our
|
||||
// way thru a full 32 bits. pf_mask shifts left 8 bits at a time
|
||||
// to serve as a interrupt cause test mask.
|
||||
//
|
||||
for( bit=0, pf_mask = 0xff; (bit < 32 && pf_icr); (bit+=8, pf_mask <<= 8) )
|
||||
{
|
||||
if ( pf_icr & pf_mask )
|
||||
{
|
||||
// one or more of the 8 bits we're testing is high
|
||||
|
||||
m = (1 << bit);
|
||||
|
||||
// iterate thru the 8 bits, servicing any of the interrupts
|
||||
for(i=0; (i<8 && pf_icr); (i++, m <<= 1))
|
||||
{
|
||||
if( pf_icr & m )
|
||||
{
|
||||
SET_ISR_FLAG( 0x80 + ((bit + i) * 4) );
|
||||
CALL_ISR( MONGOOSEV_IRQ_PERIPHERAL_BASE + bit + i, frame );
|
||||
CLR_ISR_FLAG( 0x80 + ((bit + i) * 4) );
|
||||
|
||||
// or each serviced interrupt into our interrupt clear
|
||||
// mask
|
||||
pf_reset |= m;
|
||||
|
||||
// xor off each int we service so we can immediately
|
||||
// exit once we get the last one
|
||||
pf_icr %= m;
|
||||
|
||||
// if another interrupt has arrived, jump out right
|
||||
// away but be sure to reset all the interrupts we've
|
||||
// already serviced
|
||||
//if( READ_CAUSE() & 0xff ) goto pfexit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pfexit:
|
||||
MONGOOSEV_WRITE( MONGOOSEV_PERIPHERAL_STATUS_REGISTER, pf_reset );
|
||||
}
|
||||
|
||||
//
|
||||
// this is a last ditch interrupt check, if an interrupt arrives
|
||||
// after this step, servicing it will incur the entire interrupt
|
||||
// overhead cost.
|
||||
//
|
||||
if( (cshifted = READ_CAUSE()) & 0xff ) goto intvect;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// eof
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "iregdef.h"
|
||||
#include "idtcpu.h"
|
||||
#include <rtems/bspIo.h>
|
||||
#include <bspIo.h>
|
||||
|
||||
char *cause_strings[32] =
|
||||
{
|
||||
@@ -89,6 +89,9 @@ void mips_default_exception_code_handler( int exc, CPU_Interrupt_frame *frame )
|
||||
rtems_fatal_error_occurred(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define CALL_EXC(_vector,_frame) \
|
||||
do { \
|
||||
if ( _ISR_Vector_table[_vector] ) \
|
||||
@@ -97,6 +100,9 @@ void mips_default_exception_code_handler( int exc, CPU_Interrupt_frame *frame )
|
||||
mips_default_exception_code_handler( _vector, _frame ); \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* There are constants defined for these but they should basically
|
||||
* all be close to the same set.
|
||||
|
||||
Reference in New Issue
Block a user