Chinaunix首页 | 论坛 | 博客
  • 博客访问: 494337
  • 博文数量: 223
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2145
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-01 10:23
个人简介

该坚持的时候坚持,该妥协的时候妥协,该放弃的时候放弃

文章分类

全部博文(223)

文章存档

2017年(56)

2016年(118)

2015年(3)

2014年(46)

我的朋友

分类: 嵌入式

2016-12-30 22:47:38

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

阅读(809) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~