task的TCB结构:
-
typedef struct TC_TCB_STRUCT
-
{
-
/* Standard thread information first. This information is used by
-
the target dependent portion of this component. Changes made
-
to this area of the structure can have undesirable side effects. */
-
-
CS_NODE tc_created; /* Node for linking to */ //链接指向创建task链表
-
/* created task list */
-
UNSIGNED tc_id; /* Internal TCB ID */
-
CHAR tc_name[NU_MAX_NAME]; /* Task name */
-
DATA_ELEMENT tc_status; /* Task status */
-
BOOLEAN tc_delayed_suspend; /* Delayed task suspension*/
-
DATA_ELEMENT tc_priority; /* Task priority */
-
BOOLEAN tc_preemption; /* Task preemption enable */ //是否抢占
-
UNSIGNED tc_scheduled; /* Task scheduled count */
-
UNSIGNED tc_cur_time_slice; /* Current time slice */
-
VOID *tc_stack_start; /* Stack starting address */ //栈起始地址
-
VOID *tc_stack_end; /* Stack ending address */
-
VOID *tc_stack_pointer; /* Task stack pointer */
-
UNSIGNED tc_stack_size; /* Task stack's size */
-
UNSIGNED tc_stack_minimum; /* Minimum stack size */
-
struct TC_PROTECT_STRUCT
-
*tc_current_protect; /* Current protection */
-
VOID *tc_saved_stack_ptr; /* Previous stack pointer */
-
UNSIGNED tc_time_slice; /* Task time slice value */
-
-
/* Information after this point is not used in the target dependent
-
portion of this component. Hence, changes in the following section
-
should not impact assembly language routines. */
-
struct TC_TCB_STRUCT
-
*tc_ready_previous, /* Previously ready TCB */ //指向上一个TCB
-
*tc_ready_next; /* next and previous ptrs */ //指向下一个TCB
-
-
/* Task control information follows. */
-
-
UNSIGNED tc_priority_group; /* Priority group mask bit*/
-
struct TC_TCB_STRUCT
-
**tc_priority_head; /* Pointer to list head */ //指向TCB链表头
-
DATA_ELEMENT *tc_sub_priority_ptr; /* Pointer to sub-group */
-
DATA_ELEMENT tc_sub_priority; /* Mask of sub-group bit */
-
DATA_ELEMENT tc_saved_status; /* Previous task status */
-
BOOLEAN tc_signal_active; /* Signal active flag */
-
-
#if PAD_3
-
DATA_ELEMENT tc_padding[PAD_3];
-
#endif
-
-
/* Task entry function */
-
VOID (*tc_entry)(UNSIGNED, VOID *); //task入口函数,下面是参数
-
UNSIGNED tc_argc; /* Optional task argument */
-
VOID *tc_argv; /* Optional task argument */
-
VOID (*tc_cleanup) (VOID *);/* Clean-up routine */
-
VOID *tc_cleanup_info; /* Clean-up information */
-
struct TC_PROTECT_STRUCT
-
*tc_suspend_protect; /* Protection at time of */
-
/* task suspension */
-
-
/* Task timer information. */ //计时器
-
INT tc_timer_active; /* Active timer flag */
-
TM_TCB tc_timer_control; /* Timer control block */
-
-
/* Task signal control information. */
-
-
UNSIGNED tc_signals; /* Current signals */
-
UNSIGNED tc_enabled_signals; /* Enabled signals */
-
-
/* tc_saved_status and tc_signal_active are now defined above in an
-
attempt to keep DATA_ELEMENT types together. */
-
-
/* Signal handling routine. */ //signal中断处理?
-
VOID (*tc_signal_handler) (UNSIGNED);
-
-
/* Reserved words for the system and a single reserved word for the
-
application. */
-
UNSIGNED tc_system_reserved_1; /* System reserved word */
-
UNSIGNED tc_system_reserved_2; /* System reserved word */
-
UNSIGNED tc_system_reserved_3; /* System reserved word */
-
UNSIGNED tc_app_reserved_1; /* Application reserved */
-
-
/* This information is accessed in assembly */
-
#if ((NU_SUPERV_USER_MODE == 1)||(NU_MODULE_SUPPORT == 1))
-
UNSIGNED tc_su_mode; /* Supervisor/User mode indicator */
-
UNSIGNED tc_module; /* Module identifier */
-
#endif
-
-
} TC_TCB;
TCC创建任务函数:
-
STATUS TCC_Create_Task(NU_TASK *task_ptr, CHAR *name,
-
VOID (*task_entry)(UNSIGNED, VOID *), UNSIGNED argc, VOID *argv,
-
VOID *stack_address, UNSIGNED stack_size,
-
OPTION priority, UNSIGNED time_slice,
-
OPTION preempt, OPTION auto_start)
-
{
-
-
R1 TC_TCB *task; /* Task control block ptr */
-
R2 INT i; /* Working index variable */
-
STATUS status = NU_SUCCESS;
-
-
NU_SUPERV_USER_VARIABLES
-
-
/* Switch to supervisor mode */
-
NU_SUPERVISOR_MODE();
-
-
/* Move input task pointer into internal pointer. */
-
task = (TC_TCB *) task_ptr;
-
-
-
#ifdef NU_ENABLE_STACK_CHECK
-
-
/* Call stack checking function to check for an overflow condition. */
-
TCT_Check_Stack();
-
-
#endif
-
-
#ifdef NU_ENABLE_HISTORY
-
-
/* Make an entry that corresponds to this function in the system history
-
log. */
-
HIC_Make_History_Entry(NU_CREATE_TASK_ID, (UNSIGNED) task,
-
(UNSIGNED) name, (UNSIGNED) task_entry);
-
-
#endif
-
-
/* First, clear the task ID just in case it is an old Task
-
Control Block. */
-
task -> tc_id = 0;
-
-
/* Fill in the task name. */
-
for (i = 0; i < NU_MAX_NAME; i++)
-
task -> tc_name[i] = name[i];
-
-
/* Fill in the basic task information. */
-
task -> tc_entry = task_entry;
-
task -> tc_argc = argc;
-
task -> tc_argv = argv;
-
task -> tc_status = NU_PURE_SUSPEND; //这里设定为pure_suspend,完全挂起。如果设定auto_start,调用resume_task()唤醒task
-
task -> tc_delayed_suspend = NU_FALSE;
-
task -> tc_scheduled = 0;
-
task -> tc_time_slice = time_slice;
-
task -> tc_cur_time_slice = time_slice;
-
task -> tc_current_protect = NU_NULL;
-
task -> tc_suspend_protect = NU_NULL;
-
task -> tc_cleanup = NU_NULL;
-
task -> tc_cleanup_info = NU_NULL;
-
-
/* Setup task's preemption posture. */
-
if (preempt == NU_PREEMPT)
-
task -> tc_preemption = NU_TRUE;
-
else
-
task -> tc_preemption = NU_FALSE;
-
-
/* Fill in information about the task's stack. */
-
task -> tc_stack_start = stack_address;
-
task -> tc_stack_end = 0;
-
task -> tc_stack_size = stack_size;
-
task -> tc_stack_minimum = stack_size;
-
-
/* Setup priority information for the task. There are two bit maps
-
associated with each task. The first bit map indicates which group
-
of 8-priorities it is. The second bit map indicates the actual
-
priority within the group. */
-
task -> tc_priority = priority;
-
task -> tc_priority_head = &(TCD_Priority_List[priority]); //这里挂载进TCB双向链表指针
-
task -> tc_sub_priority = (DATA_ELEMENT) (1 << (priority & 7));
-
priority = priority >> 3;
-
task -> tc_priority_group = ((UNSIGNED) 1) << priority;
-
task -> tc_sub_priority_ptr = &(TCD_Sub_Priority_Groups[priority]);
-
-
/* Initialize link pointers. */
-
task -> tc_created.cs_previous = NU_NULL;
-
task -> tc_created.cs_next = NU_NULL;
-
task -> tc_ready_previous = NU_NULL;
-
task -> tc_ready_next = NU_NULL;
-
-
/* Build a stack frame for this task by calling TCT_Build_Task_Stack. */
-
TCT_Build_Task_Stack(task);
-
-
/* Initialize the signal information of the task. */
-
task -> tc_signals = 0;
-
task -> tc_enabled_signals = 0;
-
task -> tc_signal_handler = 0;
-
task -> tc_signal_active = NU_FALSE;
-
/* Initialize additional kernel options data */
-
-
#if (NU_SUPERV_USER_MODE == 1)
-
task->tc_su_mode = 0; /* Initially in User mode */
-
task->tc_module = 0; /* Not initially bound to a module */
-
#endif
-
-
/* Initialize the task timer. */
-
task -> tc_timer_active = NU_FALSE;
-
TMC_Init_Task_Timer(&(task -> tc_timer_control), (VOID *) task);
-
-
/* Protect the list of created tasks. */
-
TCT_Protect(&TCD_List_Protect);
-
-
/* At this point the task is completely built. The ID can now be
-
set and it can be linked into the created task list. */
-
task -> tc_id = TC_TASK_ID;
-
-
#if defined(NU_MODULE_SUPPORT) && (NU_MODULE_SUPPORT > 0)
-
/* If executing in a thread's context, bind to that thread's module */
-
if(TCD_Current_Thread != NU_NULL)
-
{
-
status = MSC_Bind_Module_Task(
-
(MS_MODULE*)(((TC_TCB*)(TCD_Current_Thread))->tc_module), task);
-
}
-
else /* It must be initialization time, so use the current module */
-
{
-
status = MSC_Bind_Module_Task(msd_current_module, task);
-
}
-
#endif /* NU_MODULE_SUPPORT */
-
-
/* Link the task into the list of created tasks and increment the
-
total number of tasks in the system. */
-
CSC_Place_On_List(&TCD_Created_Tasks_List, &(task -> tc_created));
-
TCD_Total_Tasks++;
-
-
#ifdef INCLUDE_PROVIEW
-
_RTProf_DumpTask(task,RT_PROF_CREATE_TASK);
-
#endif
-
-
/* Release the protection. */
-
TCT_Unprotect();
-
-
/* Determine if the task should be automatically started. */
-
if (auto_start == NU_START)
-
{
-
-
/* Protect the system data structures. */
-
TCT_Protect(&TCD_System_Protect);
-
-
/* Start the task by resuming it. If the preemption is required,
-
leave the current task. */
-
if (TCC_Resume_Task(task_ptr, NU_PURE_SUSPEND))
-
-
-
/* Transfer control back to the system. */
-
TCT_Control_To_System();
-
else
-
-
/* Release the protection. */
-
TCT_Unprotect();
-
}
-
-
/* Return to user mode */
-
NU_USER_MODE();
-
-
/* Return successful completion. */
-
return(status);
-
}
TCC创建HISR函数:
-
STATUS TCC_Create_HISR(NU_HISR *hisr_ptr, CHAR *name,
-
VOID (*hisr_entry)(VOID), OPTION priority,
-
VOID *stack_address, UNSIGNED stack_size)
-
{
-
-
R1 TC_HCB *hisr; /* HISR control block ptr */
-
R2 INT i; /* Working index variable */
-
STATUS status = NU_SUCCESS;
-
-
NU_SUPERV_USER_VARIABLES
-
-
/* Switch to supervisor mode */
-
NU_SUPERVISOR_MODE();
-
-
/* Move input HISR pointer into internal pointer. */
-
hisr = (TC_HCB *) hisr_ptr;
-
-
-
#ifdef NU_ENABLE_STACK_CHECK
-
-
/* Call stack checking function to check for an overflow condition. */
-
TCT_Check_Stack();
-
-
#endif
-
-
#ifdef NU_ENABLE_HISTORY
-
-
/* Make an entry that corresponds to this function in the system history
-
log. */
-
HIC_Make_History_Entry(NU_CREATE_HISR_ID, (UNSIGNED) hisr,
-
(UNSIGNED) name, (UNSIGNED) hisr_entry);
-
-
#endif
-
-
/* First, clear the HISR ID just in case it is an old HISR
-
Control Block. */
-
hisr -> tc_id = 0;
-
-
/* Fill in the HISR name. */
-
for (i = 0; i < NU_MAX_NAME; i++)
-
hisr -> tc_name[i] = name[i];
-
-
/* Fill in the basic HISR information. */
-
hisr -> tc_entry = hisr_entry;
-
hisr -> tc_scheduled = 0;
-
hisr -> tc_activation_count = 0;
-
hisr -> tc_cur_time_slice = 0;
-
-
/* Fill in information about the HISR's stack. */
-
hisr -> tc_stack_start = stack_address;
-
hisr -> tc_stack_end = 0;
-
hisr -> tc_stack_size = stack_size;
-
hisr -> tc_stack_minimum = stack_size;
-
-
/* Setup priority information for the HISR. Priorities range from 0 to
-
TC_HISR_PRIORITIES - 1. */
-
hisr -> tc_priority = priority & 3; //这里优先级与上了3,所以只有0、1、2三种。优先级会更高
-
-
/* Initialize link pointers. */
-
hisr -> tc_created.cs_previous = NU_NULL; //这里不加双向链表
-
hisr -> tc_created.cs_next = NU_NULL;
-
hisr -> tc_active_next = NU_NULL;
-
-
/* Clear protect pointer. */
-
hisr -> tc_current_protect = NU_NULL;
-
-
/* Initialize additional kernel options data */
-
#if (NU_SUPERV_USER_MODE == 1)
-
hisr->tc_su_mode = 1; /* TCT_HISR_Shell in Supervisor mode */
-
hisr->tc_module = 0; /* Not initially bound to a module */
-
#endif
-
-
/* Build a stack frame for this HISR by calling TCT_Build_HISR_Stack. */
-
TCT_Build_HISR_Stack(hisr);
-
-
/* Protect the list of created HISRs. */
-
TCT_Protect(&TCD_HISR_Protect);
-
-
/* At this point the HISR is completely built. The ID can now be
-
set and it can be linked into the created HISR list. */
-
hisr -> tc_id = TC_HISR_ID;
-
-
#if defined(NU_MODULE_SUPPORT) && (NU_MODULE_SUPPORT > 0)
-
/* If executing in a thread's context, bind to that thread's module */
-
if(TCD_Current_Thread != NU_NULL)
-
{
-
status = MSC_Bind_Module_HISR(
-
(MS_MODULE*)(((TC_TCB*)(TCD_Current_Thread))->tc_module), hisr);
-
}
-
else /* It must be initialization time, so use the current module */
-
{
-
status = MSC_Bind_Module_HISR(msd_current_module, hisr);
-
}
-
#endif /* NU_MODULE_SUPPORT */
-
-
/* Link the HISR into the list of created HISRs and increment the
-
total number of HISRs in the system. */
-
CSC_Place_On_List(&TCD_Created_HISRs_List, &(hisr -> tc_created)); //在这里加入了链表?
-
TCD_Total_HISRs++; //增加了链表长度计数
-
-
#ifdef INCLUDE_PROVIEW
-
_RTProf_DumpHisr(hisr,RT_PROF_CREATE_HISR);
-
#endif
-
-
/* Release the protection. */
-
TCT_Unprotect();
-
-
/* Return to user mode */
-
NU_USER_MODE();
-
-
/* Return successful completion. */
-
return(status);
-
}
在tct.s中有TCT_Control_To_System,主要要建立新的system_stack:
-
;************************************************************************
-
;*
-
;* 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
-
;*
-
;* HISTORY
-
;*
-
;* NAME DATE REMARKS
-
;*
-
;* W. Lamie 02-15-1994 Created initial version 1.0
-
;* D. Lamie 02-15-1994 Verified version 1.0
-
;* C. Meredith 03-01-1994 Corrected problem in time-slice
-
;* reset logic, resulting in
-
;* version 1.1
-
;* D. Lamie 03-18-1994 Verified version 1.1
-
;*
-
;************************************************************************
-
;VOID TCT_Control_To_System(void)
-
;{
-
.def $TCT_Control_To_System
-
$TCT_Control_To_System ; Dual-state interworking veneer
-
.state16
-
BX r15
-
NOP
-
.state32
-
B _TCT_Control_To_System
-
-
.def _TCT_Control_To_System
-
_TCT_Control_To_System
-
-
; Lockout interrupts.
-
-
MRS r0,CPSR ; Pickup current CPSR //获取CPSR值
-
ORR r0,r0,#LOCKOUT ; Build interrupt lockout value
-
MSR CPSR,r0 ; Lockout interrupts //写入CPSR中断屏蔽位
-
-
; Save a minimal context of the thread.
-
-
STMDB r13!,{r4-r12,r14} ; Save minimal context of thread on //保存上下文
-
; the current stack
-
.if THUMB //如果是THUMB模式
-
-
MOV r2,r14 ; Determine what state the caller
-
MOV r2,r2,LSL #31 ; was in and build an
-
MOV r2,r2,LSR #26 ; appropriate state mask
-
STR r2,[r13, #-4]! ; Place it on the stack
-
-
.endif
-
MOV r2,#0 ; Build solicited stack type value //建立solicited stack(请求栈?)
-
; and NU_NULL value
-
STR r2,[r13, #-4]! ; Place it on the top of the stack //用r2替换r13下面一格的内容,r2不是0吗。那不是删除了r4的内容吗?
-
-
; Setup a pointer to the thread control block.
-
; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;
-
-
LDR r1,Current_Thread ; Pickup current thread ptr address //获取当前进程指针地址
-
LDR r0,[r1, #0] ; Pickup current thread pointer
-
-
; Clear the current thread control block pointer.
-
; TCD_Current_Thread = NU_NULL;
-
-
LDR r3,Slice_State ; Pickup time slice state address //获取time Slice_State地址
-
STR r2,[r1, #0] ; Set current thread pointer to //又把进程指针清零了
-
; NU_NULL
-
-
; Check to see if a time slice is active. If so, copy the original time
-
; slice into the current time slice field of the task's control block.
-
; if (TMD_Time_Slice_State == 0)
-
; {
-
LDR r1,[r3, #0] ; Pickup time slice state flag //r3是Slice_State中的值到r1
-
CMP r1,#0 ; Compare with active value //比较是否是0
-
BNE TCT_No_Stop_TS_1 ; If non-active, don't disable //如果不是0,跳转到TCT_No_Stop_TS_1
-
-
-
; Insure that the next time the task runs it gets a fresh time
-
; slice.
-
; REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;
-
-
LDR r1,[r0, #40h] ; Pickup original time slice //从另一个地方找了time slice
-
-
; Clear any active time slice by setting the state to NOT_ACTIVE.
-
; TMD_Time_Slice_State = 1;
-
-
MOV r2,#1 ; Build disable value //设置了1关闭
-
STR r2,[r3, #0] ; Disable time slice //设置time_slice_state
-
STR r1,[r0, #20h] ; Reset current time slice //明明已经禁止了为什么还要赋值current time_slice呢。
-
; }
-
TCT_No_Stop_TS_1: //这里是TCT_No_Stop_TS_1
-
-
; Save off the current stack pointer in the control block.
-
; REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;
-
-
STR r13,[r0, #2ch] ; Save the thread's stack pointer //保存进程栈指针,为什么Slice_State加上#2ch就是进程栈指针呢,可能是结构体向下移动了几位
-
-
; Clear the task's current protection.
-
; (REG_Thread_Ptr -> tc_current_protect) -> tc_tcb_pointer = NU_NULL;
-
; REG_Thread_Ptr -> tc_current_protect = NU_NULL;
-
-
LDR r1,[r0, #38h] ; Pickup current thread pointer //获取当前进程指针
-
MOV r2,#0 ; Build NU_NULL value //r2置0
-
STR r2,[r0, #38h] ; Clear the protect pointer field //清除保护指针字段
-
STR r2,[r1, #0] ; Release the actual protection //释放实际保护
-
-
; Switch to the system stack.
-
; REG_Stack_Ptr = TCD_System_Stack;
-
-
LDR r1, System_Stack ; Pickup address of stack pointer //这里应该建立了新的system栈
-
LDR r2, System_Limit ; Pickup address of stack limit ptr
-
LDR r13,[r1, #0] ; Switch to system stack
-
LDR r10,[r2, #0] ; Setup system stack limit
-
-
; Finished, return to the scheduling loop.
-
-
B _TCT_Schedule ; Return to scheduling loop //跳转到_TCT_Schedule
-
;}
在tct.s中有TCT_Schedule(void)内容,这里开关的中断屏蔽寄存器,来使得进程能跟切换(进程指针的获取):
-
;************************************************************************
-
;*
-
;* FUNCTION
-
;*
-
;* TCT_Schedule
-
;*
-
;* DESCRIPTION
-
;*
-
;* This function waits for a thread to become ready. Once a thread
-
;* is ready, this function initiates a transfer of control to that
-
;* thread.
-
;*
-
;* CALLED BY
-
;*
-
;* INC_Initialize Main initialization routine
-
;*
-
;* 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 //16位模式下?
-
BX r15
-
NOP
-
.state32 //32位模式下
-
B _TCT_Schedule
-
-
.def _TCT_Schedule
-
_TCT_Schedule //明明下面就是_TCT_Schedule为什么要跳转
-
-
; Restore interrupts according to the value contained in //根据在TCD_Interrupt_Level中值恢复中断
-
; TCD_Interrupt_Level.
-
-
LDR r1,Int_Level ; Build address of interrupt level //把Int_Level地址读取到r1
-
MRS r0,CPSR ; Pickup current CPSR //读取CPSR到r0
-
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 //写回CPSR
-
LDR r2,Execute_HISR ; Pickup TCD_Execute_HISR address //获取TCD_Execute_HISR地址到r2
-
LDR r3,Execute_Task ; Pickup TCD_Execute_Task address //获取TCD_Execute_Task地址到r3
-
-
.if $$isdefed("INCLUDE_PROVIEW")
-
; Nucleus ProView Hook
-
; We check if upon entering TCT_Schedule we already have a task to excute. //确认是否进入了TCT_Schedule时已经运行了task
-
; if not, we start IDLE. //如果没运行就空闲
-
LDR r0,[r2, #0] ; Pickup highest priority HISR ptr //获取最高有限级的HISR指针
-
CMP r0,#0 ; Is there a HISR active? //是否已经运行,0是运行
-
BNE TCT_Schedule_Thread ; Found an HISR //建立一个HISR,下面是TCT_Schedule_Thread
-
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. //不是0就开始IDLE
-
STR r2,[r13, #-4]! ; Save r2 on the stack //把r2压入栈Execute_HISR地址
-
STR r3,[r13, #-4]! ; Save r3 on the stack //把r3压入栈Execute_Task地址
-
BL __NU_Idle_Hook //跳转到__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)); //TCD_Execute_HISR或TCD_Execute_Task为空就一直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?
-
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 //获取CPSR
-
ORR r1,r1,#LOCKOUT ; Build interrupt lockout value //进行逻辑或设置中断屏蔽值
-
MSR CPSR,r1 ; Lockout interrupts //为什么设置了中断屏蔽就会运行了,是不是通过开关中断屏蔽,来让任务自动抢占?上面获取了HISR最高优先级的指针地址
-
-
; Transfer control to the thread by falling through to the following
-
; routine.
-
;}
control_to_thread,只要确认了time slice有没有正常工作。:
-
;************************************************************************
-
;*
-
;* 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++; //增加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) //确认time_slice
-
; {
-
CMP r3,#0 ; Is there a time slice?
-
BEQ TCT_No_Start_TS_1 ; If 0, there is no time slice //如果是0,表明没有。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 //获取time slice
-
LDR r1,Slice_State ; Pickup address of //获取time slice state
-
; TMD_Time_Slice_State
-
STR r3,[r2, #0] ; Setup the time slice //设置time slice
-
MOV r2,#0 ; Build active state flag //置0
-
STR r2,[r1,#0] ; Set the active flag //设置活动标志
-
; }
-
TCT_No_Start_TS_1: //这里是TCT_No_Start_TS_1
-
.if $$isdefed("INCLUDE_PROVIEW") //如果定义了INCLUDE_PROVIEW
-
; Nucleus ProView Hook
-
-
STR r0,[r13, #-4]! ; Save r0 on the stack //把r0压入栈
-
BL __NU_Schedule_Task_Hook ; Branch to RTView //跳转到__NU_Schedule_Task_Hook
-
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 //运行新的thread
任务的切换主要是上下文的切换,也就是task栈的切换,函数的调用会保存部分regs和返回地址,这些动作都是编译器来完成的,而OS中的任务切换是运行时(runtime)的一种状态变化,因此编译器也无能为力,所以对于上下文的保存需要代码来实现。
任务的抢占是异步的因此必须要通过中断来实现,一般每次timer的中断决定当前的task的slice time是否expired,然后设置TCT_Set_Execute_Task为相同优先级的其他task或更高优先级的task;高优先级的task抢占低优先级的task,一般是外部中断触发,在HISR中resume_task()唤醒高优先级的task,然后schedule到高优先级的task中,因为timer的HISR是在系统初始化就已经注册的,只是执行timeout和time slice超时后的操作,并没有执行resume_task的动作。
http://blog.chinaunix.net/uid-22003667-id-3291833.html
阅读(809) | 评论(0) | 转发(0) |