Chinaunix首页 | 论坛 | 博客
  • 博客访问: 432227
  • 博文数量: 103
  • 博客积分: 1455
  • 博客等级: 上尉
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-15 22:17
文章分类

全部博文(103)

文章存档

2013年(4)

2012年(99)

我的朋友

分类: LINUX

2012-11-13 10:29:57

创建任务的函数是系统的基础,系统使用的几乎所有任务都是用这个函数创建的,这不同于linux使用fork函数从权级为0的进程开始创建子进程,基本上是动态的,而μc的任务数据如栈是静态初始化在全局数据段的,在创建的时候与任务关联起来

点击(此处)折叠或打开

  1. /*
  2. *********************************************************************************************************
  3. * CREATE A TASK
  4. *
  5. * Description: This function is used to have uC/OS-II manage the execution of a task. Tasks can either
  6. * be created prior to the start of multitasking or by a running task. A task cannot be
  7. * created by an ISR.
  8. *
  9. * Arguments : task is a pointer to the task's code
  10. *
  11. * p_arg is a pointer to an optional data area which can be used to pass parameters to
  12. * the task when the task first executes. Where the task is concerned it thinks
  13. * it was invoked and passed the argument 'p_arg' as follows:
  14. *
  15. * void Task (void *p_arg)
  16. * {
  17. * for (;;) {
  18. * Task code;
  19. * }
  20. * }
  21. *
  22. * ptos is a pointer to the task's top of stack. If the configuration constant
  23. * OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high
  24. * memory to low memory). 'pstk' will thus point to the highest (valid) memory
  25. * location of the stack. If OS_STK_GROWTH is set to 0, 'pstk' will point to the
  26. * lowest memory location of the stack and the stack will grow with increasing
  27. * memory locations.
  28. *
  29. * prio is the task's priority. A unique priority MUST be assigned to each task and the
  30. * lower the number, the higher the priority.
  31. *
  32. * Returns : OS_NO_ERR if the function was successful.
  33. * OS_PRIO_EXIT if the task priority already exist
  34. * (each task MUST have a unique priority).
  35. * OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
  36. * (i.e. >= OS_LOWEST_PRIO)
  37. * OS_ERR_TASK_CREATE_ISR if you tried to create a task from an ISR.
  38. *********************************************************************************************************
  39. */

  40. #if OS_TASK_CREATE_EN > 0
  41. INT8U OSTaskCreate (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio)
  42. {
  43.     OS_STK *psp;
  44.     INT8U err;
  45. #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
  46.     OS_CPU_SR cpu_sr = 0;
  47. #endif



  48. #if OS_ARG_CHK_EN > 0
  49.     if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */
  50.         return (OS_PRIO_INVALID);
  51.     }
  52. #endif
  53.     OS_ENTER_CRITICAL();
  54.     if (OSIntNesting > 0) { /* Make sure we don't create the task from within an ISR */
  55.         OS_EXIT_CRITICAL();
  56.         return (OS_ERR_TASK_CREATE_ISR);
  57.     }
  58.     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */
  59.         OSTCBPrioTbl[prio] = (OS_TCB *)1; /* Reserve the priority to prevent others from doing ... */
  60.                                              /* ... the same thing until task is created. */
  61.         OS_EXIT_CRITICAL();
  62.         psp = OSTaskStkInit(task, p_arg, ptos, 0); /* Initialize the task's stack */
  63.         err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);
  64.         if (err == OS_NO_ERR) {
  65.             if (OSRunning == OS_TRUE) { /* Find highest priority task if multitasking has started */
  66.                 OS_Sched();
  67.             }
  68.         } else {
  69.             OS_ENTER_CRITICAL();
  70.             OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */
  71.             OS_EXIT_CRITICAL();
  72.         }
  73.         return (err);
  74.     }
  75.     OS_EXIT_CRITICAL();
  76.     return (OS_PRIO_EXIST);
  77. }
  78. #endif

初始化阶段,初始化一个元素栈指针,一个err变量,中断相关CPU状态变量
检查阶段,检查优先级是不是超出LOW的范围或者idle的范围
执行阶段,
关中断,检查是否中断嵌套,是否在中断中执行,
检查相应的优先级的TCB是否存在,如果不存在,即OSTCBPrioTbl[prio] == (OS_TCB *)0
那么执行OSTCBPrioTbl[prio] = (OS_TCB *)1
开中断
 
初始化栈函数 psp = OSTaskStkInit(task, p_arg, ptos, 0);

点击(此处)折叠或打开

  1. /*
  2. *********************************************************************************************************
  3. * INITIALIZE A TASK'S STACK
  4. *
  5. * Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
  6. * stack frame of the task being created. This function is highly processor specific.
  7. *
  8. * Arguments : task is a pointer to the task code
  9. *
  10. * p_arg is a pointer to a user supplied data area that will be passed to the task
  11. * when the task first executes.
  12. *
  13. * ptos is a pointer to the top of stack. It is assumed that 'ptos' points to
  14. * a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then
  15. * 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if
  16. * OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
  17. * of the stack.
  18. *
  19. * opt specifies options that can be used to alter the behavior of OSTaskStkInit().
  20. * (see uCOS_II.H for OS_TASK_OPT_???).
  21. *
  22. * Returns : Always returns the location of the new top-of-stack' once the processor registers have
  23. * been placed on the stack in the proper order.
  24. *
  25. * Note(s) : 1) Interrupts are enabled when your task starts executing.
  26. * 2) All tasks run in SVC mode.
  27. *********************************************************************************************************
  28. */

  29. OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt)
  30. {
  31.     OS_STK *stk;

  32.     opt = opt; /* 'opt' is not used, prevent warning */
  33.     
  34.     stk = ptos; /* Load stack pointer */
  35.     
  36.     *(stk) = (OS_STK)task; /* Entry Point */
  37.     *(--stk) = (INT32U)0;     /* LR */
  38.     *(--stk) = (INT32U)0;     /* R12 */
  39.     *(--stk) = (INT32U)0;     /* R11 */
  40.     *(--stk) = (INT32U)0;     /* R10 */
  41.     *(--stk) = (INT32U)0;     /* R9 */
  42.     *(--stk) = (INT32U)0;     /* R8 */
  43.     *(--stk) = (INT32U)0;     /* R7 */
  44.     *(--stk) = (INT32U)0;     /* R6 */
  45.     *(--stk) = (INT32U)0;     /* R5 */
  46.     *(--stk) = (INT32U)0;     /* R4 */
  47.     *(--stk) = (INT32U)0;     /* R3 */
  48.     *(--stk) = (INT32U)0;     /* R2 */
  49.     *(--stk) = (INT32U)0;     /* R1 */
  50.     *(--stk) = (INT32U)p_arg;        /* R0 : argument */
  51.     *(--stk) = (INT32U)0x00000013L; /* CPSR (SVC mode, Enable both IRQ and FIQ interrupts) */
  52.                                      
  53.     return (stk);
  54. }
这个函数有四个参数,第一个参数是指向task代码的指针
第二个参数是指向参数的指针,将参数指针存放在R0的位置*(--stk) = (INT32U)p_arg;
第三个参数,是指向栈顶的指针,ARM是从高地址到低地址栈,结构是从最高地址开始,向下存放数据
第四个参数,是不使用的opt选项参数,在uCOS_II.H中有OS_TASK_OPT_???相关的介绍
这些设置好的数据,应该是用来保存任务切换时的cpu寄存器的数据,也就是说这个初始化和栈的使用都是和选用的cpu相关的,那么在调度的时候也会不同!
 
将栈初始化好之后返回栈指向可使用地址的指针
 
然后是创建TCB的函数,这个函数应该是创建一个task最重要的一步,一个TCB对应一个prio对应一个task,TCB中保存着task所有的信息

点击(此处)折叠或打开

  1. /*
  2. *********************************************************************************************************
  3. * INITIALIZE TCB
  4. *
  5. * Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when
  6. * a task is created (see OSTaskCreate() and OSTaskCreateExt()).
  7. *
  8. * Arguments : prio is the priority of the task being created
  9. *
  10. * ptos is a pointer to the task's top-of-stack assuming that the CPU registers
  11. * have been placed on the stack. Note that the top-of-stack corresponds to a
  12. * 'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory
  13. * location if OS_STK_GROWTH is set to 0. Note that stack growth is CPU
  14. * specific.
  15. *
  16. * pbos is a pointer to the bottom of stack. A NULL pointer is passed if called by
  17. * 'OSTaskCreate()'.
  18. *
  19. * id is the task's ID (0..65535)
  20. *
  21. * stk_size is the size of the stack (in 'stack units'). If the stack units are INT8Us
  22. * then, 'stk_size' contains the number of bytes for the stack. If the stack
  23. * units are INT32Us then, the stack contains '4 * stk_size' bytes. The stack
  24. * units are established by the #define constant OS_STK which is CPU
  25. * specific. 'stk_size' is 0 if called by 'OSTaskCreate()'.
  26. *
  27. * pext is a pointer to a user supplied memory area that is used to extend the task
  28. * control block. This allows you to store the contents of floating-point
  29. * registers, MMU registers or anything else you could find useful during a
  30. * context switch. You can even assign a name to each task and store this name
  31. * in this TCB extension. A NULL pointer is passed if called by OSTaskCreate().
  32. *
  33. * opt options as passed to 'OSTaskCreateExt()' or,
  34. * 0 if called from 'OSTaskCreate()'.
  35. *
  36. * Returns : OS_NO_ERR if the call was successful
  37. * OS_NO_MORE_TCB if there are no more free TCBs to be allocated and thus, the task cannot
  38. * be created.
  39. *
  40. * Note : This function is INTERNAL to uC/OS-II and your application should not call it.
  41. *********************************************************************************************************
  42. */

  43. INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
  44. {
  45.     OS_TCB *ptcb;
  46. #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
  47.     OS_CPU_SR cpu_sr = 0;
  48. #endif



  49.     OS_ENTER_CRITICAL();
  50.     ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */
  51.     if (ptcb != (OS_TCB *)0) {
  52.         OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */
  53.         OS_EXIT_CRITICAL();
  54.         ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB */
  55.         ptcb->OSTCBPrio = prio; /* Load task priority into TCB */
  56.         ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */
  57.         ptcb->OSTCBPendTO = OS_FALSE; /* Clear the Pend timeout flag */
  58.         ptcb->OSTCBDly = 0; /* Task is not delayed */

  59. #if OS_TASK_CREATE_EXT_EN > 0
  60.         ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension */
  61.         ptcb->OSTCBStkSize = stk_size; /* Store stack size */
  62.         ptcb->OSTCBStkBottom = pbos; /* Store pointer to bottom of stack */
  63.         ptcb->OSTCBOpt = opt; /* Store task options */
  64.         ptcb->OSTCBId = id; /* Store task ID */
  65. #else
  66.         pext = pext; /* Prevent compiler warning if not used */
  67.         stk_size = stk_size;
  68.         pbos = pbos;
  69.         opt = opt;
  70.         id = id;
  71. #endif

  72. #if OS_TASK_DEL_EN > 0
  73.         ptcb->OSTCBDelReq = OS_NO_ERR;
  74. #endif

  75. #if OS_LOWEST_PRIO <= 63
  76.         ptcb->OSTCBY = (INT8U)(prio >> 3); /* Pre-compute X, Y, BitX and BitY */
  77.         ptcb->OSTCBBitY = (INT8U)(1 << ptcb->OSTCBY);
  78.         ptcb->OSTCBX = (INT8U)(prio & 0x07);
  79.         ptcb->OSTCBBitX = (INT8U)(1 << ptcb->OSTCBX);
  80. #else
  81.         ptcb->OSTCBY = (INT8U)((prio >> 4) & 0xFF);/* Pre-compute X, Y, BitX and BitY */
  82.         ptcb->OSTCBBitY = (INT16U)(1 << ptcb->OSTCBY);
  83.         ptcb->OSTCBX = (INT8U)(prio & 0x0F);
  84.         ptcb->OSTCBBitX = (INT16U)(1 << ptcb->OSTCBX);
  85. #endif

  86. #if OS_EVENT_EN
  87.         ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event */
  88. #endif

  89. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
  90.         ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* Task is not pending on an event flag */
  91. #endif

  92. #if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
  93.         ptcb->OSTCBMsg = (void *)0; /* No message received */
  94. #endif

  95. #if OS_TASK_PROFILE_EN > 0
  96.         ptcb->OSTCBCtxSwCtr = 0L; /* Initialize profiling variables */
  97.         ptcb->OSTCBCyclesStart = 0L;
  98.         ptcb->OSTCBCyclesTot = 0L;
  99.         ptcb->OSTCBStkBase = (OS_STK *)0;
  100.         ptcb->OSTCBStkUsed = 0L;
  101. #endif

  102. #if OS_TASK_NAME_SIZE > 1
  103.         ptcb->OSTCBTaskName[0] = '?'; /* Unknown name at task creation */
  104.         ptcb->OSTCBTaskName[1] = OS_ASCII_NUL;
  105. #endif

  106. #if OS_VERSION >= 204
  107.         OSTCBInitHook(ptcb);
  108. #endif

  109.         OSTaskCreateHook(ptcb); /* Call user defined hook */

  110.         OS_ENTER_CRITICAL();
  111.         OSTCBPrioTbl[prio] = ptcb;
  112.         ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */
  113.         ptcb->OSTCBPrev = (OS_TCB *)0;
  114.         if (OSTCBList != (OS_TCB *)0) {
  115.             OSTCBList->OSTCBPrev = ptcb;
  116.         }
  117.         OSTCBList = ptcb;
  118.         OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
  119.         OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  120.         OSTaskCtr++; /* Increment the #tasks counter */
  121.         OS_EXIT_CRITICAL();
  122.         return (OS_NO_ERR);
  123.     }
  124.     OS_EXIT_CRITICAL();
  125.     return (OS_NO_MORE_TCB);
  126. }

我们来详细的看看这一部分代码:
第一步
关中断
ptcb = OSTCBFreeList; 从系统里面取得一个没有使用的TCB块
如果获取成功,OSTCBFreeList = ptcb->OSTCBNext;
开中断
初始化栈地址,优先级,运行状态,等待状态,Delay等待时间,
如果使能Ext,那么还有附加数据指针,栈大小,栈底指针,TCB选项,TCBID的初始化
如果没有使能Ext那么这些变量都作为局部变量不使用
 
初始化就绪表比较使用到的,XYbitX和bitY变量,用来快速查找就绪表
 ptcb->OSTCBY         = (INT8U)(prio >> 3);   /* Pre-compute X, Y, BitX and BitY */
 ptcb->OSTCBBitY      = (INT8U)(1 << ptcb->OSTCBY);
 ptcb->OSTCBX         = (INT8U)(prio & 0x07);
 ptcb->OSTCBBitX      = (INT8U)(1 << ptcb->OSTCBX);
 
初始化事件关联 ptcb->OSTCBEventPtr  = (OS_EVENT *)0;
 
ptcb->OSTCBFlagNode初始化flag
ptcb->OSTCBMsg初始化消息邮箱 队列
初始化分析数据
 
关中断,将初始化好的TCB赋值给OSTCBPrioTbl[prio],这个列表中存放的是已经建立好的TCB指针,注意是指针数组,
OS_EXT  OS_TCB           *OSTCBCur;  /* Pointer to currently running TCB         */
OS_EXT  OS_TCB           *OSTCBFreeList; /* Pointer to list of free TCBs             */
OS_EXT  OS_TCB           *OSTCBHighRdy; /* Pointer to highest priority TCB R-to-R   */
OS_EXT  OS_TCB           *OSTCBList;/* Pointer to doubly linked list of TCBs    */
OS_EXT  OS_TCB           *OSTCBPrioTbl[OS_LOWEST_PRIO + 1];/* Table of pointers to created TCBs*/
OS_EXT  OS_TCB            OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS];/* Table of TCBs  */
这是几种TCB的链表和数组,注意,只有最后一个OSTCBTbl数组才是真正的元素为TCB的数组,其他的都是指针和指针数组,都是指向这个数组的元素的指针构成的数据!
 
将当前的TCB加入双量表OSTCBList的表尾,next指向NULL
将就绪表的相应位置为就绪
taskctr自加
开中断
返回OS_NO_ERR
 
从TCB初始化函数跳出来返回任务建立函数
如果建立返回值为OS_NO_ERR且running标志位为true,开始调度
如果不是,建立失败返回err变量
 
明天看调度函数!
阅读(2346) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~