• nucleus学习


    task的TCB结构:
    1. typedef struct TC_TCB_STRUCT
    2. {
    3.     /* Standard thread information first. This information is used by
    4.        the target dependent portion of this component. Changes made
    5.        to this area of the structure can have undesirable side effects. */

    6.     CS_NODE tc_created; /* Node for linking to */                                       //链接指向创建task链表
    7.                                                /* created task list */
    8.     UNSIGNED tc_id; /* Internal TCB ID */
    9.     CHAR tc_name[NU_MAX_NAME]; /* Task name */
    10.     DATA_ELEMENT tc_status; /* Task status */
    11.     BOOLEAN tc_delayed_suspend; /* Delayed task suspension*/
    12.     DATA_ELEMENT tc_priority; /* Task priority */
    13.     BOOLEAN tc_preemption; /* Task preemption enable */                                  //是否抢占
    14.     UNSIGNED tc_scheduled; /* Task scheduled count */
    15.     UNSIGNED tc_cur_time_slice; /* Current time slice */
    16.     VOID *tc_stack_start; /* Stack starting address */                                   //栈起始地址
    17.     VOID *tc_stack_end; /* Stack ending address */
    18.     VOID *tc_stack_pointer; /* Task stack pointer */
    19.     UNSIGNED tc_stack_size; /* Task stack's size */
    20.     UNSIGNED tc_stack_minimum; /* Minimum stack size */
    21.     struct TC_PROTECT_STRUCT
    22.                        *tc_current_protect; /* Current protection */
    23.     VOID *tc_saved_stack_ptr; /* Previous stack pointer */
    24.     UNSIGNED tc_time_slice; /* Task time slice value */

    25.     /* Information after this point is not used in the target dependent
    26.        portion of this component. Hence, changes in the following section
    27.        should not impact assembly language routines. */
    28.     struct TC_TCB_STRUCT
    29.                        *tc_ready_previous, /* Previously ready TCB */                               //指向上一个TCB
    30.                        *tc_ready_next; /* next and previous ptrs */                                 //指向下一个TCB

    31.     /* Task control information follows. */

    32.     UNSIGNED tc_priority_group; /* Priority group mask bit*/
    33.     struct TC_TCB_STRUCT
    34.                       **tc_priority_head; /* Pointer to list head */                                //指向TCB链表头
    35.     DATA_ELEMENT *tc_sub_priority_ptr; /* Pointer to sub-group */
    36.     DATA_ELEMENT tc_sub_priority; /* Mask of sub-group bit */
    37.     DATA_ELEMENT tc_saved_status; /* Previous task status */
    38.     BOOLEAN tc_signal_active; /* Signal active flag */

    39. #if PAD_3
    40.     DATA_ELEMENT tc_padding[PAD_3];
    41. #endif

    42.                                                /* Task entry function */
    43.     VOID (*tc_entry)(UNSIGNED, VOID *);                                                              //task入口函数,下面是参数
    44.     UNSIGNED tc_argc; /* Optional task argument */
    45.     VOID *tc_argv; /* Optional task argument */
    46.     VOID (*tc_cleanup) (VOID *);/* Clean-up routine */
    47.     VOID *tc_cleanup_info; /* Clean-up information */
    48.     struct TC_PROTECT_STRUCT
    49.                        *tc_suspend_protect; /* Protection at time of */
    50.                                                /* task suspension */

    51.     /* Task timer information. */                                                                    //计时器
    52.     INT tc_timer_active; /* Active timer flag */
    53.     TM_TCB tc_timer_control; /* Timer control block */

    54.     /* Task signal control information. */

    55.     UNSIGNED tc_signals; /* Current signals */
    56.     UNSIGNED tc_enabled_signals; /* Enabled signals */

    57.     /* tc_saved_status and tc_signal_active are now defined above in an
    58.        attempt to keep DATA_ELEMENT types together. */

    59.     /* Signal handling routine. */                                                                   //signal中断处理?
    60.     VOID (*tc_signal_handler) (UNSIGNED);

    61.     /* Reserved words for the system and a single reserved word for the
    62.        application. */
    63.     UNSIGNED tc_system_reserved_1; /* System reserved word */
    64.     UNSIGNED tc_system_reserved_2; /* System reserved word */
    65.     UNSIGNED tc_system_reserved_3; /* System reserved word */
    66.     UNSIGNED tc_app_reserved_1; /* Application reserved */

    67.     /* This information is accessed in assembly */
    68. #if ((NU_SUPERV_USER_MODE == 1)||(NU_MODULE_SUPPORT == 1))
    69.     UNSIGNED tc_su_mode; /* Supervisor/User mode indicator */
    70.     UNSIGNED tc_module; /* Module identifier */
    71. #endif

    72. } TC_TCB;
    TCC创建任务函数:
    1. STATUS TCC_Create_Task(NU_TASK *task_ptr, CHAR *name,
    2.           VOID (*task_entry)(UNSIGNED, VOID *), UNSIGNED argc, VOID *argv,
    3.           VOID *stack_address, UNSIGNED stack_size,
    4.           OPTION priority, UNSIGNED time_slice,
    5.           OPTION preempt, OPTION auto_start)
    6. {

    7. R1 TC_TCB *task; /* Task control block ptr */
    8. R2 INT i; /* Working index variable */
    9. STATUS status = NU_SUCCESS;

    10. NU_SUPERV_USER_VARIABLES

    11.     /* Switch to supervisor mode */
    12.     NU_SUPERVISOR_MODE();

    13.     /* Move input task pointer into internal pointer. */
    14.     task = (TC_TCB *) task_ptr;


    15. #ifdef NU_ENABLE_STACK_CHECK

    16.     /* Call stack checking function to check for an overflow condition. */
    17.     TCT_Check_Stack();

    18. #endif

    19. #ifdef NU_ENABLE_HISTORY

    20.     /* Make an entry that corresponds to this function in the system history
    21.        log. */
    22.     HIC_Make_History_Entry(NU_CREATE_TASK_ID, (UNSIGNED) task,
    23.                                 (UNSIGNED) name, (UNSIGNED) task_entry);

    24. #endif

    25.     /* First, clear the task ID just in case it is an old Task
    26.        Control Block. */
    27.     task -> tc_id = 0;

    28.     /* Fill in the task name. */
    29.     for (i = 0; i < NU_MAX_NAME; i++)
    30.         task -> tc_name[i] = name[i];

    31.     /* Fill in the basic task information. */
    32.     task -> tc_entry = task_entry;
    33.     task -> tc_argc = argc;
    34.     task -> tc_argv = argv;
    35.     task -> tc_status = NU_PURE_SUSPEND;                                 //这里设定为pure_suspend,完全挂起。如果设定auto_start,调用resume_task()唤醒task
    36.     task -> tc_delayed_suspend = NU_FALSE;
    37.     task -> tc_scheduled = 0;
    38.     task -> tc_time_slice = time_slice;
    39.     task -> tc_cur_time_slice = time_slice;
    40.     task -> tc_current_protect = NU_NULL;
    41.     task -> tc_suspend_protect = NU_NULL;
    42.     task -> tc_cleanup = NU_NULL;
    43.     task -> tc_cleanup_info = NU_NULL;

    44.     /* Setup task's preemption posture. */
    45.     if (preempt == NU_PREEMPT)
    46.         task -> tc_preemption = NU_TRUE;
    47.     else
    48.         task -> tc_preemption = NU_FALSE;

    49.     /* Fill in information about the task's stack. */
    50.     task -> tc_stack_start = stack_address;
    51.     task -> tc_stack_end = 0;
    52.     task -> tc_stack_size = stack_size;
    53.     task -> tc_stack_minimum = stack_size;

    54.     /* Setup priority information for the task. There are two bit maps
    55.        associated with each task. The first bit map indicates which group
    56.        of 8-priorities it is. The second bit map indicates the actual
    57.        priority within the group. */
    58.     task -> tc_priority = priority;                                                                         
    59.     task -> tc_priority_head = &(TCD_Priority_List[priority]);                                              //这里挂载进TCB双向链表指针
    60.     task -> tc_sub_priority = (DATA_ELEMENT) (1 << (priority & 7));
    61.     priority = priority >> 3;
    62.     task -> tc_priority_group = ((UNSIGNED) 1) << priority;
    63.     task -> tc_sub_priority_ptr = &(TCD_Sub_Priority_Groups[priority]);

    64.     /* Initialize link pointers. */
    65.     task -> tc_created.cs_previous = NU_NULL;
    66.     task -> tc_created.cs_next = NU_NULL;
    67.     task -> tc_ready_previous = NU_NULL;
    68.     task -> tc_ready_next = NU_NULL;

    69.     /* Build a stack frame for this task by calling TCT_Build_Task_Stack. */
    70.     TCT_Build_Task_Stack(task);

    71.     /* Initialize the signal information of the task. */
    72.     task -> tc_signals = 0;
    73.     task -> tc_enabled_signals = 0;
    74.     task -> tc_signal_handler = 0;
    75.     task -> tc_signal_active = NU_FALSE;
    76.     /* Initialize additional kernel options data */

    77. #if (NU_SUPERV_USER_MODE == 1)
    78.     task->tc_su_mode = 0; /* Initially in User mode */
    79.     task->tc_module = 0; /* Not initially bound to a module */
    80. #endif

    81.     /* Initialize the task timer. */
    82.     task -> tc_timer_active = NU_FALSE;
    83.     TMC_Init_Task_Timer(&(task -> tc_timer_control), (VOID *) task);

    84.     /* Protect the list of created tasks. */
    85.     TCT_Protect(&TCD_List_Protect);

    86.     /* At this point the task is completely built. The ID can now be
    87.        set and it can be linked into the created task list. */
    88.     task -> tc_id = TC_TASK_ID;

    89. #if defined(NU_MODULE_SUPPORT) && (NU_MODULE_SUPPORT > 0)
    90.     /* If executing in a thread's context, bind to that thread's module */
    91.     if(TCD_Current_Thread != NU_NULL)
    92.     {
    93.         status = MSC_Bind_Module_Task(
    94.           (MS_MODULE*)(((TC_TCB*)(TCD_Current_Thread))->tc_module), task);
    95.     }
    96.     else /* It must be initialization time, so use the current module */
    97.     {
    98.         status = MSC_Bind_Module_Task(msd_current_module, task);
    99.     }
    100. #endif /* NU_MODULE_SUPPORT */

    101.     /* Link the task into the list of created tasks and increment the
    102.        total number of tasks in the system. */
    103.     CSC_Place_On_List(&TCD_Created_Tasks_List, &(task -> tc_created));
    104.     TCD_Total_Tasks++;

    105. #ifdef INCLUDE_PROVIEW
    106.     _RTProf_DumpTask(task,RT_PROF_CREATE_TASK);
    107. #endif

    108.     /* Release the protection. */
    109.     TCT_Unprotect();

    110.     /* Determine if the task should be automatically started. */
    111.     if (auto_start == NU_START)
    112.     {

    113.         /* Protect the system data structures. */
    114.         TCT_Protect(&TCD_System_Protect);

    115.         /* Start the task by resuming it. If the preemption is required,
    116.            leave the current task. */
    117.         if (TCC_Resume_Task(task_ptr, NU_PURE_SUSPEND))


    118.             /* Transfer control back to the system. */
    119.             TCT_Control_To_System();
    120.         else

    121.             /* Release the protection. */
    122.             TCT_Unprotect();
    123.     }

    124.     /* Return to user mode */
    125.     NU_USER_MODE();

    126.     /* Return successful completion. */
    127.     return(status);
    128. }
    TCC创建HISR函数:
    1. STATUS TCC_Create_HISR(NU_HISR *hisr_ptr, CHAR *name,
    2.           VOID (*hisr_entry)(VOID), OPTION priority,
    3.           VOID *stack_address, UNSIGNED stack_size)
    4. {

    5. R1 TC_HCB *hisr; /* HISR control block ptr */
    6. R2 INT i; /* Working index variable */
    7. STATUS status = NU_SUCCESS;

    8. NU_SUPERV_USER_VARIABLES

    9.     /* Switch to supervisor mode */
    10.     NU_SUPERVISOR_MODE();

    11.     /* Move input HISR pointer into internal pointer. */
    12.     hisr = (TC_HCB *) hisr_ptr;


    13. #ifdef NU_ENABLE_STACK_CHECK

    14.     /* Call stack checking function to check for an overflow condition. */
    15.     TCT_Check_Stack();

    16. #endif

    17. #ifdef NU_ENABLE_HISTORY

    18.     /* Make an entry that corresponds to this function in the system history
    19.        log. */
    20.     HIC_Make_History_Entry(NU_CREATE_HISR_ID, (UNSIGNED) hisr,
    21.                                 (UNSIGNED) name, (UNSIGNED) hisr_entry);

    22. #endif

    23.     /* First, clear the HISR ID just in case it is an old HISR
    24.        Control Block. */
    25.     hisr -> tc_id = 0;

    26.     /* Fill in the HISR name. */
    27.     for (i = 0; i < NU_MAX_NAME; i++)
    28.         hisr -> tc_name[i] = name[i];

    29.     /* Fill in the basic HISR information. */
    30.     hisr -> tc_entry = hisr_entry;
    31.     hisr -> tc_scheduled = 0;
    32.     hisr -> tc_activation_count = 0;
    33.     hisr -> tc_cur_time_slice = 0;

    34.     /* Fill in information about the HISR's stack. */
    35.     hisr -> tc_stack_start = stack_address;
    36.     hisr -> tc_stack_end = 0;
    37.     hisr -> tc_stack_size = stack_size;
    38.     hisr -> tc_stack_minimum = stack_size;

    39.     /* Setup priority information for the HISR. Priorities range from 0 to
    40.        TC_HISR_PRIORITIES - 1. */
    41.     hisr -> tc_priority = priority & 3;                                                   //这里优先级与上了3,所以只有0、1、2三种。优先级会更高

    42.     /* Initialize link pointers. */
    43.     hisr -> tc_created.cs_previous = NU_NULL;                                             //这里不加双向链表
    44.     hisr -> tc_created.cs_next = NU_NULL;
    45.     hisr -> tc_active_next = NU_NULL;

    46.     /* Clear protect pointer. */
    47.     hisr -> tc_current_protect = NU_NULL;

    48.     /* Initialize additional kernel options data */
    49. #if (NU_SUPERV_USER_MODE == 1)
    50.     hisr->tc_su_mode = 1; /* TCT_HISR_Shell in Supervisor mode */
    51.     hisr->tc_module = 0; /* Not initially bound to a module */
    52. #endif

    53.     /* Build a stack frame for this HISR by calling TCT_Build_HISR_Stack. */
    54.     TCT_Build_HISR_Stack(hisr);

    55.     /* Protect the list of created HISRs. */
    56.     TCT_Protect(&TCD_HISR_Protect);

    57.     /* At this point the HISR is completely built. The ID can now be
    58.        set and it can be linked into the created HISR list. */
    59.     hisr -> tc_id = TC_HISR_ID;

    60. #if defined(NU_MODULE_SUPPORT) && (NU_MODULE_SUPPORT > 0)
    61.     /* If executing in a thread's context, bind to that thread's module */
    62.     if(TCD_Current_Thread != NU_NULL)
    63.     {
    64.         status = MSC_Bind_Module_HISR(
    65.           (MS_MODULE*)(((TC_TCB*)(TCD_Current_Thread))->tc_module), hisr);
    66.     }
    67.     else /* It must be initialization time, so use the current module */
    68.     {
    69.         status = MSC_Bind_Module_HISR(msd_current_module, hisr);
    70.     }
    71. #endif /* NU_MODULE_SUPPORT */

    72.     /* Link the HISR into the list of created HISRs and increment the
    73.        total number of HISRs in the system. */
    74.     CSC_Place_On_List(&TCD_Created_HISRs_List, &(hisr -> tc_created));                           //在这里加入了链表?
    75.     TCD_Total_HISRs++;                                                                           //增加了链表长度计数

    76. #ifdef INCLUDE_PROVIEW
    77.     _RTProf_DumpHisr(hisr,RT_PROF_CREATE_HISR);
    78. #endif

    79.     /* Release the protection. */
    80.     TCT_Unprotect();

    81.     /* Return to user mode */
    82.     NU_USER_MODE();

    83.     /* Return successful completion. */
    84.     return(status);
    85. }

    在tct.s中有TCT_Control_To_System,主要要建立新的system_stack:
    1. ;************************************************************************
    2. ;*
    3. ;* FUNCTION
    4. ;*
    5. ;* TCT_Control_To_System
    6. ;*
    7. ;* DESCRIPTION
    8. ;*
    9. ;* This function returns control from a thread to the system. Note
    10. ;* that this service is called in a solicited manner, i.e. it is
    11. ;* not called from an interrupt thread. Registers required by the
    12. ;* compiler to be preserved across function boundaries are saved by
    13. ;* this routine. Note that this is usually a sub-set of the total
    14. ;* number of available registers.
    15. ;*
    16. ;* CALLED BY
    17. ;*
    18. ;* Other Components
    19. ;*
    20. ;* CALLS
    21. ;*
    22. ;* TCT_Schedule Schedule the next thread
    23. ;*
    24. ;* INPUTS
    25. ;*
    26. ;* None
    27. ;*
    28. ;* OUTPUTS
    29. ;*
    30. ;* None
    31. ;*
    32. ;* HISTORY
    33. ;*
    34. ;* NAME DATE REMARKS
    35. ;*
    36. ;* W. Lamie 02-15-1994 Created initial version 1.0
    37. ;* D. Lamie 02-15-1994 Verified version 1.0
    38. ;* C. Meredith 03-01-1994 Corrected problem in time-slice
    39. ;* reset logic, resulting in
    40. ;* version 1.1
    41. ;* D. Lamie 03-18-1994 Verified version 1.1
    42. ;*
    43. ;************************************************************************
    44. ;VOID TCT_Control_To_System(void)
    45. ;{
    46.     .def $TCT_Control_To_System
    47. $TCT_Control_To_System ; Dual-state interworking veneer
    48.     .state16
    49.     BX r15
    50.     NOP
    51.     .state32
    52.     B _TCT_Control_To_System

    53.         .def _TCT_Control_To_System
    54. _TCT_Control_To_System

    55.     ; Lockout interrupts.

    56.         MRS r0,CPSR ; Pickup current CPSR                                                                                         //获取CPSR值
    57.         ORR r0,r0,#LOCKOUT ; Build interrupt lockout value
    58.         MSR CPSR,r0 ; Lockout interrupts                                                                                          //写入CPSR中断屏蔽位

    59.     ; Save a minimal context of the thread.

    60.         STMDB r13!,{r4-r12,r14} ; Save minimal context of thread on                                                               //保存上下文
    61.                                             ; the current stack
    62.         .if THUMB                                                                                                                 //如果是THUMB模式
    63.          
    64.          MOV r2,r14 ; Determine what state the caller
    65.          MOV r2,r2,LSL #31 ; was in and build an
    66.          MOV r2,r2,LSR #26 ; appropriate state mask
    67.          STR r2,[r13, #-4]! ; Place it on the stack
    68.          
    69.         .endif
    70.         MOV r2,#0 ; Build solicited stack type value                                                                              //建立solicited stack(请求栈?)
    71.                                             ; and NU_NULL value
    72.         STR r2,[r13, #-4]! ; Place it on the top of the stack                                                                     //用r2替换r13下面一格的内容,r2不是0吗。那不是删除了r4的内容吗?

    73.     ; Setup a pointer to the thread control block.
    74. ; REG_Thread_Ptr = (TC_TCB *) TCD_Current_Thread;

    75.         LDR r1,Current_Thread ; Pickup current thread ptr address                                                              //获取当前进程指针地址
    76.         LDR r0,[r1, #0] ; Pickup current thread pointer

    77.     ; Clear the current thread control block pointer.
    78. ; TCD_Current_Thread = NU_NULL;

    79.         LDR r3,Slice_State ; Pickup time slice state address                                                                   //获取time Slice_State地址
    80.         STR r2,[r1, #0] ; Set current thread pointer to                                                                        //又把进程指针清零了
    81.                                             ; NU_NULL

    82. ; Check to see if a time slice is active. If so, copy the original time
    83. ; slice into the current time slice field of the task's control block.
    84. ; if (TMD_Time_Slice_State == 0)
    85. ; {
    86.         LDR r1,[r3, #0] ; Pickup time slice state flag                                                                         //r3是Slice_State中的值到r1
    87.         CMP r1,#0 ; Compare with active value                                                                                  //比较是否是0
    88.         BNE TCT_No_Stop_TS_1 ; If non-active, don't disable                                                                    //如果不是0,跳转到TCT_No_Stop_TS_1

    89.     
    90.     ; Insure that the next time the task runs it gets a fresh time
    91.     ; slice.
    92. ; REG_Thread_Ptr -> tc_cur_time_slice = REG_Thread_Ptr -> tc_time_slice;

    93.         LDR r1,[r0, #40h] ; Pickup original time slice                                                                         //从另一个地方找了time slice

    94.         ; Clear any active time slice by setting the state to NOT_ACTIVE.
    95. ; TMD_Time_Slice_State = 1;

    96.         MOV r2,#1 ; Build disable value                                                                                         //设置了1关闭
    97.         STR r2,[r3, #0] ; Disable time slice                                                                                    //设置time_slice_state
    98.         STR r1,[r0, #20h] ; Reset current time slice                                                                            //明明已经禁止了为什么还要赋值current time_slice呢。
    99. ; }
    100. TCT_No_Stop_TS_1:                                                                                                               //这里是TCT_No_Stop_TS_1

    101.      ; Save off the current stack pointer in the control block.
    102. ; REG_Thread_Ptr -> tc_stack_pointer = (VOID *) REG_Stack_Ptr;

    103.         STR r13,[r0, #2ch] ; Save the thread's stack pointer                                                                    //保存进程栈指针,为什么Slice_State加上#2ch就是进程栈指针呢,可能是结构体向下移动了几位

    104.      ; Clear the task's current protection.
    105. ; (REG_Thread_Ptr -> tc_current_protect) -> tc_tcb_pointer = NU_NULL;
    106. ; REG_Thread_Ptr -> tc_current_protect = NU_NULL;

    107.         LDR r1,[r0, #38h] ; Pickup current thread pointer                                                                       //获取当前进程指针
    108.         MOV r2,#0 ; Build NU_NULL value                                                                                         //r2置0
    109.         STR r2,[r0, #38h] ; Clear the protect pointer field                                                                     //清除保护指针字段
    110.         STR r2,[r1, #0] ; Release the actual protection                                                                         //释放实际保护

    111.     ; Switch to the system stack.
    112. ; REG_Stack_Ptr = TCD_System_Stack;

    113.         LDR r1, System_Stack ; Pickup address of stack pointer                                                                  //这里应该建立了新的system栈
    114.         LDR r2, System_Limit ; Pickup address of stack limit ptr
    115.         LDR r13,[r1, #0] ; Switch to system stack
    116.         LDR r10,[r2, #0] ; Setup system stack limit

    117.     ; Finished, return to the scheduling loop.

    118.         B _TCT_Schedule ; Return to scheduling loop                                                                             //跳转到_TCT_Schedule
    119. ;}
    在tct.s中有TCT_Schedule(void)内容,这里开关的中断屏蔽寄存器,来使得进程能跟切换(进程指针的获取):
    1. ;************************************************************************
    2. ;*
    3. ;* FUNCTION
    4. ;*
    5. ;* TCT_Schedule
    6. ;*
    7. ;* DESCRIPTION
    8. ;*
    9. ;* This function waits for a thread to become ready. Once a thread
    10. ;* is ready, this function initiates a transfer of control to that
    11. ;* thread.
    12. ;*
    13. ;* CALLED BY
    14. ;*
    15. ;* INC_Initialize Main initialization routine
    16. ;*
    17. ;* CALLS
    18. ;*
    19. ;* TCT_Control_To_Thread Transfer control to a thread
    20. ;*
    21. ;* INPUTS
    22. ;*
    23. ;* TCD_Execute_Task Pointer to task to execute
    24. ;*
    25. ;* OUTPUTS
    26. ;*
    27. ;* None
    28. ;*
    29. ;* HISTORY
    30. ;*
    31. ;* NAME DATE REMARKS
    32. ;*
    33. ;* W. Lamie 02-15-1994 Created initial version 1.0
    34. ;* D. Lamie 02-15-1994 Verified version 1.0
    35. ;*
    36. ;************************************************************************
    37. ;VOID TCT_Schedule(void)
    38. ;{
    39.     .def $TCT_Schedule
    40. $TCT_Schedule ; Dual-state interworking veneer
    41.     .state16                                                                                                                           //16位模式下?
    42.     BX r15
    43.     NOP
    44.     .state32                                                                                                                           //32位模式下
    45.     B _TCT_Schedule

    46.         .def _TCT_Schedule
    47. _TCT_Schedule                                                                                                                          //明明下面就是_TCT_Schedule为什么要跳转

    48.     ; Restore interrupts according to the value contained in                                                                           //根据在TCD_Interrupt_Level中值恢复中断 
    49. ; TCD_Interrupt_Level.

    50.         LDR r1,Int_Level ; Build address of interrupt level                                                                            //把Int_Level地址读取到r1                                                                 
    51.         MRS r0,CPSR ; Pickup current CPSR                                                                                              //读取CPSR到r0
    52.         LDR r2,[r1, #0] ; Pickup current interrupt lockout                                                                             //获取当前中断屏蔽字段
    53.         BIC r0,r0,#LOCK_MSK ; Clear the interrupt lockout bits                                                                         //清除中断屏蔽
    54.         ORR r0,r0,r2 ; Build new interrupt lockout CPSR                                                                                //设置新的中断屏蔽字段
    55.         MSR CPSR,r0 ; Setup new CPSR                                                                                                   //写回CPSR
    56.         LDR r2,Execute_HISR ; Pickup TCD_Execute_HISR address                                                                          //获取TCD_Execute_HISR地址到r2
    57.         LDR r3,Execute_Task ; Pickup TCD_Execute_Task address                                                                          //获取TCD_Execute_Task地址到r3

    58.     .if $$isdefed("INCLUDE_PROVIEW")
    59. ; Nucleus ProView Hook
    60. ; We check if upon entering TCT_Schedule we already have a task to excute.                                                             //确认是否进入了TCT_Schedule时已经运行了task
    61. ; if not, we start IDLE.                                                                                                               //如果没运行就空闲
    62.         LDR r0,[r2, #0] ; Pickup highest priority HISR ptr                                                                             //获取最高有限级的HISR指针
    63.         CMP r0,#0 ; Is there a HISR active?                                                                                            //是否已经运行,0是运行
    64.         BNE TCT_Schedule_Thread ; Found an HISR                                                                                        //建立一个HISR,下面是TCT_Schedule_Thread
    65.         LDR r0,[r3, #0] ; Pickup highest priority Task ptr                                                                             //获取任务的最高优先级
    66.         CMP r0,#0 ; Is there a task active?                                                                                            //判断是否运行
    67.         BNE TCT_Schedule_Thread ; If not, start IDLE.                                                                                  //不是0就开始IDLE
    68.         STR r2,[r13, #-4]! ; Save r2 on the stack                                                                                      //把r2压入栈Execute_HISR地址
    69.         STR r3,[r13, #-4]! ; Save r3 on the stack                                                                                      //把r3压入栈Execute_Task地址
    70.         BL __NU_Idle_Hook                                                                                                              //跳转到__NU_IDLE_HOOK这个是进等待吧,钩子
    71.         LDR r3,[r13], #4 ; Recover r2
    72.         LDR r2,[r13], #4 ; Recover r3
    73.     .endif


    74.     ; Wait until a thread (task or HISR) is available to execute.
    75. ; do
    76. ; {
    77. TCT_Schedule_Loop:

    78. ; } while ((!TCD_Execute_HISR) && (!TCD_Execute_Task));                                                                                 //TCD_Execute_HISRTCD_Execute_Task为空就一直IDLE

    79.         LDR r0,[r2, #0] ; Pickup highest priority HISR ptr
    80.         CMP r0,#0 ; Is there a HISR active?
    81.         BNE TCT_Schedule_Thread ; Found an HISR
    82.         LDR r0,[r3, #0] ; Pickup highest priority Task ptr
    83.         CMP r0,#0 ; Is there a task active?
    84.         BEQ TCT_Schedule_Loop ; If not, continue the search

    85.     ; Yes, either a task or an HISR is ready to execute. Lockout
    86.     ; interrupts while the thread is transferred to.

    87. TCT_Schedule_Thread:                                                                                                                    //这里应该是调度任务了
    88.         MRS r1,CPSR ; Pickup CPSR again                                                                                                 //获取CPSR
    89.         ORR r1,r1,#LOCKOUT ; Build interrupt lockout value                                                                              //进行逻辑或设置中断屏蔽值
    90.         MSR CPSR,r1 ; Lockout interrupts                                                                                                //为什么设置了中断屏蔽就会运行了,是不是通过开关中断屏蔽,来让任务自动抢占?上面获取了HISR最高优先级的指针地址

    91. ; Transfer control to the thread by falling through to the following
    92. ; routine.
    93. ;}
    control_to_thread,只要确认了time slice有没有正常工作。:
    1. ;************************************************************************
    2. ;*
    3. ;* FUNCTION
    4. ;*
    5. ;* TCT_Control_To_Thread
    6. ;*
    7. ;* DESCRIPTION
    8. ;*
    9. ;* This function transfers control to the specified thread. Each
    10. ;* time control is transferred to a thread, its scheduled counter
    11. ;* is incremented. Additionally, time-slicing for task threads is
    12. ;* enabled in this routine. The TCD_Current_Thread pointer is
    13. ;* setup by this function.
    14. ;*
    15. ;* CALLED BY
    16. ;*
    17. ;* TCT_Schedule Indirectly called
    18. ;* TCT_Protect Protection task switch
    19. ;*
    20. ;* CALLS
    21. ;*
    22. ;* None
    23. ;*
    24. ;* INPUTS
    25. ;*
    26. ;* thread Thread control block pointer
    27. ;*
    28. ;* OUTPUTS
    29. ;*
    30. ;* None
    31. ;*
    32. ;* HISTORY
    33. ;*
    34. ;* NAME DATE REMARKS
    35. ;*
    36. ;* W. Lamie 02-15-1994 Created initial version 1.0
    37. ;* D. Lamie 02-15-1994 Verified version 1.0
    38. ;*
    39. ;************************************************************************
    40. ;VOID TCT_Control_To_Thread(TC_TCB *thread)
    41. ;{
    42. _TCT_Control_To_Thread

    43.     ; Setup the current thread pointer.
    44. ; TCD_Current_Thread = (VOID *) thread;                                                                                //设置当前进程指针

    45.         LDR r1,Current_Thread ; Pickup current thread ptr address
    46.         LDR r2,[r0, #1ch] ; Pickup scheduled count
    47.         STR r0,[r1, #0] ; Setup current thread pointer

    48.     ; Increment the thread scheduled counter.
    49. ; thread -> tc_scheduled++;                                                                                            //增加scheduled计数

    50.         LDR r3,[r0, #20h] ; Pickup time slice value
    51.         ADD r2,r2,#1 ; Increment the scheduled count
    52.         STR r2,[r0, #1ch] ; Store new scheduled count

    53.     ; Check for time slice option.
    54. ; if (thread -> tc_cur_time_slice)                                                                                     //确认time_slice
    55. ; {
    56.         CMP r3,#0 ; Is there a time slice?
    57.         BEQ TCT_No_Start_TS_1 ; If 0, there is no time slice                                                           //如果是0,表明没有。time slice没有运行

    58.         ; Start a time slice.
    59. ; TMD_Time_Slice = thread -> tc_cur_time_slice;
    60. ; TMD_Time_Slice_State = 0;

    61.         LDR r2,Time_Slice ; Pickup address of TMD_Time_Slice                                                          //获取time slice
    62.         LDR r1,Slice_State ; Pickup address of                                                                        //获取time slice state
    63.                                             ; TMD_Time_Slice_State
    64.         STR r3,[r2, #0] ; Setup the time slice                                                                        //设置time slice
    65.         MOV r2,#0 ; Build active state flag                                                                           //置0
    66.         STR r2,[r1,#0] ; Set the active flag                                                                          //设置活动标志
    67. ; }
    68. TCT_No_Start_TS_1:                                                                                                    //这里是TCT_No_Start_TS_1
    69.     .if $$isdefed("INCLUDE_PROVIEW")                                                                                  //如果定义了INCLUDE_PROVIEW
    70. ; Nucleus ProView Hook

    71.         STR r0,[r13, #-4]! ; Save r0 on the stack                                                                    //把r0压入栈
    72.         BL __NU_Schedule_Task_Hook ; Branch to RTView                                                                //跳转到__NU_Schedule_Task_Hook 
    73.         LDR r0,[r13], #4 ; Recover return address
    74.     .endif


    75.     ; Pickup the stack pointer and resume the thread.
    76. ; REG_Stack_Ptr = thread -> tc_stack_pointer;

    77.         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

    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    数组相关操作
    控制结构和函数
    调用函数和方法
    常用类型、算术和操作符重载
    函数式 CSS (FCSS)
    Javascript 封装问题
    认识javascript中的作用域和上下文
    Javascript 继承-原型的陷阱
    解耦你的HTML,CSS和JAVASRIPT
    网格如此简单
  • 原文地址:https://www.cnblogs.com/ch122633/p/7363282.html
Copyright © 2020-2023  润新知