| 帮同学宣传一下http://shop57644665.taobao.com/ |
Task的创建与调度
Nucleus的系统入口函数是
VOID INC_Initialize(VOID *first_available_memory)
{
。。。。。。。。
/* Invoke the application-supplied initialization function. */
Application_Initialize(first_available_memory);
/* Indicate that initialization is finished. */
INC_Initialize_State = INC_END_INITIALIZE;
/* Start scheduling threads of execution. */
TCT_Schedule();
}
Application_Initialize(first_available_memory);这个函数是留给平台用来初始化系统框架和创建task用的。
Task的创建一般如下
if ( NU_Create_Task (&TaskTable[Handle].TaskCB.TCB, Name, os_TaskEntry, Handle, (VOID *)NULL, (void*)(TaskTable[Handle].Stack+1), (ULONG) StackSize, (UCHAR) Priority, #ifndef _TARGET_ 10, #else 0, #endif NU_PREEMPT, NU_NO_START) != NU_SUCCESS ) #define NU_Resume_Task TCCE_Create_Task
最关键的实现是
status = TCC_Create_Task(task_ptr, name, task_entry, argc, argv,
stack_address, stack_size, priority, time_slice, preempt, auto_start);
……
/* Move input task pointer into internal pointer. */
task = (TC_TCB *) task_ptr;
/* Move input task pointer into internal pointer. */
task = (TC_TCB *) task_ptr;
…
填充TC_TCB结构体..
/* Build a stack frame for this task by calling TCT_Build_Task_Stack. */
TCT_Build_Task_Stack(task);
这个函数是根据arm平台thumb模式下填充arm的15个寄存器。
; Build an initial stack frame as follows:
;
; (Lower Address) Stack Top -> 1 (Interrupt stack type)
; CPSR Saved CPSR
; r0 Saved r0
; r1 Saved r1
; r2 Saved r2
; r3 Saved r3
; r4 Saved r4
; r5 Saved r5
; r6 Saved r6
; r7 Saved r7
; r8 Saved r8
; r9 Saved r9
; r10 Saved r10
; r11 Saved r11
; r12 Saved r12
; sp Saved sp
; lr Saved lr
; (Higher Address) Stack Bottom-> pc Saved pc
/* 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
在初始化该task的timer
/* 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;
将task放到相应的list中
/* 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++;
如果创建参数是需要自动运行的,就通过resume来start task。
.......
Nucleus的task调度
;VOID TCT_Schedule(VOID)
.def _TCT_Schedule
_TCT_Schedule
…..
; Get the addresses of the HISR and Task to execute
LDR r2,TCT_Execute_HISR
//TCT_Execute_HISR是已经准备好需要运行的HISR
LDR r3,TCT_Execute_Task
//TCT_Execute_Task是已经准备好需要运行的Task
.if NU_PROFILE_PLUS
; Check to see if there is a task to execute upon entering TCT_Schedule.
; If not, we start IDLE.
//先查询是否有HISR需要运行,其运行是同task一样的流程
LDR r0,[r2] ; Pickup highest priority HISR ptr
CMP r0,#0 ; Is there a HISR active?
BNE TCT_Schedule_Thread ; Found an HISR
//如果没有HISR需运行,就查询task。
LDR r0,[r3] ; Pickup highest priority Task ptr
CMP r0,#0 ; Is there a task active?
BNE TCT_Schedule_Thread ; If not, start IDLE.
//如果也没有就开始loop,一直查询.
STMDB sp!,{r2-r3} ; Save r2-r3
BL __NU_Idle_Hook
LDMIA sp!,{r2-r3} ; Restore r2-r3
.endif
.def TCT_Schedule_Loop
TCT_Schedule_Loop
; Wait until a thread (task or HISR) is available to execute.
; When a thread is available, branch to TCT_Schedule_Thread.
LDR r0,[r2] ; Pickup highest priority HISR ptr
CMP r0,#0 ; Is there a HISR active?
BNE TCT_Schedule_Thread ; Found a HISR
LDR r0,[r3] ; Pickup highest priority Task ptr
CMP r0,#0 ; Is there a task active?
TCT_Schedule_Thread中主要是调用TCT_Control_To_Thread
TCT_Control_To_Thread先判断该task的时间片是否为0,然后设置时间片状态。
; Pickup the thread's stack pointer and resume the thread.
LDR sp,[r0, #TC_STACK_POINTER]
; Pop off the stack top to determine stack type
LDR r1,[sp], #4
; Remove CPSR from stack and put in SPSR
LDR r0,[sp], #4 ; Pop off the CPSR
MSR SPSR,r0 ; Place it into the SPSR
//以上偏移是根据创建时的各个位的定义
; Check if interrupt stack or solicited stack
//r1此时存的为上次中断的类型
CMP r1,#1 ; Compare stack type with 1
BEQ TCT_Interrupt_Resume ; If equal to 1, interrupt stack frame
; Recover all solicited stack frame registers and return
//将task堆栈中存的上次中断时arm的各个寄存器的值复位就恢复了task的运行,和被中断前一样
LDMIA sp!,{r4-r12,pc}^ ; A solicited return is required.
; This type of return only
; Recovers r4-r12 & pc
TCT_Interrupt_Resume
; Recover all registers and resume at point of interrupt
LDMIA sp,{r0-pc}^
















