📄 windalib.s
字号:
/* windALib.s - internal VxWorks kernel assembly library *//* Copyright 1996-2002 Wind River Systems, Inc. *//*modification history--------------------01m,16jan02,to add context switch for _fpStatus01l,17oct01,t_m convert to FUNC_LABEL:01k,11oct01,jb Enabling removal of pre-pended underscores for new compilers (Diab/Gnu elf)01j,13nov98,cdp add big-endian support; make Thumb support dependent on ARM_THUMB; optimise for no instrumentation.01i,02sep98,cjtc port to windView 2.001h,31jul98,pr temporarily commentig out WindView code01g,24nov97,cdp fix ARM7TDMI_T call to workQAdd1 (WindView instrumentation).01f,28oct97,cdp correct WindView instrumentation code, remove "EOF", tidy.01e,09oct97,cdp WindView fixes from Paola Rossaro (incorrect extern); tidy up.01d,23sep97,cdp removed kludges for old Thumb tool-chains.01c,16apr97,cdp added (Thumb) ARM7TDMI_T support; added WindView support.01b,05feb97,cdp Fix return from windExit().01a,09may96,cdp written, based (loosely) on 68K version*//*DESCRIPTIONThis module contains internals to the VxWorks kernel.These routines have been coded in assembler because they are eitherspecific to this processor, or they have been optimized for performance.*/#define _ASMLANGUAGE#include "vxWorks.h"#include "private/taskLibP.h"#include "private/workQLibP.h"#include "private/eventP.h" .data .globl FUNC(copyright_wind_river) .long FUNC(copyright_wind_river) /* globals */ .globl VAR(_fpStatus) .globl FUNC(windExit) /* routine to exit mutual exclusion */ .globl FUNC(windIntStackSet) /* interrupt stack set routine */#ifdef PORTABLE .globl FUNC(windLoadContext) /* needed by portable reschedule () */#else .globl FUNC(reschedule) /* optimized reschedule () routine */#endif /* PORTABLE */ /* externs */ .extern FUNC(workQIsEmpty) .extern FUNC(workQDoWork) .extern FUNC(kernelState) .extern FUNC(intCnt) .extern FUNC(taskIdCurrent) .extern FUNC(readyQHead) .extern FUNC(errno)#ifdef PORTABLE .extern FUNC(reschedule)#else .extern FUNC(kernelIsIdle) .extern FUNC(taskSwapTable) .extern FUNC(taskSwitchTable)#endif /* PORTABLE */ .extern FUNC(exit)#ifdef WV_INSTRUMENTATION .extern FUNC(evtAction) .extern FUNC(wvEvtClass) .extern FUNC(trgEvtClass) .extern FUNC(_func_evtLogT0) .extern FUNC(_func_evtLogTSched) .extern FUNC(_func_trgCheck)#endif /* WV_INSTRUMENTATION */#if (ARM_THUMB) .extern FUNC(arm_call_via_r2) .extern FUNC(arm_call_via_r12)#endif /* (ARM_THUMB) */ /* variables */ .data .balign 4VAR_LABEL(_fpStatus) .long 0 .text .balign 4 .code 32/* PC-relative-addressable pointers - LDR Rn,=sym is broken */L$__fpStatus: .long VAR(_fpStatus)L$_workQIsEmpty: .long FUNC(workQIsEmpty)L$_kernelState: .long FUNC(kernelState) L$_intCnt: .long FUNC(intCnt)L$_taskIdCurrent: .long FUNC(taskIdCurrent)L$_readyQHead: .long FUNC(readyQHead)L$_errno: .long FUNC(errno)#if (ARM_THUMB)L$_workQDoWork: .long FUNC(workQDoWork)#endif /* (ARM_THUMB) */#ifdef WV_INSTRUMENTATION L$_evtAction: .long FUNC(evtAction)L$_wvEvtClass: .long FUNC(wvEvtClass) L$_trgEvtClass: .long FUNC(trgEvtClass) L$__func_evtLogT0: .long FUNC(_func_evtLogT0) L$__func_evtLogTSched: .long FUNC(_func_evtLogTSched)L$__func_trgCheck: .long FUNC(_func_trgCheck)#endif /* WV_INSTRUMENTATION */#ifndef PORTABLEL$_kernelIsIdle: .long FUNC(kernelIsIdle)L$_taskSwapTable: .long FUNC(taskSwapTable)L$_taskSwitchTable: .long FUNC(taskSwitchTable)#endif /* !PORTABLE *//********************************************************************************* windExitInt - exit kernel routine from interrupt level** windExit branches here if exiting kernel routine from int level* No rescheduling is necessary because the ISR will exit via intExit, and* intExit does the necessary rescheduling. Before leaving kernel state* the work queue is emptied.** REGISTERS* Exit: r0 = 0*/windExitInt: /* save interrupt state and link */ STMFD sp!, {r4,lr} /* save v1 and link */ MRS r4, cpsrwindExitIntLoop: /* * disable interrupts * r4 = CPSR */ ORR r0, r4, #I_BIT MSR cpsr, r0 /* * INTERRUPTS DISABLED * * see if workQ is empty */ LDR r0, L$_workQIsEmpty LDR r0, [r0] TEQS r0, #0 BNE windExitIntNoWork /* branch if empty */ /* * work to do * restore interrupt state * r4 = previous CPSR */ MSR cpsr, r4 /* * INTERRUPTS ENABLED * * call a C routine to empty the workQ */#if (ARM_THUMB) LDR r12, L$_workQDoWork /* empty workQ (r4 preserved) */ BL FUNC(arm_call_via_r12) /* returns in ARM state */#else BL FUNC(workQDoWork) /* empty workQ (r4 preserved) */#endif /* (ARM_THUMB) */ B windExitIntLoop /* NEVER FALL THROUGH */windExitIntNoWork: /* workQ is empty */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * exit windExit with no dispatch; point 1 in the windExit diagram. */ LDR lr, L$_evtAction /* is event logging or triggering? */ LDR lr, [lr] TEQS lr, #0 BNE instrumentDispatch1 /* branch if so */ /* instrumentation currently disabled */resumeDispatch1: /* windview instrumentation - END */#endif /* WV_INSTRUMENTATION */ /* exit kernelState */ LDR lr, L$_kernelState MOV r0, #0 STR r0, [lr] /* * restore interrupt state and return OK * r0 = 0 */ MSR cpsr, r4 /* INTERRUPTS ENABLED */#if (ARM_THUMB) LDMFD sp!, {r4,lr} BX lr#else LDMFD sp!, {r4,pc}#endif /* (ARM_THUMB) *//******************************************************************************/#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * exit windExit with no dispatch; point 1 in the windExit diagram. */instrumentDispatch1: LDR lr, L$_wvEvtClass /* is instrumentation on? */ LDR lr, [lr] AND lr, lr, #WV_CLASS_1_ON TEQS lr, #WV_CLASS_1_ON BNE trgInst1 /* branch if not */ /* * try to determine if the task is running at an inherited priority * and log a different event if so */ LDR r12, L$_taskIdCurrent LDR r12, [r12] /* r12 -> TCB */ LDR r1, [r12, #WIND_TCB_PRIORITY] LDR r2, [r12, #WIND_TCB_PRI_NORMAL] CMPS r2, r1 MOVHI r0, #EVENT_WIND_EXIT_NODISPATCH_PI MOVLS r0, #EVENT_WIND_EXIT_NODISPATCH LDR r12, L$__func_evtLogTSched /* get address of fn pointer */#if (ARM_THUMB) LDR r12, [r12] /* get function address */ BL FUNC(arm_call_via_r12) /* and call it */#else MOV lr, pc /* call function */ LDR pc, [r12]#endif /* (ARM_THUMB) */trgInst1: LDR lr, L$_trgEvtClass /* is triggering on? */ LDR lr, [lr] AND lr, lr,#TRG_CLASS_1_ON TEQS lr, #TRG_CLASS_1_ON BNE resumeDispatch1 /* branch if not */ /* * There are 8 parameters to the trgCheck function: * r0 <- eventId * r1 <- index = TRG_CLASS1_INDEX * r2 <- obj (NULL) * r3 <- arg1 (NULL - unused) * stack <- arg2 (NULL - unused) * stack <- arg3 (NULL - unused) * stack <- arg4 (NULL - unused) * stack <- arg5 (NULL - unused) */ MOV r3, #0 /* NULL parms for stack */ MOV r2, #0 MOV r1, #0 MOV r0, #0 STMFD sp!, {r0-r3} /* push stack-based parms */ /* * try to determine if the task is running at an inherited priority * and log a different event if so */ LDR r12, L$_taskIdCurrent LDR r12, [r12] /* r12 -> TCB */ LDR r0, [r12, #WIND_TCB_PRIORITY] LDR r1, [r12, #WIND_TCB_PRI_NORMAL] CMPS r1, r0 MOVHI r0, #EVENT_WIND_EXIT_NODISPATCH_PI MOVLS r0, #EVENT_WIND_EXIT_NODISPATCH /* r0 <- eventId */ MOV r1, #TRG_CLASS1_INDEX /* r1 <- TRG_CLASS1_INDEX */ /* r2 <- NULL (from above) */ /* r3 <- NULL (from above) */ LDR r12,L$__func_trgCheck /* trigCheck routine */#if (ARM_THUMB) LDR r12, [r12] /* get function address */ BL FUNC(arm_call_via_r12) /* and call it */#else MOV lr, pc /* call function */ LDR pc, [r12]#endif /* (ARM_THUMB) */ ADD sp, sp, #16 /* strip 4 parameters from stack */ B resumeDispatch1 /* windview instrumentation - END */#endif /* WV_INSTRUMENTATION *//********************************************************************************* checkTaskReady - check that taskIdCurrent is ready to run** This code branched to by windExit when it finds preemption is disabled.* It is possible that even though preemption is disabled, a context switch* must occur. This situation arises when a task blocks during a preemption* lock. So this routine checks if taskIdCurrent is ready to run, if not it* branches to save the context of taskIdCurrent, otherwise it falls thru to* check the work queue for any pending work.** REGISTERS* r0 -> TCB*/checkTaskReady: LDR r1, [r0, #WIND_TCB_STATUS] /* is task ready to run? */ TEQS r1, #WIND_READY BNE saveTaskContext /* if no, go and reschedule */ /* * task is ready to run * * FALL THROUGH TO checkWorkQ *//********************************************************************************* checkWorkQ - check the work queue for any work to do** This code is branched to by windExit. Currently taskIdCurrent is highest* priority ready task, but before we can return to it we must check the work* queue. If there is work we empty it via doWorkPreSave, otherwise we unlock* interrupts, clear r0, and return to taskIdCurrent.** REGISTERS* r0 scratch* lr = link*/checkWorkQ: /* disable interrupts */ MRS r0, cpsr ORR r0, r0, #I_BIT MSR cpsr, r0 /* INTERRUPTS DISABLED */ LDR r0, L$_workQIsEmpty LDR r0, [r0] TEQS r0, #0 /* empty? */ BEQ doWorkPreSave /* branch if not */ /* workQ is empty */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * exit windExit with no dispatch; point 4 in the windExit diagram. */ LDR r0, L$_evtAction /* is event logging or triggering? */ LDR r0, [r0] TEQS r0, #0 BNE instrumentDispatch4 /* branch if so */ /* instrumentation currently disabled */resumeDispatch4: /* windview instrumentation - END */#endif /* WV_INSTRUMENTATION */ /* release exclusion */ STMFD sp!, {lr} LDR lr, L$_kernelState MOV r0, #0 STR r0, [lr] /* enable interrupts */ MRS r0, cpsr BIC r0, r0, #I_BIT MSR cpsr, r0 /* * INTERRUPTS ENABLED
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -