📄 tct.s
字号:
;* CALLS
;*
;* TCT_Control_To_Thread Transfer control to a thread
;*
;* INPUTS
;*
;* TCD_Execute_Task Pointer to task to execute
;*
;* OUTPUTS
;*
;* None
;*
;* HISTORY
;*
;* NAME DATE REMARKS
;*
;* W. Lamie 02-15-1994 Created initial version 1.0
;* D. Lamie 02-15-1994 Verified version 1.0
;*
;************************************************************************
;VOID TCT_Schedule(void)
;{
.def $TCT_Schedule
$TCT_Schedule ; Dual-state interworking veneer
.state16
BX r15
NOP
.state32
B _TCT_Schedule
.def _TCT_Schedule
_TCT_Schedule
; Restore interrupts according to the value contained in
; TCD_Interrupt_Level.
LDR r1,Int_Level ; Build address of interrupt level
MRS r0,CPSR ; Pickup current CPSR
LDR r2,[r1, #0] ; Pickup current interrupt lockout
BIC r0,r0,#LOCK_MSK ; Clear the interrupt lockout bits
ORR r0,r0,r2 ; Build new interrupt lockout CPSR
MSR CPSR,r0 ; Setup new CPSR
LDR r2,Execute_HISR ; Pickup TCD_Execute_HISR address
LDR r3,Execute_Task ; Pickup TCD_Execute_Task address
.if $$isdefed("INCLUDE_PROVIEW")
; Nucleus ProView Hook
; We check if upon entering TCT_Schedule we already have a task to excute.
; if not, we start IDLE.
LDR r0,[r2, #0] ; Pickup highest priority HISR ptr
CMP r0,#0 ; Is there a HISR active?
BNE TCT_Schedule_Thread ; Found an HISR
LDR r0,[r3, #0] ; Pickup highest priority Task ptr
CMP r0,#0 ; Is there a task active?
BNE TCT_Schedule_Thread ; If not, start IDLE.
STR r2,[r13, #-4]! ; Save r2 on the stack
STR r3,[r13, #-4]! ; Save r3 on the stack
BL __NU_Idle_Hook
LDR r3,[r13], #4 ; Recover r2
LDR r2,[r13], #4 ; Recover r3
.endif
; Wait until a thread (task or HISR) is available to execute.
; do
; {
TCT_Schedule_Loop:
; } while ((!TCD_Execute_HISR) && (!TCD_Execute_Task));
LDR r0,[r2, #0] ; Pickup highest priority HISR ptr
CMP r0,#0 ; Is there a HISR active?
BNE TCT_Schedule_Thread ; Found an HISR
LDR r0,[r3, #0] ; Pickup highest priority Task ptr
CMP r0,#0 ; Is there a task active?
BEQ TCT_Schedule_Loop ; If not, continue the search
; Yes, either a task or an HISR is ready to execute. Lockout
; interrupts while the thread is transferred to.
TCT_Schedule_Thread:
MRS r1,CPSR ; Pickup CPSR again
ORR r1,r1,#LOCKOUT ; Build interrupt lockout value
MSR CPSR,r1 ; Lockout interrupts
; Transfer control to the thread by falling through to the following
; routine.
;}
;************************************************************************
;*
;* FUNCTION
;*
;* TCT_Control_To_Thread
;*
;* DESCRIPTION
;*
;* This function transfers control to the specified thread. Each
;* time control is transferred to a thread, its scheduled counter
;* is incremented. Additionally, time-slicing for task threads is
;* enabled in this routine. The TCD_Current_Thread pointer is
;* setup by this function.
;*
;* CALLED BY
;*
;* TCT_Schedule Indirectly called
;* TCT_Protect Protection task switch
;*
;* CALLS
;*
;* None
;*
;* INPUTS
;*
;* thread Thread control block pointer
;*
;* OUTPUTS
;*
;* None
;*
;* HISTORY
;*
;* NAME DATE REMARKS
;*
;* W. Lamie 02-15-1994 Created initial version 1.0
;* D. Lamie 02-15-1994 Verified version 1.0
;*
;************************************************************************
;VOID TCT_Control_To_Thread(TC_TCB *thread)
;{
_TCT_Control_To_Thread
; Setup the current thread pointer.
; TCD_Current_Thread = (VOID *) thread;
LDR r1,Current_Thread ; Pickup current thread ptr address
LDR r2,[r0, #1ch] ; Pickup scheduled count
STR r0,[r1, #0] ; Setup current thread pointer
; Increment the thread scheduled counter.
; thread -> tc_scheduled++;
LDR r3,[r0, #20h] ; Pickup time slice value
ADD r2,r2,#1 ; Increment the scheduled count
STR r2,[r0, #1ch] ; Store new scheduled count
; Check for time slice option.
; if (thread -> tc_cur_time_slice)
; {
CMP r3,#0 ; Is there a time slice?
BEQ TCT_No_Start_TS_1 ; If 0, there is no time slice
; Start a time slice.
; TMD_Time_Slice = thread -> tc_cur_time_slice;
; TMD_Time_Slice_State = 0;
LDR r2,Time_Slice ; Pickup address of TMD_Time_Slice
LDR r1,Slice_State ; Pickup address of
; TMD_Time_Slice_State
STR r3,[r2, #0] ; Setup the time slice
MOV r2,#0 ; Build active state flag
STR r2,[r1,#0] ; Set the active flag
; }
TCT_No_Start_TS_1:
.if $$isdefed("INCLUDE_PROVIEW")
; Nucleus ProView Hook
STR r0,[r13, #-4]! ; Save r0 on the stack
BL __NU_Schedule_Task_Hook ; Branch to RTView
LDR r0,[r13], #4 ; Recover return address
.endif
; Pickup the stack pointer and resume the thread.
; REG_Stack_Ptr = thread -> tc_stack_pointer;
LDR r13,[r0, #2ch] ; Switch to thread's stack pointer
; Pop off the saved information associated with the thread. After we
; determine which type of stack is present. A 1 on the top of the
; stack indicates an interrupt stack, while a 0 on the top of the
; stack indicates a solicited type of stack.
; Remember that the interrupt level that is restored must represent
; the interrupt level in TCD_Interrupt_Level.
LDR r1,[r13], #4 ; Pop off the stack type
CMP r1,#1 ; See if it is an interrupt stack
BEQ TCT_Interrupt_Resume ; If so, an interrupt resume of
; thread is required
LDR r1, Int_Level ; Pickup address of interrupt
; lockout
MRS r0,CPSR ; Pickup current CPSR
BIC r0,r0,#LOCK_MSK ; Clear lockout mask
BIC r0,r0,#0x80000000
LDR r2,[r1, #0] ; Pickup interrupt lockout mask
ORR r0,r0,r2 ; Build new interrupt lockout mask
.if THUMB
LDR r2,[r13], #4 ; Pop off the state mask
ORR r0,r0,r2 ; Set appropriate state
.endif
MSR SPSR,r0 ; Place it into the SPSR
LDMIA r13!,{r4-r12,r15}^ ; A solicited return is required.
; This type of return only
; recovers r4-r13 & r15
TCT_Interrupt_Resume:
LDR r0,[r13], #4 ; Pop off the CPSR
LDR r1,Int_Level ; Pickup address of interrupt
; lockout
BIC r0,r0,#LOCK_MSK ; Clear lockout mask
LDR r2,[r1, #0] ; Pickup interrupt lockout mask
ORR r0,r0,r2 ; Build new interrupt lockout mask
MSR SPSR,r0 ; Place it into the SPSR
LDMIA r13,{r0-r15}^ ; Recover all registers and resume
; at point of interrupt
;}
;************************************************************************
;*
;* FUNCTION
;*
;* TCT_Control_To_System
;*
;* DESCRIPTION
;*
;* This function returns control from a thread to the system. Note
;* that this service is called in a solicited manner, i.e. it is
;* not called from an interrupt thread. Registers required by the
;* compiler to be preserved across function boundaries are saved by
;* this routine. Note that this is usually a sub-set of the total
;* number of available registers.
;*
;* CALLED BY
;*
;* Other Components
;*
;* CALLS
;*
;* TCT_Schedule Schedule the next thread
;*
;* INPUTS
;*
;* None
;*
;* OUTPUTS
;*
;* None
;*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -