⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intarchlib.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
* certain operating system functions that may block or perform I/O* operations.** This routine generally simply calls intHandlerCreate() and* intVecSet().  The address of the handler returned by intHandlerCreate()* is what actually goes in the interrupt vector.** This routine takes an interrupt vector as a parameter, which is the byte* offset into the vector table. Macros are provided to convert between interrupt* vectors and interrupt numbers, see `intArchLib'.** NOTE ARM:* ARM processors generally do not have on-chip interrupt controllers.* Control of interrupts is a BSP-specific matter. This routine calls a* BSP-specific routine to install the handler such that, when the* interrupt occurs, <routine> is called with <parameter>.** NOTE X86:* Refer to the special x86 routine intHandlerCreateI86().* * NOTE SH:* The on-chip interrupt controller (INTC) design of SH architecture depends* on the processor type, but there are some similarities.  The number of* external interrupt inputs are limited, so it may necessary to multiplex* some interrupt requests.  However most of them are auto-vectored, thus have* only one vector to an external interrupt input.  As a framework to handle* this type of multiplexed interrupt, you can use your original intConnect* code by hooking it to _func_intConnectHook pointer.  If _func_intConnectHook* is set, the SH version of intConnect() simply calls the hooked routine with* same arguments, then returns the status of hooked routine.  A sysLib sample* is shown below:** .CS* #include "intLib.h"* #include "iv.h"		/@ INUM_INTR_HIGH for SH7750/SH7700 @/** #define SYS_INT_TBL_SIZE	(255 - INUM_INTR_HIGH)** typedef struct*     {*     VOIDFUNCPTR routine;	/@ routine to be called @/*     int         parameter;	/@ parameter to be passed @/*     } SYS_INT_TBL;** LOCAL SYS_INT_TBL sysIntTbl [SYS_INT_TBL_SIZE]; /@ local vector table @/** LOCAL int sysInumVirtBase = INUM_INTR_HIGH + 1;** STATUS sysIntConnect*     (*     VOIDFUNCPTR *vec,		/@ interrupt vector to attach to     @/*     VOIDFUNCPTR routine,	/@ routine to be called              @/*     int         param		/@ parameter to be passed to routine @/*     )*     {*     FUNCPTR intDrvRtn;*  *     if (vec >= INUM_TO_IVEC (0) && vec < INUM_TO_IVEC (sysInumVirtBase))*         {*         /@ do regular intConnect() process @/**         intDrvRtn = intHandlerCreate ((FUNCPTR)routine, param);*  *         if (intDrvRtn == NULL)*             return ERROR;*  *         /@ make vector point to synthesized code @/*  *         intVecSet ((FUNCPTR *)vec, (FUNCPTR)intDrvRtn);*         }*     else*         {*         int index = IVEC_TO_INUM (vec) - sysInumVirtBase;*  *         if (index < 0 || index >= SYS_INT_TBL_SIZE)*             return ERROR;*  *         sysIntTbl [index].routine   = routine;*         sysIntTbl [index].parameter = param;*         }*  *     return OK;*     }** void sysHwInit (void)*     {*     ...*     _func_intConnectHook = (FUNCPTR)sysIntConnect;*     }** LOCAL void sysVmeIntr (void)*     {*     volatile UINT32 vec = *VME_VEC_REGISTER;	/@ get VME interrupt vector @/*     int i = vec - sysInumVirtBase;*  *     if (i >= 0 && i < SYS_INT_TBL_SIZE && sysIntTbl[i].routine != NULL)*         (*sysIntTbl[i].routine)(sysIntTbl[i].parameter);*     else*         logMsg ("uninitialized VME interrupt: vec = %d\n", vec,0,0,0,0,0);*     }** void sysHwInit2 (void)*     {*     int i;*     ...*     /@ initialize VME interrupts dispatch table @/**     for (i = 0; i < SYS_INT_TBL_SIZE; i++)*         {*         sysIntTbl[i].routine   = (VOIDFUNCPTR)NULL;*         sysIntTbl[i].parameter = NULL;*         }**     /@ connect generic VME interrupts handler @/**     intConnect (INT_VEC_VME, sysVmeIntr, NULL);*     ...*     }* .CE** The used vector numbers of SH processors are limited to certain ranges,* depending on the processor type. The `sysInumVirtBase' should be initialized* to a value higher than the last used vector number, defined as INUM_INTR_HIGH.* It is typically safe to set `sysInumVirtBase' to (INUM_INTR_HIGH + 1).** The sysIntConnect() routine simply acts as the regular intConnect() if * <vector> is smaller than INUM_TO_IVEC (sysInumVirtBase), so sysHwInit2() * connects a common VME interrupt dispatcher `sysVmeIntr' to the multiplexed* interrupt vector. If <vector> is equal to or greater than INUM_TO_IVEC * (sysInumVirtBase), the sysIntConnect() fills a local vector entry in * sysIntTbl[] with an individual VME interrupt handler, in a coordinated * manner with `sysVmeIntr'.** RETURNS: OK, or ERROR if the interrupt handler cannot be built.** SEE ALSO: intHandlerCreate(), intVecSet()*/STATUS intConnect    (    VOIDFUNCPTR *  vector,      /* interrupt vector to attach to     */    VOIDFUNCPTR    routine,     /* routine to be called              */    int            parameter    /* parameter to be passed to routine */    )    {    ...    }/********************************************************************************* intHandlerCreate - construct an interrupt handler for a C routine (MC680x0, x86, MIPS, SimSolaris)** This routine builds an interrupt handler around the specified C routine.* This interrupt handler is then suitable for connecting to a specific* vector address with intVecSet().  The interrupt handler is invoked in* supervisor mode at interrupt level.  A proper C environment is* established, the necessary registers saved, and the stack set up.** The routine can be any normal C code, except that it must not invoke* certain operating system functions that may block or perform I/O* operations.** RETURNS: A pointer to the new interrupt handler, or NULL if memory * is insufficient.* */FUNCPTR intHandlerCreate    (    FUNCPTR  routine,     /* routine to be called              */    int      parameter    /* parameter to be passed to routine */    )    {    ...    }/********************************************************************************* intLockLevelSet - set the current interrupt lock-out level (MC680x0, x86, ARM, SH, SimSolaris, SimNT)* * This routine sets the current interrupt lock-out level and stores it* in the globally accessible variable `intLockMask'.  The specified* interrupt level is masked when interrupts are locked by* intLock().  The default lock-out level (MC680x0 = 7,* x86 = 1, SH = 15) is initially set by kernelInit() when* VxWorks is initialized.** NOTE SIMSOLARIS, SIMNT:* This routine does nothing.** NOTE ARM:* On the ARM, this call establishes the interrupt level to be set when* intLock() is called.** RETURNS: N/A* * SEE ALSO: intLockLevelGet(), intLock(), taskLock()*/void intLockLevelSet    (    int  newLevel        /* new interrupt level */    )    {    ...    }/********************************************************************************* intLockLevelGet - get the current interrupt lock-out level (MC680x0, x86, ARM, SH, SimSolaris, SimNT)* * This routine returns the current interrupt lock-out level, which is* set by intLockLevelSet() and stored in the globally accessible* variable `intLockMask'.  This is the interrupt level currently* masked when interrupts are locked out by intLock().  The default* lock-out level (MC680x0 = 7, x86 = 1, SH = 15)* is initially set by kernelInit() when VxWorks is initialized.** NOTE SIMNT:* This routine does nothing.** RETURNS: The interrupt level currently stored in the interrupt* lock-out mask. (ARM = ERROR always)** SEE ALSO: intLockLevelSet()*/int intLockLevelGet (void)    {    ...    }/********************************************************************************* intVecBaseSet - set the vector (trap) base address (MC680x0, x86, MIPS, ARM, SimSolaris, SimNT)** This routine sets the vector (trap) base address.  The CPU's vector base* register is set to the specified value, and subsequent calls to intVecGet()* or intVecSet() will use this base address.  The vector base address is* initially 0, until modified by calls to this routine.** \"NOTE SPARC:* \"On SPARC processors, the vector base address must be on a 4 Kbyte boundary* \"(that is, its bottom 12 bits must be zero).* \"* NOTE 68000:* The 68000 has no vector base register; thus, this routine is a no-op for* 68000 systems.** \"NOTE I960:* \"This routine is a no-op for i960 systems.  The interrupt vector table is* \"located in sysLib, and moving it by intVecBaseSet() would require* \"resetting the processor.  Also, the vector base is cached on-chip in the* \"PRCB and thus cannot be set from this routine.* \"* NOTE MIPS:* The MIPS processors have no vector base register;* thus this routine is a no-op for this architecture.** NOTE SH77XX:* This routine sets <baseAddr> to vbr, then loads an interrupt dispatch* code to (vbr + 0x600).  When SH77XX processor accepts an interrupt request,* it sets an exception code to INTEVT register and jumps to (vbr + 0x600).* Thus this dispatch code is commonly used for all interrupts' handling.** The exception codes are 12bits width, and interleaved by 0x20.  VxWorks* for SH77XX locates a vector table at (vbr + 0x800), and defines the vector* offsets as (exception codes / 8).  This vector table is commonly used by* all interrupts, exceptions, and software traps.** All SH77XX processors have INTEVT register at address 0xffffffd8.  The SH7707* processor has yet another INTEVT2 register at address 0x04000000, to identify* its enhanced interrupt sources.  The dispatch code obtains the address* of INTEVT register from a global constant `intEvtAdrs'.  The constant is* defined in `sysLib', thus the selection of INTEVT/INTEVT2 is configurable* at BSP level.  The `intEvtAdrs' is loaded to (vbr + 4) by intVecBaseSet().** After fetching the exception code, the interrupt dispatch code applies* a new interrupt mask to the status register, and jumps to an individual* interrupt handler.  The new interrupt mask is taken from `intPrioTable[]',* which is defined in `sysALib'.  The `intPrioTable[]' is loaded to* (vbr + 0xc00) by intVecBaseSet().** NOTE ARM:* The ARM processors have no vector base register;* thus this routine is a no-op for this architecture.** NOTE SIMSOLARIS, SIMNT:* This routine does nothing.** RETURNS: N/A** SEE ALSO: intVecBaseGet(), intVecGet(), intVecSet()*/void intVecBaseSet    (    FUNCPTR *  baseAddr     /* new vector (trap) base address */    )    {    ...    }/********************************************************************************* intVecBaseGet - get the vector (trap) base address (MC680x0, x86, MIPS, ARM, SimSolaris, SimNT)** This routine returns the current vector base address, which is set* with intVecBaseSet().** RETURNS: The current vector base address* (MIPS = 0 always, ARM = 0 always, SimSolaris = 0 always and * SimNT = 0 always).** SEE ALSO: intVecBaseSet()*/FUNCPTR *intVecBaseGet (void)    {    ...    }/******************************************************************************** intVecSet - set a CPU vector (trap) (MC680x0, x86, MIPS, SH, SimSolaris, SimNT)** This routine attaches an exception/interrupt/trap handler to a specified * vector.  The vector is specified as an offset into the CPU's vector table. * This vector table starts, by default, at:* * .TS* tab(|);* l l.*     MC680x0:     | 0*     MIPS:        | `excBsrTbl' in excArchLib*     x86:         | 0*     SH702x/SH703x/SH704x/SH76xx: | `excBsrTbl' in excArchLib*     SH77xx:      | vbr + 0x800*     SimSolaris:  | 0* .TE** However, the vector table may be set to start at any address with* intVecBaseSet() (on CPUs for which it is available).  The vector table is* set up in usrInit().** This routine takes an interrupt vector as a parameter, which is the byte* offset into the vector table. Macros are provided to convert between interrupt* vectors and interrupt numbers, see `intArchLib'.** \"NOTE SPARC:* \"This routine generates code to:* \".IP (1) 4* \"save volatile registers;* \".IP (2)* \"fix possible window overflow;* \".IP (3)* \"read the processor state register into register %L0; and * \".IP (4)* \"jump to the specified address.* \".LP* \"* The intVecSet() routine puts this generated code into the trap table* entry corresponding to <vector>.* * Window overflow and window underflow are sacred to* the kernel and may not be pre-empted.  They are written here* only to track changing trap base registers (TBRs).* With the "branch anywhere" scheme (as opposed to the branch PC-relative* +/-8 megabytes) the first instruction in the vector table must not be a * change of flow control nor affect any critical registers.  The JMPL that * replaces the BA will always execute the next vector's first instruction.** \"NOTE I960:* \"Vectors 0-7 are illegal vectors; using them puts the vector into the* \"priorities/pending portion of the table, which yields undesirable* \"actions.  The i960CA caches the NMI vector in internal RAM at system* \"power-up.  This is where the vector is taken when the NMI occurs.  Thus, it* \"is important to check to see if the vector being changed is the NMI* \"vector, and, if so, to write it to internal RAM.* \"* NOTE MIPS:* On MIPS CPUs the vector table is set up statically in software.** NOTE SH77XX:* The specified interrupt handler <function> has to coordinate with an interrupt* stack frame which is specially designed for SH77XX version of VxWorks:**.CS*    [ task's stack ]       [ interrupt stack ]**	|  xxx  | high address*	|  yyy  |		+-------+*	|__zzz__|<--------------|task'sp|  0*	|	|		|INTEVT | -4*	|	| low address	|  ssr  | -8*				|_ spc _| -12 <- sp (non-nested interrupt)*				:	:*				:	:*				:_______:*                               |INTEVT |  0*                               |  ssr  | -4*                               |_ spc _| -8  <- sp (nested interrupt)*                               |       |*.CE** This interrupt stack frame is formed by a common interrupt dispatch code* which is loaded at (vbr + 0x600).  You usually do not have to pay any* attention to this stack frame, since intConnect() automatically appends* an appropriate stack manipulation code to your interrupt service routine.* The intConnect() assumes that your interrupt service routine (ISR) is

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -