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

📄 intarchlib.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
* written in C, thus it also wraps your ISR in minimal register save/restore* codes.  However if you need a very fast response time to a particular* interrupt request, you might want to skip this register save/restore* sequence by directly attaching your ISR to the corresponding vector table* entry using intVecSet().  Note that this technique is only applicable to* an interrupt service with NO VxWorks system call.  For example it is not* allowed to use semGive() or logMsg() in the interrupt service routine which* is directly attached to vector table by intVecSet().  To facilitate the* direct usage of intVecSet() by user, a special entry point to exit an* interrupt context is provided within the SH77XX version of VxWorks kernel.* This entry point is located at address (vbr + intRte1W), here the intRte1W* is a global symbol for the vbr offset of the entry point in 16 bit length.* This entry point `intRte1' assumes that the current register bank is 0* (SR.RB == 0), and r1 and r0 are still saved on the interrupt stack, and* it also requires 0x70000000 in r0. Then `intRte1' properly cleans up the* interrupt stack and executes <rte> instruction to return to the previous* interrupt or task context.  The following code is an example of `intRte1'* usage.  Here the corresponding intPrioTable[] entry is assumed to be* 0x400000X0, namely MD=1, RB=0, BL=0 at the beginning of `usrIsr1'.**.CS*	.text*	.align	2*	.global	_usrIsr1*	.type	_usrIsr1,@function*	.extern	_usrRtn*	.extern intRte1W*				/@ intPrioTable[] sets SR to 0x400000X0 @/* _usrIsr1:*	mov.l	r0,@-sp		/@ must save r0 first (BANK0) @/*	mov.l	r1,@-sp		/@ must save r1 second (BANK0) @/**	mov.l	r2,@-sp		/@ save rest of volatile registers (BANK0) @/*	mov.l	r3,@-sp*	mov.l	r4,@-sp*	mov.l	r5,@-sp*	mov.l	r6,@-sp*	mov.l	r7,@-sp*	sts.l	pr,@-sp*	sts.l	mach,@-sp*	sts.l	macl,@-sp**	mov.l	UsrRtn,r0*	jsr	@r0		/@ call user's C routine @/*	nop			/@ (delay slot) @/**	lds.l	@sp+,macl	/@ restore volatile registers (BANK0) @/*	lds.l	@sp+,mach*	lds.l	@sp+,pr*	mov.l	@sp+,r7*	mov.l	@sp+,r6*	mov.l	@sp+,r5*	mov.l	@sp+,r4*	mov.l	@sp+,r3*	mov.l	@sp+,r2*				/@ intRte1 restores r1 and r0 @/*	mov.l	IntRte1W,r1*	mov.w	@r1,r0*	stc	vbr,r1*	add	r0,r1*	mov.l	IntRteSR,r0	/@ r0: 0x70000000 @/*	jmp	@r1		/@ let intRte1 clean up stack, then rte @/*	nop			/@ (delay slot) @/**		.align	2* UsrRtn:	.long	_usrRtn		/@ user's C routine @/* IntRteSR:	.long	0x70000000	/@ MD=1, RB=1, BL=1 @/* IntRte1W:	.long	intRte1W* .CE** The `intRte1' sets r0 to status register (SR: 0x70000000), to safely restore* SPC/SSR and to clean up the interrupt stack.  Note that TLB mishit exception* immediately reboots CPU while SR.BL=1.  To avoid this fatal condition, VxWorks* loads the `intRte1' code and the interrupt stack to a physical address space* (P1) where no TLB mishit happens.** Furthermore, there is another special entry point called `intRte2' at an* address (vbr + intRte2W).  The `intRte2' assumes that SR is already set to* 0x70000000 (MD: 1, RB: 1, BL: 1), then it does not restore r1 and r0.* While SR value is 0x70000000, you may use r0,r1,r2,r3 in BANK1 as volatile* registers.  The rest of BANK1 registers (r4,r5,r6,r7) are non-volatile, so* if you need to use them then you have to preserve their original values by* saving/restoring them on the interrupt stack.  So, if you need the ultimate* interrupt response time, you may set the corresponding intPrioTable[] entry* to NULL and manage your interrupt service only with r0,r1,r2,r3 in BANK1* as shown in the next sample code:** .CS*	.text*	.global  _usrIsr2*	.type    _usrIsr2,@function*	.extern  _usrIntCnt	/@ interrupt counter @/*	.extern  intRte2W*	.align   2*				/@ MD=1, RB=1, BL=1, since SR is not @/*				/@ substituted from intPrioTable[].  @/* _usrIsr2:*	mov.l	UsrIntAck,r1*	mov	#0x1,r0*	mov.b	r0,@r1		/@ acknowledge interrupt @/**	mov.l	UsrIntCnt,r1*	mov.l	X1FFFFFFF,r2*	mov.l	X80000000,r3*	and	r2,r1*	or	r3,r1		/@ r1: _usrIntCnt address in P1 @/*	mov.l	@r1,r0*	add	#1,r0*	mov.l	r0,@r1		/@ increment counter @/**	mov.l	IntRte2W,r1*	and	r2,r1*	or	r3,r1		/@ r1: intRte2W address in P1 @/*	mov.w	@r1,r0*	stc	vbr,r1*	add	r1,r0*	jmp	@r0		/@ let intRte2 clean up stack, then rte @/*	nop			/@ (delay slot) @/**		.align	2* UsrIntAck:	.long	0xa0001234	/@ interrupt acknowledge register @/* UsrIntCnt:	.long	_usrIntCnt* IntRte2W:	.long	intRte2W* X1FFFFFFF:	.long	0x1fffffff* X80000000:	.long	0x80000000* .CE** Note that the entire interrupt service is executed under SR.BL=1 in this* sample code.  It means that any access to virtual address space may reboot* CPU, since TLB mishit exception is blocked.  Therefore `usrIsr2' has to* access `usrIntCnt' and `intRte2W' from P1 region.  Also `usrIsr2' itself* has to be executed on P1 region, and it can be done by relocating the address* of `usrIsr2' to P1 as shown below:** .CS* IMPORT void usrIsr2 (void);** intVecSet (vector, (FUNCPTR)(((UINT32)usrIsr2 & 0x1fffffff) | 0x80000000));* .CE** In conclusion, you have to guarantee that the entire ISR does not access to* any virtual address space if you set the corresponding intPrioTable[] entry* to NULL.* * NOTE SIMNT:* This routine does nothing.** RETURNS: N/A** SEE ALSO: intVecBaseSet(), intVecGet()*/void intVecSet    (    FUNCPTR *	vector,		/* vector offset              */    FUNCPTR	function	/* address to place in vector */    )    {    ...    }/********************************************************************************* intVecGet - get an interrupt vector (MC680x0, x86, MIPS, SH, SimSolaris, SimNT)** This routine returns a pointer to the exception/interrupt handler attached* 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).** 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 I960:* \"The interrupt table location is reinitialized to <sysIntTable> after* \"booting.  This location is returned by intVecBaseGet().* \"* NOTE SIMNT:* This routine does nothing and always returns 0.** RETURNS:* A pointer to the exception/interrupt handler attached to the specified vector.** SEE ALSO: intVecSet(), intVecBaseSet()*/FUNCPTR intVecGet    (    FUNCPTR *  vector     /* vector offset */    )    {    ...    }/********************************************************************************* intVecTableWriteProtect - write-protect exception vector table (MC680x0, x86, ARM, SimSolaris, SimNT)** If the unbundled Memory Management Unit (MMU) support package (VxVMI) is* present, this routine write-protects the exception vector table to* protect it from being accidentally corrupted.** Note that other data structures contained in the page will also be * write-protected.  In the default VxWorks configuration, the exception vector* table is located at location 0 in memory.  Write-protecting this affects* the backplane anchor, boot configuration information, and potentially the* text segment (assuming the default text location of 0x1000.)  All code* that manipulates these structures has been modified to write-enable * memory for the duration of the operation.  If you select a different* address for the exception vector table, be sure it resides in a page* separate from other writable data structures.** NOTE SIMSOLARIS, SIMNT:* This routine always returns ERROR on simulators.** RETURNS: OK, or ERROR if memory cannot be write-protected.** ERRNO: S_intLib_VEC_TABLE_WP_UNAVAILABLE*/STATUS intVecTableWriteProtect (void)    {    ...    }/********************************************************************************* intUninitVecSet - set the uninitialized vector handler (ARM)** This routine installs a handler for the uninitialized vectors to be* called when any uninitialised vector is entered.** RETURNS: N/A.*/void intUninitVecSet    (    VOIDFUNCPTR routine /* ptr to user routine */    )    {    ...    }/********************************************************************************* intHandlerCreateI86 - construct an interrupt handler for a C routine (x86)** This routine builds an interrupt handler around a 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.** IMPLEMENTATION:* This routine builds an interrupt handler of the following form in* allocated memory:** .CS* 00  e8 kk kk kk kk		call	_intEnt		* tell kernel* 05  50			pushl	%eax		* save regs* 06  52			pushl	%edx* 07  51			pushl	%ecx* 08  68 pp pp pp pp		pushl	$_parameterBoi	* push BOI param* 13  e8 rr rr rr rr		call	_routineBoi	* call BOI routine* 18  68 pp pp pp pp		pushl	$_parameter	* push param* 23  e8 rr rr rr rr		call	_routine	* call C routine* 28  68 pp pp pp pp		pushl	$_parameterEoi	* push EOI param* 33  e8 rr rr rr rr		call	_routineEoi	* call EOI routine* 38  83 c4 0c			addl	$12, %esp	* pop param* 41  59			popl	%ecx		* restore regs* 42  5a			popl	%edx* 43  58			popl	%eax* 44  e9 kk kk kk kk		jmp	_intExit	* exit via kernel* .CE* * Third and fourth parameter of intHandlerCreateI86() are the BOI routine * address and its parameter that are inserted into the code as "routineBoi" * and "parameterBoi". * Fifth and sixth parameter of intHandlerCreateI86() are the EOI routine * address and its parameter that are inserted into the code as "routineEoi" * and "parameterEoi". * The BOI routine detects if this interrupt is stray/spurious/phantom by* interrogating the interrupt controller, and returns from the interrupt* if it is.  The EOI routine issues End Of Interrupt signal to the * interrupt controller, if it is required by the controller.  * Each interrupt controller has its own BOI and EOI routine.  They are* located in the BSP, and their address and parameter are taken by the* intEoiGet function (set to sysIntEoiGet() in the BSP).* The Tornado 2, and later, BSPs should use the BOI and EOI mechanism with* intEoiGet function pointer.** To keep the Tornado 101 BSP backward compatible, the function pointer * intEOI is not removed.  If intEoiGet is NULL, it should be set to the* sysIntEoiGet() routine in the BSP, intHandlerCreate() and the intEOI * function pointer (set to sysIntEOI() in the Tornado 101 BSP) is used.* * RETURNS: A pointer to the new interrupt handler, or NULL if memory* is insufficient.*/FUNCPTR intHandlerCreateI86    (    FUNCPTR routine,		/* routine to be called              */    int parameter,		/* parameter to be passed to routine */    FUNCPTR routineBoi,		/* BOI routine to be called          */    int parameterBoi,		/* parameter to be passed to routineBoi */    FUNCPTR routineEoi,		/* EOI routine to be called          */    int parameterEoi		/* parameter to be passed to routineEoi */    )    {    ...    }/******************************************************************************** intVecSet2 - set a CPU vector, gate type(int/trap), and selector (x86)** This routine attaches an exception handler to a specified vector,* with the type of the gate and the selector of the gate.  * The vector is specified as an offset into the CPU's vector table.  This* vector table starts, by default, at address 0.  * However, the vector table may be set to start at any address with* intVecBaseSet().  The vector table is set up in usrInit().** RETURNS: N/A** SEE ALSO: intVecBaseSet(), intVecGet(), intVecSet(), intVecGet2()*/void intVecSet2    (    FUNCPTR * vector,		/* vector offset              */    FUNCPTR function,		/* address to place in vector */    int idtGate,		/* IDT_TRAP_GATE or IDT_INT_GATE */    int idtSelector		/* sysCsExc or sysCsInt */    )    {    ...    }/******************************************************************************** intVecGet2 - get a CPU vector, gate type(int/trap), and gate selector (x86)** This routine gets a pointer to the exception/interrupt handler attached* to a specified vector, the type of the gate, the selector of the gate.  * The vector is specified as an offset into the CPU's vector table.  * This vector table starts, by default, at address 0.* However, the vector table may be set to start at any address with* intVecBaseSet().** RETURNS: N/A** SEE ALSO: intVecBaseSet(), intVecGet(), intVecSet(), intVecSet2()*/void intVecGet2    (    FUNCPTR * vector,		/* vector offset              */    FUNCPTR * pFunction,	/* address to place in vector */    int *     pIdtGate,		/* IDT_TRAP_GATE or IDT_INT_GATE */    int *     pIdtSelector	/* sysCsExc or sysCsInt */    )    {    ...    }/********************************************************************************* intStackEnable - enable or disable the interrupt stack usage (x86)** This routine enables or disables the interrupt stack usage and is only * callable from the task level. An Error is returned for any other calling * context. The interrupt stack usage is disabled in the default configuration* for the backward compatibility.  Routines that manipulate the interrupt* stack, are located in the file i86/windALib.s. These routines include* intStackEnable(), intEnt() and intExit().** RETURNS: OK, or ERROR if it is not in the task level.*/STATUS intStackEnable     (    BOOL enable		/* TRUE to enable, FALSE to disable */    )    {    ...    }

⌨️ 快捷键说明

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