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>
|
2002-01-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
|
||||||
|
|
||||||
* mongoosev/vectorisrs/vectorisrs.c: Include rtems/bspIo.h instead of bspIo.h.
|
* 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
|
The Synova Mongoose-V is a radiation hardened derivative of the
|
||||||
LSI 33K with on-CPU peripherals.
|
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)
|
(MONGOOSEV_UART_CMD_PARITY_ODD << MONGOOSEV_UART0_CMD_SHIFT)
|
||||||
|
|
||||||
#define MONGOOSEV_UART_CMD_TX_ENABLE_1 \
|
#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 \
|
#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 \
|
#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 \
|
#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 \
|
#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 \
|
#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 \
|
#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 */
|
/* UART Bits in Peripheral Status and Interrupt Cause Register */
|
||||||
#define MONGOOSEV_UART_RX_FRAME_ERROR 0x0001
|
#define MONGOOSEV_UART_RX_FRAME_ERROR 0x0001
|
||||||
@@ -131,6 +131,17 @@
|
|||||||
#define MONGOOSEV_UART0_IRQ_SHIFT 11
|
#define MONGOOSEV_UART0_IRQ_SHIFT 11
|
||||||
#define MONGOOSEV_UART1_IRQ_SHIFT 17
|
#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 \
|
#define MONGOOSEV_UART_FRAME_ERROR_1 \
|
||||||
(MONGOOSEV_UART_FRAME_ERROR << MONGOOSEV_UART1_IRQ_SHIFT)
|
(MONGOOSEV_UART_FRAME_ERROR << MONGOOSEV_UART1_IRQ_SHIFT)
|
||||||
#define MONGOOSEV_UART_RX_OVERRUN_ERROR_1 \
|
#define MONGOOSEV_UART_RX_OVERRUN_ERROR_1 \
|
||||||
@@ -142,17 +153,6 @@
|
|||||||
#define MONGOOSEV_UART_RX_READY_1 \
|
#define MONGOOSEV_UART_RX_READY_1 \
|
||||||
(MONGOOSEV_UART_RX_READY << MONGOOSEV_UART1_IRQ_SHIFT)
|
(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
|
* Bits in the Peripheral Interrupt Mask Register
|
||||||
*/
|
*/
|
||||||
@@ -162,9 +162,9 @@
|
|||||||
*/
|
*/
|
||||||
#define MONGOOSEV_EDAC_SERR_BIT 0x80000000
|
#define MONGOOSEV_EDAC_SERR_BIT 0x80000000
|
||||||
#define MONGOOSEV_EDAC_MERR_BIT 0x40000000
|
#define MONGOOSEV_EDAC_MERR_BIT 0x40000000
|
||||||
|
/* 29 - 24 reserved */
|
||||||
#define MONGOOSEV_MAVN_WRITE_ACCESS 0x00800000
|
#define MONGOOSEV_MAVN_WRITE_ACCESS 0x00800000
|
||||||
#define MONGOOSEV_MAVN_READ_ACCESS 0x00400000
|
#define MONGOOSEV_MAVN_READ_ACCESS 0x00400000
|
||||||
/* 29 - 24 reserved */
|
|
||||||
#define MONGOOSEV_UART_1_RX_READY 0x00200000
|
#define MONGOOSEV_UART_1_RX_READY 0x00200000
|
||||||
#define MONGOOSEV_UART_1_TX_READY 0x00100000
|
#define MONGOOSEV_UART_1_TX_READY 0x00100000
|
||||||
#define MONGOOSEV_UART_1_TX_EMPTY 0x00080000
|
#define MONGOOSEV_UART_1_TX_EMPTY 0x00080000
|
||||||
@@ -189,6 +189,14 @@
|
|||||||
#define MONGOOSEV_EXTERN_INT_0 0x00000001
|
#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
|
* EDAC Registers
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,122 +19,36 @@
|
|||||||
#include "idtcpu.h"
|
#include "idtcpu.h"
|
||||||
|
|
||||||
|
|
||||||
#define CALL_ISR(_vector,_frame) \
|
#include <bspIo.h> /* for printk */
|
||||||
do { \
|
|
||||||
if ( _ISR_Vector_table[_vector] ) \
|
|
||||||
(_ISR_Vector_table[_vector])(_vector,_frame); \
|
|
||||||
else \
|
|
||||||
mips_default_isr(_vector); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#include <rtems/bspIo.h> /* for printk */
|
|
||||||
|
|
||||||
void mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
|
|
||||||
|
int mips_default_isr( int vector )
|
||||||
{
|
{
|
||||||
unsigned32 sr, srmaskoff;
|
unsigned int sr, sr2;
|
||||||
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 cause;
|
unsigned int cause;
|
||||||
|
|
||||||
mips_get_sr( sr );
|
mips_get_sr( sr );
|
||||||
mips_get_cause( cause );
|
mips_get_cause( cause );
|
||||||
|
|
||||||
printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n",
|
sr2 = sr & ~0xff;
|
||||||
vector, cause, sr );
|
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);
|
rtems_fatal_error_occurred(1);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* userspace routine to assert either software interrupt */
|
/* userspace routine to assert either software interrupt */
|
||||||
|
|
||||||
int assertSoftwareInterrupt( unsigned32 n )
|
int assertSoftwareInterrupt( unsigned32 n )
|
||||||
{
|
{
|
||||||
if( n >= 0 && n<2 )
|
if( n<2 )
|
||||||
{
|
{
|
||||||
unsigned32 c;
|
unsigned32 c;
|
||||||
|
|
||||||
mips_get_cause(c);
|
mips_get_cause(c);
|
||||||
c = ((n+1) << 8);
|
c = ((n+1) << CAUSE_IPSHIFT);
|
||||||
mips_set_cause(c);
|
mips_set_cause(c);
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
@@ -142,3 +56,211 @@ int assertSoftwareInterrupt( unsigned32 n )
|
|||||||
else return -1;
|
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 <stdlib.h>
|
||||||
#include "iregdef.h"
|
#include "iregdef.h"
|
||||||
#include "idtcpu.h"
|
#include "idtcpu.h"
|
||||||
#include <rtems/bspIo.h>
|
#include <bspIo.h>
|
||||||
|
|
||||||
char *cause_strings[32] =
|
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);
|
rtems_fatal_error_occurred(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_EXC(_vector,_frame) \
|
#define CALL_EXC(_vector,_frame) \
|
||||||
do { \
|
do { \
|
||||||
if ( _ISR_Vector_table[_vector] ) \
|
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 ); \
|
mips_default_exception_code_handler( _vector, _frame ); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are constants defined for these but they should basically
|
* There are constants defined for these but they should basically
|
||||||
* all be close to the same set.
|
* all be close to the same set.
|
||||||
|
|||||||
Reference in New Issue
Block a user