📄 excep.c
字号:
/* '192' set */ { 2, { 7,6,0,0,0,0,0,0 } },
/* '193' set */ { 3, { 7,6,0,0,0,0,0,0 } },
/* '194' set */ { 3, { 7,6,1,0,0,0,0,0 } },
/* '195' set */ { 4, { 7,6,1,0,0,0,0,0 } },
/* '196' set */ { 3, { 7,6,2,0,0,0,0,0 } },
/* '197' set */ { 4, { 7,6,2,0,0,0,0,0 } },
/* '198' set */ { 4, { 7,6,2,1,0,0,0,0 } },
/* '199' set */ { 5, { 7,6,2,1,0,0,0,0 } },
/* '200' set */ { 3, { 7,6,3,0,0,0,0,0 } },
/* '201' set */ { 4, { 7,6,3,0,0,0,0,0 } },
/* '202' set */ { 4, { 7,6,3,1,0,0,0,0 } },
/* '203' set */ { 5, { 7,6,3,1,0,0,0,0 } },
/* '204' set */ { 4, { 7,6,3,2,0,0,0,0 } },
/* '205' set */ { 5, { 7,6,3,2,0,0,0,0 } },
/* '206' set */ { 5, { 7,6,3,2,1,0,0,0 } },
/* '207' set */ { 6, { 7,6,3,2,1,0,0,0 } },
/* '208' set */ { 3, { 7,6,4,0,0,0,0,0 } },
/* '209' set */ { 4, { 7,6,4,0,0,0,0,0 } },
/* '210' set */ { 4, { 7,6,4,1,0,0,0,0 } },
/* '211' set */ { 5, { 7,6,4,1,0,0,0,0 } },
/* '212' set */ { 4, { 7,6,4,2,0,0,0,0 } },
/* '213' set */ { 5, { 7,6,4,2,0,0,0,0 } },
/* '214' set */ { 5, { 7,6,4,2,1,0,0,0 } },
/* '215' set */ { 6, { 7,6,4,2,1,0,0,0 } },
/* '216' set */ { 4, { 7,6,4,3,0,0,0,0 } },
/* '217' set */ { 5, { 7,6,4,3,0,0,0,0 } },
/* '218' set */ { 5, { 7,6,4,3,1,0,0,0 } },
/* '219' set */ { 6, { 7,6,4,3,1,0,0,0 } },
/* '220' set */ { 5, { 7,6,4,3,2,0,0,0 } },
/* '221' set */ { 6, { 7,6,4,3,2,0,0,0 } },
/* '222' set */ { 6, { 7,6,4,3,2,1,0,0 } },
/* '223' set */ { 7, { 7,6,4,3,2,1,0,0 } },
/* '224' set */ { 3, { 7,6,5,0,0,0,0,0 } },
/* '225' set */ { 4, { 7,6,5,0,0,0,0,0 } },
/* '226' set */ { 4, { 7,6,5,1,0,0,0,0 } },
/* '227' set */ { 5, { 7,6,5,1,0,0,0,0 } },
/* '228' set */ { 4, { 7,6,5,2,0,0,0,0 } },
/* '229' set */ { 5, { 7,6,5,2,0,0,0,0 } },
/* '230' set */ { 5, { 7,6,5,2,1,0,0,0 } },
/* '231' set */ { 6, { 7,6,5,2,1,0,0,0 } },
/* '232' set */ { 4, { 7,6,5,3,0,0,0,0 } },
/* '233' set */ { 5, { 7,6,5,3,0,0,0,0 } },
/* '234' set */ { 5, { 7,6,5,3,1,0,0,0 } },
/* '235' set */ { 6, { 7,6,5,3,1,0,0,0 } },
/* '236' set */ { 5, { 7,6,5,3,2,0,0,0 } },
/* '237' set */ { 6, { 7,6,5,3,2,0,0,0 } },
/* '238' set */ { 6, { 7,6,5,3,2,1,0,0 } },
/* '239' set */ { 7, { 7,6,5,3,2,1,0,0 } },
/* '240' set */ { 4, { 7,6,5,4,0,0,0,0 } },
/* '241' set */ { 5, { 7,6,5,4,0,0,0,0 } },
/* '242' set */ { 5, { 7,6,5,4,1,0,0,0 } },
/* '243' set */ { 6, { 7,6,5,4,1,0,0,0 } },
/* '244' set */ { 5, { 7,6,5,4,2,0,0,0 } },
/* '245' set */ { 6, { 7,6,5,4,2,0,0,0 } },
/* '246' set */ { 6, { 7,6,5,4,2,1,0,0 } },
/* '247' set */ { 7, { 7,6,5,4,2,1,0,0 } },
/* '248' set */ { 5, { 7,6,5,4,3,0,0,0 } },
/* '249' set */ { 6, { 7,6,5,4,3,0,0,0 } },
/* '250' set */ { 6, { 7,6,5,4,3,1,0,0 } },
/* '251' set */ { 7, { 7,6,5,4,3,1,0,0 } },
/* '252' set */ { 6, { 7,6,5,4,3,2,0,0 } },
/* '253' set */ { 7, { 7,6,5,4,3,2,0,0 } },
/* '254' set */ { 7, { 7,6,5,4,3,2,1,0 } },
/* '255' set */ { 8, { 7,6,5,4,3,2,1,0 } }
};
/* Textual descriptions of cause codes */
static char *(cause_names[]) =
{
/* C0_CAUSE_CODE_INT */ "Interrupt",
/* C0_CAUSE_CODE_MOD */ "TLB modification",
/* C0_CAUSE_CODE_TLBL */ "TLB (load or instruction fetch)",
/* C0_CAUSE_CODE_TLBS */ "TLB (store)",
/* C0_CAUSE_CODE_ADEL */ "Address error (load or instruction fetch)",
/* C0_CAUSE_CODE_ADES */ "Address error (store)",
/* C0_CAUSE_CODE_IBE */ "Bus error (instruction fetch)",
/* C0_CAUSE_CODE_DBE */ "Bus error (data reference: load or store)",
/* C0_CAUSE_CODE_SYS */ "Syscall",
/* C0_CAUSE_CODE_BP */ "Breakpoint",
/* C0_CAUSE_CODE_RI */ "Reserved instruction",
/* C0_CAUSE_CODE_CPU */ "Coprocessor Unusable",
/* C0_CAUSE_CODE_OV */ "Arithmetic Overflow",
/* C0_CAUSE_CODE_TR */ "Trap",
/* 14 (reserved) */ NULL,
/* C0_CAUSE_CODE_FPE */ "Floating point",
/* 16 */ NULL,
/* 17 */ NULL,
/* 18 */ NULL,
/* 19 */ NULL,
/* 20 */ NULL,
/* 21 */ NULL,
/* 22 */ NULL,
/* C0_CAUSE_CODE_WATCH */ "Reference to WatchHi/WatchLo address",
/* C0_CAUSE_CODE_MCHECK */ "Machine check",
/* 25 */ NULL,
/* 26 */ NULL,
/* 27 */ NULL,
/* 28 */ NULL,
/* 29 */ NULL,
/* 30 */ NULL,
/* 31 */ NULL
};
/* CPU register names */
static const char *(reg_names[]) =
{
"zr", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
#define REG_NAMES_COUNT (sizeof(reg_names)/sizeof(char *))
/************************************************************************
* Static function prototypes
************************************************************************/
static void
exception_sr(
UINT32 exc_code,
bool ejtag);
static void
interrupt_sr( void );
static void
controller_sr(
void *data );
static void
default_handler(
char *msg );
/************************************************************************
* Implementation : Public functions
************************************************************************/
/************************************************************************
*
* EXCEP_init
* Description :
* -------------
*
* Initializes the 'EXCEP' module.
*
* Parameters :
* ------------
*
* None
*
* Return values :
* ---------------
*
* 'OK'(=0)
*
************************************************************************/
INT32
EXCEP_init( void )
{
UINT32 rcode, i, j;
/* Initialize interrupt controller */
arch_excep_init_intctrl(&excep_ic_count, &excep_ic_int);
if( excep_ic_count > MAX_IC ) /* Should not happen */
while(1);
/**** Initialize exception handler structure ****/
/* Initialize specific exception handlers */
for( i = 0; i < MAX_EXCEPTIONS; i++)
{
table.exception[i].handler = NULL;
}
/* Initialize interrupt handler table */
for( i = 0; i < MAX_INTERRUPTS; i++)
{
for( j = 0; j < INT_HANDLERS_PER_LINE; j++)
{
table.interrupt[i].int_handler[j].handler = NULL;
table.interrupt[i].int_handler[j].data = NULL;
}
table.interrupt[i].list_size = 0;
}
/* Initialize interrupt controller handler table */
for( i = 0; i < MAX_IC; i++)
{
for( j = 0; j < CTRL_HANDLERS_PER_LINE; j++)
{
table.controller[i].ctrl_handler[j].handler = NULL;
table.controller[i].ctrl_handler[j].data = NULL;
}
table.controller[i].list_size = 0;
}
/* Initialise remaining entries of the exception handler structure */
table.ejtag.handler = NULL;
table.default_exception.handler = NULL;
table.default_int.handler = NULL;
table.default_ctrl.handler = NULL;
/* Register ESR for interrupt exception */
EXCEP_register_esr( C0_CAUSE_CODE_INT,
FALSE,
interrupt_sr,
NULL,
NULL );
/* Register interrupt control handler if controller is available */
if( excep_ic_count > 0 )
EXCEP_register_cpu_isr( excep_ic_int, controller_sr, NULL, NULL );
/* register low level exception handler */
EXCEP_install_exc_in_ram( 0, exception_sr );
/* Enable interrupts */
sys_enable_int();
}
/************************************************************************
*
* EXCEP_register_esr
* Description :
* -------------
*
* Registers an exception handler, also known as an "Exception Service
* Routine" (ESR) for the specified exception.
*
* Two special exception IDs are defined :
* EXCEP_DEFAULT_HANDLER used for a default handler.
* EXCEP_EJTAG_HANDLER used for EJTAG exceptions.
*
* The default handler is called if no other handler is registered
* for an exception. If no default handler is registered, a static
* (i.e. not registered) "super default" function is invoked.
* This function prints out the registers and halts.
*
* Deregistration of a handler may be be done by calling this function
* with 'handler' set to NULL.
* Handlers can also be deregistered using EXCEP_deregister_esr.
*
* A handler may be registered even if a previously registered
* handler has not been deregistered. In this case the previously
* registered handler is lost.
*
* In case an ESR does not want to handle the exception, it may
* call the return function passed in the 'retfunc' parameter.
*
* Case 1 : 'retfunc' called by ESR registered for the INTERRUPT exception.
*
* We assume an application has registered this ESR and wants
* YAMON to process the (remaining) interrupts.
* So, we call the ESR, which is used by YAMON for handling
* interrupt exceptions, i.e. interrupt_sr().
*
* Case 2 : 'retfunc' called by an ESR registered for a specific
* exception (not INTERRUPT).
*
* Default handling will be done.
*
* Case 3 : 'retfunc' is called by the ESR registered as default handler.
*
* The exception will be handled as though no ESR is registered
* (i.e. the "super default" function is called).
*
* Parameters :
* ------------
*
* 'exception', IN, Exception code (C0_CAUSE_CODE_xxx).
* or EXCEP_DEFAULT_HANDLER for a default handler
* or EXCEP_EJTAG_HANDLER for ejtag exceptions.
* 'raw', IN If TRUE, ESR will get called with registers
* in the state they were when the exception occurred.
* This includes all CP0 registers and CPU registers
* $0..$31, except for k0,k1 ($26,$27).
* 'handler', IN, Function pointer for ESR.
* 'ref', OUT, Handle used for deregistration of handler.
* 'retfunc', OUT, Pointer to function pointer for the return
* function described above.
*
* Return values :
* ---------------
*
* 'OK'(=0)
* 'ERROR_EXCEP_ILLEGAL_EXCEPTION': Exception ID is unknown
*
************************************************************************/
INT32
EXCEP_register_esr(
UINT32 exception, /* Exception identification */
bool raw, /* Pass on unmodified registers */
t_EXCEP_esr handler, /* ESR to be registered */
t_EXCEP_ref *ref, /* OUT : Handle for deregistration */
t_EXCEP_retfunc *retfunc ) /* OUT : Return function */
{
t_EXCEP_handler *h;
if( exception == EXCEP_DEFAULT_HANDLER )
{
h = &table.default_exception;
}
else if( exception == EXCEP_EJTAG_HANDLER )
{
h = &table.ejtag;
}
else if( exception >= MAX_EXCEPTIONS )
{
return ERROR_EXCEP_ILLEGAL_EXCEPTION;
}
else
{
/* Specific exception */
h = &table.exception[exception];
}
/* register/deregister exception handler */
h->handler = handler;
h->raw = raw;
if( ref )
*ref = (t_EXCEP_ref)h;
if( retfunc )
*retfunc = EXCEP_return;
return OK;
}
/************************************************************************
*
* EXCEP_deregister_esr
* Description :
* -------------
*
* Deregisters exception handler
*
* Parameters :
* ------------
*
* 'ref', IN, Handle obtained when calling EXCEP_register_esr
*
* Return values :
* ---------------
*
* 'OK'(=0)
* 'ERROR_EXCEP_ILLEGAL_HANDLER': ref is unknown
*
************************************************************************/
INT32
EXCEP_deregister_esr(
t_EXCEP_ref ref ) /* In : Handle for deregistration */
{
t_EXCEP_handler *h = (t_EXCEP_handler *)ref;
if( h )
{
h->handler = NULL;
return OK;
}
else
return ERROR_EXCEP_ILLEGAL_HANDLER;
}
/************************************************************************
*
* EXCEP_register_cpu_isr
* Description :
* -------------
*
* Registers an interrupt handler for the specified CPU interrupt.
* The highest service priority is attached to HW-INT5, which is
* connected to the CPU-built-in CP0-timer. SW_INT0 gets the lowest
* service priority. During registration, the interrupt mask field
* in the CPU CP0-status register is updated to enable interrupts
* from the specified interrupt source.
*
* A special ID is defined :
* EXCEP_DEFAULT_HANDLER used for a default handler.
*
* The default handler is called if no other handler is registered
* for a CPU interrupt.
*
* Deregistration of the default handler may be done by calling
* this function with 'handler' set to NULL.
* Also, a new default handler may be registered even if a
* previously registered handler has not been deregistered.
* Handlers for specific CPU interrupts must be deregistered using
* EXCEP_deregister_cpu_isr.
*
* Parameters :
* ------------
*
* 'cpu_int', IN, CPU interrupt (C0_STATUS_IM_HW[0..5] |
* C0_STATUS_IM_SW[0..1])
* or EXCEP_DEFAULT_HANDLER for a default handler.
* 'handler', IN, Function pointer for user defined handler
* 'data', IN, Data pointer, may be NULL
* 'ref', OUT, Handle used for deregistration of handler.
*
* Return values :
* ---------------
*
* 'OK'(=0)
* 'ERROR_EXCEP_ILLEGAL_INTERRUPT': CPU interrupt source is unknown
* 'ERROR_EXCEP_ILLEGAL_HANDLER': Handler reference is NULL
* 'ERROR_EXCEP_NO_SPACE': Too many handlers have been registered
*
************************************************************************/
INT32
EXCEP_register_cpu_isr(
UINT32 cpu_int, /* CPU interrupt, 0..7 */
t_EXCEP_isr handler, /* ISR to be registered */
void *data, /* Data reference to be registered */
t_EXCEP_ref *ref ) /* OUT : Handle for deregistration */
{
UINT32 old_ie;
t_INT_handler *h;
UINT32 rc = OK;
UINT32 i;
bool enable = FALSE;
/* Disable interrupts */
old_ie = sys_disable_int();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -