帮同学宣传一下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}^