μC/OS-II任务管理中的主要函数解析

μC/OS-II中,任务是基本的执行单元,所以任务如何管理对于基于μC/OS-II系统的驱动的编写是很关键的,下面就来浅析几个主要的任务管理函数的源码。其任务管理函数主要就在源码目录的Os_task.c中。

首先先来看一下任务是如何创建的,μC/OS-II中最基本的任务创建函数是OSTaskCreate ()函数,它的源码如下:

  1. #if OS_TASK_CREATE_EN > 0  
  2. INT8U  OSTaskCreate (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio)  
  3. {  
  4.     OS_STK    *psp;  
  5.     INT8U      err;  
  6. #if OS_CRITICAL_METHOD == 3                  /* Allocate storage for CPU status register               */  
  7.     OS_CPU_SR  cpu_sr = 0;  
  8. #endif  
  9.   
  10.   
  11.   
  12. #if OS_ARG_CHK_EN > 0  
  13.     if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */  
  14.         return (OS_PRIO_INVALID);  
  15.     }  
  16. #endif  
  17.     OS_ENTER_CRITICAL();  
  18.     if (OSIntNesting > 0) {                  /* Make sure we don't create the task from within an ISR  */  
  19.         OS_EXIT_CRITICAL();  
  20.         return (OS_ERR_TASK_CREATE_ISR);  
  21.     }  
  22.     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority  */  
  23.         OSTCBPrioTbl[prio] = (OS_TCB *)1;    /* Reserve the priority to prevent others from doing ...  */  
  24.                                              /* ... the same thing until task is created.              */  
  25.         OS_EXIT_CRITICAL();  
  26.         psp = OSTaskStkInit(task, p_arg, ptos, 0);              /* Initialize the task's stack         */  
  27.         err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);  
  28.         if (err == OS_NO_ERR) {  
  29.             if (OSRunning == TRUE) {         /* Find highest priority task if multitasking has started */  
  30.                 OS_Sched();  
  31.             }  
  32.         } else {  
  33.             OS_ENTER_CRITICAL();  
  34.             OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others                 */  
  35.             OS_EXIT_CRITICAL();  
  36.         }  
  37.         return (err);  
  38.     }  
  39.     OS_EXIT_CRITICAL();  
  40.     return (OS_PRIO_EXIST);  
  41. }  
  42. #endif  
先来看前面一段:
  1. #if OS_CRITICAL_METHOD == 3                  /* Allocate storage for CPU status register               */  
  2.     OS_CPU_SR  cpu_sr = 0;  
  3. #endif  

这个事进入临界状态方法的一个选择,一般在ARM中选择的都是第三种,其是把寄存器的值保存到临界变量cpu_sr中。

  1. #define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}  
  2. #define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}  

上面就是进入临界状态和退出临界状态的方法,首先通过函数将寄存器中的值保存在cpu_sr中,然后在退出临界状态时再将寄存器的值恢复。

  1. #if OS_ARG_CHK_EN > 0  
  2.     if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */  
  3.         return (OS_PRIO_INVALID);  
  4.     }  
  5. #endif  
上面这一段是检测任务的优先级的值是否在规定的范围之内。
  1. OS_ENTER_CRITICAL();  
  2.     if (OSIntNesting > 0) {                  /* Make sure we don't create the task from within an ISR  OSIntNesting为中断嵌套次数,没有中断则为0*/  
  3.         OS_EXIT_CRITICAL();  
  4.         return (OS_ERR_TASK_CREATE_ISR);  
  5.     }  
  6.     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority  */  
  7.         OSTCBPrioTbl[prio] = (OS_TCB *)1;    /* Reserve the priority to prevent others from doing ...  */  
  8.                                              /* ... the same thing until task is created.              */  
  9.         OS_EXIT_CRITICAL();  
  10.         psp = OSTaskStkInit(task, p_arg, ptos, 0);              /* Initialize the task's stack         */  
  11.         err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);  
  12.         if (err == OS_NO_ERR) {  
  13.             if (OSRunning == TRUE) {         /* Find highest priority task if multitasking has started */  
  14.                 OS_Sched();  
  15.             }  
  16.         } else {  
  17.             OS_ENTER_CRITICAL();  
  18.             OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others                 */  
  19.             OS_EXIT_CRITICAL();  
  20.         }  
  21.         return (err);  
  22.     }  
  23.     OS_EXIT_CRITICAL();  
  24.     return (OS_PRIO_EXIST);  
  25. }  
上 面首先是判断是否在中断服务程序中执行此任务,如果是进入中断的话则返回错误。然后再检查任务的优先级是否已经存在,如果存在的话返回优先级已经存在的错 误提示,如果不存在,则注册此优先级。下面则由函数OSTaskStkInit()初始化任务栈空间,再由函数OS_TCBInit()初始化任务控制 块,如果任务快初始化失败,则释放注册的优先级占用。然后检测CPU是否在运行状态,如果在运行,则调度优先级最高的任务。感兴趣的可以把把初始化任务栈 和TCB的函数调出来看看。

下面我们再来看OSTaskCreate()的升级版OSTaskCreateExt()函数:

  1. #if OS_TASK_CREATE_EXT_EN > 0  
  2. INT8U  OSTaskCreateExt (void   (*task)(void *p_arg),      //指向任务代码的指针  
  3.                         void    *p_arg,                   //指向传递给任务的参数的指针  
  4.                         OS_STK  *ptos,                    //指向栈顶指针  
  5.                         INT8U    prio,                    //任务优先级  
  6.                         INT16U   id,                      //任务ID值  
  7.                         OS_STK  *pbos,                    //任务栈底指针  
  8.                         INT32U   stk_size,                //任务栈单元个数  
  9.                         void    *pext,                    //任务控制块中扩展部分数据的位置  
  10.                         INT16U   opt)                     //任务栈初始化选项  
  11. {  
  12.     OS_STK    *psp;  
  13.     INT8U      err;  
  14. #if OS_CRITICAL_METHOD == 3                  /* Allocate storage for CPU status register               */  
  15.     OS_CPU_SR  cpu_sr = 0;  
  16. #endif  
  17.   
  18.   
  19.   
  20. #if OS_ARG_CHK_EN > 0  
  21.     if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */  
  22.         return (OS_PRIO_INVALID);  
  23.     }  
  24. #endif  
  25.     OS_ENTER_CRITICAL();  
  26.     if (OSIntNesting > 0) {                  /* Make sure we don't create the task from within an ISR  */  
  27.         OS_EXIT_CRITICAL();  
  28.         return (OS_ERR_TASK_CREATE_ISR);  
  29.     }  
  30.     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority  */  
  31.         OSTCBPrioTbl[prio] = (OS_TCB *)1;    /* Reserve the priority to prevent others from doing ...  */  
  32.                                              /* ... the same thing until task is created.              */  
  33.         OS_EXIT_CRITICAL();  
  34.   
  35.         OS_TaskStkClr(pbos, stk_size, opt);                    /* Clear the task stack (if needed)     */  
  36.   
  37.         psp = OSTaskStkInit(task, p_arg, ptos, opt);           /* Initialize the task's stack          */  
  38.         err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt);  
  39.         if (err == OS_NO_ERR) {  
  40.             if (OSRunning == TRUE) {                           /* Find HPT if multitasking has started */  
  41.                 OS_Sched();  
  42.             }  
  43.         } else {  
  44.             OS_ENTER_CRITICAL();  
  45.             OSTCBPrioTbl[prio] = (OS_TCB *)0;                  /* Make this priority avail. to others  */  
  46.             OS_EXIT_CRITICAL();  
  47.         }  
  48.         return (err);  
  49.     }  
  50.     OS_EXIT_CRITICAL();  
  51.     return (OS_PRIO_EXIST);  
  52. }  
  53. #endif  
先来看下opt的几种定义:
  1. /* 
  2. ********************************************************************************************************* 
  3. *                                 TASK OPTIONS (see OSTaskCreateExt()) 
  4. ********************************************************************************************************* 
  5. */  
  6. #define  OS_TASK_OPT_NONE        0x0000u    /* NO option selected                                      */  
  7. #define  OS_TASK_OPT_STK_CHK     0x0001u    /* Enable stack checking for the task                      */  
  8. #define  OS_TASK_OPT_STK_CLR     0x0002u    /* Clear the stack when the task is create                 */  
  9. #define  OS_TASK_OPT_SAVE_FP     0x0004u    /* Save the contents of any floating-point registers       */  
  10.   
  11. /*  
分别是没有选项位置、使能栈检查、创建栈时初始化为0、保存所有浮点指针寄存器的内容。

代码前面和OSTaskCreate()大同小异,都是对优先级中断等的一些检测,初始化栈、任务控制块、引发任务调度。其中OS_TaskStkClr(0是清除栈空间,根据清理选项和栈增长方向逐个字节将栈空间初始化为0,其原型为:

  1. #if OS_TASK_CREATE_EXT_EN > 0  
  2. void  OS_TaskStkClr (OS_STK *pbos, INT32U size, INT16U opt)  
  3. {  
  4.     if ((opt & OS_TASK_OPT_STK_CHK) != 0x0000) {       /* See if stack checking has been enabled       */  
  5.         if ((opt & OS_TASK_OPT_STK_CLR) != 0x0000) {   /* See if stack needs to be cleared             */  
  6. #if OS_STK_GROWTH == 1  
  7.             while (size > 0) {                         /* Stack grows from HIGH to LOW memory          */  
  8.                 size--;  
  9.                 *pbos++ = (OS_STK)0;                   /* Clear from bottom of stack and up!           */  
  10.             }  
  11. #else  
  12.             while (size > 0) {                         /* Stack grows from LOW to HIGH memory          */  
  13.                 size--;  
  14.                 *pbos-- = (OS_STK)0;                   /* Clear from bottom of stack and down          */  
  15.             }  
  16. #endif  
  17.         }  
  18.     }  
  19. }  
  20.   
  21. #endif  


 

接下来看删除任务函数:

  1. #if OS_TASK_DEL_EN > 0  
  2. INT8U  OSTaskDel (INT8U prio)  
  3. {  
  4. #if OS_EVENT_EN  
  5.     OS_EVENT     *pevent;  
  6. #endif  
  7. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)  
  8.     OS_FLAG_NODE *pnode;  
  9. #endif  
  10.     OS_TCB       *ptcb;  
  11.     INT8U         y;  
  12. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */  
  13.     OS_CPU_SR     cpu_sr = 0;  
  14. #endif  
  15.   
  16.   
  17.   
  18.     if (OSIntNesting > 0) {                                     /* See if trying to delete from ISR    */  
  19.         return (OS_TASK_DEL_ISR);  
  20.     }  
  21. #if OS_ARG_CHK_EN > 0  
  22.     if (prio == OS_IDLE_PRIO) {                                 /* Not allowed to delete idle task     */  
  23.         return (OS_TASK_DEL_IDLE);  
  24.     }  
  25.     if (prio >= OS_LOWEST_PRIO) {                               /* Task priority valid ?               */  
  26.         if (prio != OS_PRIO_SELF) {  
  27.             return (OS_PRIO_INVALID);  
  28.         }  
  29.     }  
  30. #endif  
  31.     OS_ENTER_CRITICAL();                                        // 标记1  
  32.     if (prio == OS_PRIO_SELF) {                                 /* See if requesting to delete self    如果是删除自己*/  
  33.         prio = OSTCBCur->OSTCBPrio;                             /* Set priority to delete to current   获取自己的优先级*/  
  34.     }  
  35.     ptcb = OSTCBPrioTbl[prio];                                  /*查找要删除任务的任务控制块 */  
  36.     if (ptcb == (OS_TCB *)0) {                                  /* Task to delete must exist           */  
  37.         OS_EXIT_CRITICAL();  
  38.         return (OS_TASK_DEL_ERR);  
  39.     }  
  40.     if (ptcb == (OS_TCB *)1) {                                  /* Must not be assigned to Mutex       */  
  41.         OS_EXIT_CRITICAL();  
  42.         return (OS_TASK_NOT_EXIST);  
  43.     }  
  44.     y            =  ptcb->OSTCBY;                           /*获取就绪表中对应的行*/  
  45.     OSRdyTbl[y] &= ~ptcb->OSTCBBitX;                        /*清除就绪表中对应行的位*/  
  46.     if (OSRdyTbl[y] == 0) {                                     /* Make task not ready                 */  
  47.         OSRdyGrp &= ~ptcb->OSTCBBitY;  
  48.     }  
  49. #if OS_EVENT_EN  
  50.     pevent = ptcb->OSTCBEventPtr;                               /*如果定义了事件,找到任务所等待的事件*/  
  51.     if (pevent != (OS_EVENT *)0) {                              /* If task is waiting on event         */  
  52.         pevent->OSEventTbl[y] &= ~ptcb->OSTCBBitX;          /*从该事件的等待列表中删除该任务*/  
  53.         if (pevent->OSEventTbl[y] == 0) {                       /* ... remove task from ...            */  
  54.             pevent->OSEventGrp &= ~ptcb->OSTCBBitY;             /* ... event ctrl block                */  
  55.         }  
  56.     }  
  57. #endif  
  58. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)  
  59.     pnode = ptcb->OSTCBFlagNode;  
  60.     if (pnode != (OS_FLAG_NODE *)0) {                           /* If task is waiting on event flag  时间组标志  */  
  61.         OS_FlagUnlink(pnode);                                   /* Remove from wait list               */  
  62.     }  
  63. #endif  
  64.     ptcb->OSTCBDly    = 0;                                      /* Prevent OSTimeTick() from updating 置等待时间为0,放置系统时钟中断更新此值 */  
  65.     ptcb->OSTCBStat   = OS_STAT_RDY;                            /* Prevent task from being resumed  防止任务在此运行   */  
  66.     ptcb->OSTCBPendTO = FALSE;                                  /*清除等待超时标志*/  
  67.     if (OSLockNesting < 255u) {                             /* Make sure we don't context switch 禁止任务调度  */  
  68.         OSLockNesting++;  
  69.     }  
  70.     OS_EXIT_CRITICAL();                                         /* 标记2 Enabling INT. ignores next instruc. */  
  71.     OS_Dummy();                                                 /* ... Dummy ensures that INTs will be 等待一个时间周期*/  
  72.     OS_ENTER_CRITICAL();                                        /*标记3 ... disabled HERE!                  */  
  73.     if (OSLockNesting > 0) {                                    /* Remove context switch lock          */  
  74.         OSLockNesting--;  
  75.     }  
  76.     OSTaskDelHook(ptcb);                                        /* Call user defined hook              */  
  77.     OSTaskCtr--;                                                /* One less task being managed 任务计数器减1        */  
  78.     OSTCBPrioTbl[prio] = (OS_TCB *)0;                           /* Clear old priority entry   清除该优先级任务控制块入口     */  
  79.     if (ptcb->OSTCBPrev == (OS_TCB *)0) {                       /* Remove from TCB chain  如果当前任务是TCB链表的第一个成员   */  
  80.         ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;               /*从TCB链表中删除此控制块*/  
  81.         OSTCBList                  = ptcb->OSTCBNext;  
  82.     } else {                                                    /*如果不是第一个成员*/  
  83.         ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;  
  84.         ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;  
  85.     }  
  86.     ptcb->OSTCBNext   = OSTCBFreeList;                          /* Return TCB to free TCB list         */  
  87.     OSTCBFreeList     = ptcb;  
  88. #if OS_TASK_NAME_SIZE > 1                                       /*如果允许设置任务名*/  
  89.     ptcb->OSTCBTaskName[0] = '?';                               /* Unknown name                        */  
  90.     ptcb->OSTCBTaskName[1] = OS_ASCII_NUL;  
  91. #endif  
  92.     OS_EXIT_CRITICAL();                                         //标记4  
  93.     OS_Sched();                                                 /* Find new highest priority task      */  
  94.     return (OS_NO_ERR);  
  95. }  
  96. #endif  
这个函数由其参数就可以看出,删除任务实际上就是删除任务的优先级,借此可以看出,任务是由优先级来标识的。

首先还是进行任务的检测,如果在中断中,或者优先级不存在,或者空闲任务等,就不会执行删除任务。

从上面代码的标记1开始进入临界状态,禁止中断,如果直到标记4退出临界区,开中断, 这个时间会比较长,不利于高实时性。所以在标记2的地方开中断,响应等待的中断,但是此时可能会引发新的调度,而无法返回当前任务,导致后续的代码没有得 到执行,所以这里将OSLockNesting加1,保证只会响应中断而不会发生任务调度。之后再次关中断了以后,将OSLockNesting减1,恢 复原值。

下面看请求删除任务:

  1. #if OS_TASK_DEL_EN > 0  
  2. INT8U  OSTaskDelReq (INT8U prio)  
  3. {  
  4.     INT8U      stat;  
  5.     OS_TCB    *ptcb;  
  6. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */  
  7.     OS_CPU_SR  cpu_sr = 0;  
  8. #endif  
  9.   
  10.   
  11.   
  12. #if OS_ARG_CHK_EN > 0  
  13.     if (prio == OS_IDLE_PRIO) {                                 /* Not allowed to delete idle task     */  
  14.         return (OS_TASK_DEL_IDLE);  
  15.     }  
  16.     if (prio >= OS_LOWEST_PRIO) {                                /* Task priority valid ?               */  
  17.         if (prio != OS_PRIO_SELF) {  
  18.             return (OS_PRIO_INVALID);  
  19.         }  
  20.     }  
  21. #endif  
  22.     if (prio == OS_PRIO_SELF) {                                 /* See if a task is requesting to ...  */  
  23.         OS_ENTER_CRITICAL();                                    /* ... this task to delete itself      */  
  24.         stat = OSTCBCur->OSTCBDelReq;                           /* Return request status to caller     */  
  25.         OS_EXIT_CRITICAL();  
  26.         return (stat);  
  27.     }  
  28.     OS_ENTER_CRITICAL();  
  29.     ptcb = OSTCBPrioTbl[prio];  
  30.     if (ptcb == (OS_TCB *)0) {                                  /* Task to delete must exist           */  
  31.         OS_EXIT_CRITICAL();  
  32.         return (OS_TASK_NOT_EXIST);                             /* Task must already be deleted        */  
  33.     }  
  34.     if (ptcb == (OS_TCB *)1) {                                  /* Must NOT be assigned to a Mutex     */  
  35.         OS_EXIT_CRITICAL();  
  36.         return (OS_TASK_DEL_ERR);  
  37.     }  
  38.     ptcb->OSTCBDelReq = OS_TASK_DEL_REQ;                        /* Set flag indicating task to be DEL. */  
  39.     OS_EXIT_CRITICAL();  
  40.     return (OS_NO_ERR);  
  41. }  
  42. #endif  
这个删除任务的主要功能就是删除任务本身,该任务在执行时释放申请的资源,然后再删除自己。

前面还是一样,检测参数,后面就检测是否要求删除自己,如果是的话返回存储在TCB中的标志。

最后,将任务控制块的OSTCBDelReq的值设为OS_TASK_DEL_REQ,当删除任务被调度的时候,会检测这个值,当这个值是OS_TASK_DEL_REQ时,则就会调用OSTaskDel ()函数。

接下来我们继续看Os_task.c中的任务管理函数。

获取任务名称:

  1. #if OS_TASK_NAME_SIZE > 1  
  2. INT8U  OSTaskNameGet (INT8U prio, INT8U *pname, INT8U *err)  
  3. {  
  4.     OS_TCB    *ptcb;  
  5.     INT8U      len;  
  6. #if OS_CRITICAL_METHOD == 3                              /* Allocate storage for CPU status register   */  
  7.     OS_CPU_SR  cpu_sr = 0;  
  8. #endif  
  9.   
  10.   
  11.   
  12. #if OS_ARG_CHK_EN > 0  
  13.     if (err == (INT8U *)0) {                             /* Validate 'err'                             */  
  14.         return (0);  
  15.     }  
  16.     if (prio > OS_LOWEST_PRIO) {                         /* Task priority valid ?                      */  
  17.         if (prio != OS_PRIO_SELF) {  
  18.             *err = OS_PRIO_INVALID;                      /* No                                         */  
  19.             return (0);  
  20.         }  
  21.     }  
  22.     if (pname == (INT8U *)0) {                             /* Is 'pname' a NULL pointer?   如果pname为空             */  
  23.         *err = OS_ERR_PNAME_NULL;                         /* Yes                                       */  
  24.         return (0);  
  25.     }  
  26. #endif  
  27.     OS_ENTER_CRITICAL();  
  28.     if (prio == OS_PRIO_SELF) {                           /* See if caller desires it's own name       */  
  29.         prio = OSTCBCur->OSTCBPrio;  
  30.     }  
  31.     ptcb = OSTCBPrioTbl[prio];  
  32.     if (ptcb == (OS_TCB *)0) {                            /* Does task exist?                          */  
  33.         OS_EXIT_CRITICAL();                               /* No                                        */  
  34.         *err = OS_TASK_NOT_EXIST;  
  35.         return (0);  
  36.     }  
  37.     if (ptcb == (OS_TCB *)1) {                            /* Task assigned to a Mutex?                 */  
  38.         OS_EXIT_CRITICAL();                               /* Yes                                       */  
  39.         *err = OS_TASK_NOT_EXIST;  
  40.         return (0);  
  41.     }  
  42.     len  = OS_StrCopy(pname, ptcb->OSTCBTaskName);        /* Yes, copy name from TCB     拷贝任务名              */  
  43.     OS_EXIT_CRITICAL();  
  44.     *err = OS_NO_ERR;  
  45.     return (len);  
  46. }  
  47. #endif  

这个函数主要就是通过优先级,获取到任务的TCB信息,最后通过OS_StrCopy()函数,将任务名赋值给len,最终将其返回。

设置任务名:

  1. #if OS_TASK_NAME_SIZE > 1  
  2. void  OSTaskNameSet (INT8U prio, INT8U *pname, INT8U *err)  
  3. {  
  4.     INT8U      len;  
  5.     OS_TCB    *ptcb;  
  6. #if OS_CRITICAL_METHOD == 3                          /* Allocate storage for CPU status register       */  
  7.     OS_CPU_SR  cpu_sr = 0;  
  8. #endif  
  9.   
  10.   
  11.   
  12. #if OS_ARG_CHK_EN > 0  
  13.     if (err == (INT8U *)0) {                         /* Validate 'err'                                 */  
  14.         return;  
  15.     }  
  16.     if (prio > OS_LOWEST_PRIO) {                     /* Task priority valid ?                          */  
  17.         if (prio != OS_PRIO_SELF) {  
  18.             *err = OS_PRIO_INVALID;                  /* No                                             */  
  19.             return;  
  20.         }  
  21.     }  
  22.     if (pname == (INT8U *)0) {                        /* Is 'pname' a NULL pointer?                     */  
  23.         *err = OS_ERR_PNAME_NULL;                    /* Yes                                            */  
  24.         return;  
  25.     }  
  26. #endif  
  27.     OS_ENTER_CRITICAL();  
  28.     if (prio == OS_PRIO_SELF) {                      /* See if caller desires to set it's own name     */  
  29.         prio = OSTCBCur->OSTCBPrio;  
  30.     }  
  31.     ptcb = OSTCBPrioTbl[prio];  
  32.     if (ptcb == (OS_TCB *)0) {                       /* Does task exist?                               */  
  33.         OS_EXIT_CRITICAL();                          /* No                                             */  
  34.         *err = OS_TASK_NOT_EXIST;  
  35.         return;  
  36.     }  
  37.     if (ptcb == (OS_TCB *)1) {                       /* Task assigned to a Mutex?                      */  
  38.         OS_EXIT_CRITICAL();                          /* Yes                                            */  
  39.         *err = OS_TASK_NOT_EXIST;  
  40.         return;  
  41.     }  
  42.     len = OS_StrLen(pname);                          /* Yes, Can we fit the string in the TCB?         */  
  43.     if (len > (OS_TASK_NAME_SIZE - 1)) {             /*      No                                        */  
  44.         OS_EXIT_CRITICAL();  
  45.         *err = OS_ERR_TASK_NAME_TOO_LONG;  
  46.         return;  
  47.     }  
  48.     (void)OS_StrCopy(ptcb->OSTCBTaskName, pname);    /*      Yes, copy to TCB                          */  
  49.     OS_EXIT_CRITICAL();  
  50.     *err = OS_NO_ERR;  
  51. }  
  52. #endif  

通过OS_StrLen()函数获取预设值的名称的长度,然后检测其长度是否合理,最后通过OS_StrCopy()函数拷贝任务名到TCB中。

挂起任务:

  1. #if OS_TASK_SUSPEND_EN > 0  
  2. INT8U  OSTaskSuspend (INT8U prio)  
  3. {  
  4.     BOOLEAN    self;  
  5.     OS_TCB    *ptcb;  
  6.     INT8U      y;  
  7. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */  
  8.     OS_CPU_SR  cpu_sr = 0;  
  9. #endif  
  10.   
  11.   
  12.   
  13. #if OS_ARG_CHK_EN > 0  
  14.     if (prio == OS_IDLE_PRIO) {                                 /* Not allowed to suspend idle task    */  
  15.         return (OS_TASK_SUSPEND_IDLE);  
  16.     }  
  17.     if (prio >= OS_LOWEST_PRIO) {                                /* Task priority valid ?               */  
  18.         if (prio != OS_PRIO_SELF) {  
  19.             return (OS_PRIO_INVALID);  
  20.         }  
  21.     }  
  22. #endif  
  23.     OS_ENTER_CRITICAL();  
  24.     if (prio == OS_PRIO_SELF) {                                 /* See if suspend SELF                 */  
  25.         prio = OSTCBCur->OSTCBPrio;  
  26.         self = TRUE;  
  27.     } else if (prio == OSTCBCur->OSTCBPrio) {                   /* See if suspending self              */  
  28.         self = TRUE;  
  29.     } else {  
  30.         self = FALSE;                                           /* No suspending another task          */  
  31.     }  
  32.     ptcb = OSTCBPrioTbl[prio];  
  33.     if (ptcb == (OS_TCB *)0) {                                  /* Task to suspend must exist          */  
  34.         OS_EXIT_CRITICAL();  
  35.         return (OS_TASK_SUSPEND_PRIO);  
  36.     }  
  37.     if (ptcb == (OS_TCB *)1) {                                  /* See if assigned to Mutex            */  
  38.         OS_EXIT_CRITICAL();  
  39.         return (OS_TASK_NOT_EXIST);  
  40.     }  
  41.     y            = ptcb->OSTCBY;  
  42.     OSRdyTbl[y] &= ~ptcb->OSTCBBitX;                         /* Make task not ready                 */  
  43.     if (OSRdyTbl[y] == 0) {  
  44.         OSRdyGrp &= ~ptcb->OSTCBBitY;  
  45.     }  
  46.     ptcb->OSTCBStat |= OS_STAT_SUSPEND;                         /* Status of task is 'SUSPENDED'       */  
  47.     OS_EXIT_CRITICAL();  
  48.     if (self == TRUE) {                                         /* Context switch only if SELF         */  
  49.         OS_Sched();  
  50.     }  
  51.     return (OS_NO_ERR);  
  52. }  
  53. #endif  

这个函数主要注意self值的设定,当需要挂起的是当前任务的话,则self为TRUE,当self为TRUE时,需要进行任务调度。还有将OSTCBStat设定为OS_STAT_SUSPEND。还有要将就绪表中的任务删除。

恢复任务:

  1. #if OS_TASK_SUSPEND_EN > 0  
  2. INT8U  OSTaskResume (INT8U prio)  
  3. {  
  4.     OS_TCB    *ptcb;  
  5. #if OS_CRITICAL_METHOD == 3                                   /* Storage for CPU status register       */  
  6.     OS_CPU_SR  cpu_sr = 0;  
  7. #endif  
  8.   
  9.   
  10.   
  11. #if OS_ARG_CHK_EN > 0  
  12.     if (prio >= OS_LOWEST_PRIO) {                             /* Make sure task priority is valid      */  
  13.         return (OS_PRIO_INVALID);  
  14.     }  
  15. #endif  
  16.     OS_ENTER_CRITICAL();  
  17.     ptcb = OSTCBPrioTbl[prio];  
  18.     if (ptcb == (OS_TCB *)0) {                                /* Task to suspend must exist            */  
  19.         OS_EXIT_CRITICAL();  
  20.         return (OS_TASK_RESUME_PRIO);  
  21.     }  
  22.     if (ptcb == (OS_TCB *)1) {                                /* See if assigned to Mutex              */  
  23.         OS_EXIT_CRITICAL();  
  24.         return (OS_TASK_NOT_EXIST);  
  25.     }  
  26.     if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) { /* Task must be suspended                */  
  27.         ptcb->OSTCBStat &= ~OS_STAT_SUSPEND;               /* Remove suspension                     */  
  28.         if (ptcb->OSTCBStat == OS_STAT_RDY) {                 /* See if task is now ready              */  
  29.             if (ptcb->OSTCBDly == 0) {  
  30.                 OSRdyGrp               |= ptcb->OSTCBBitY;    /* Yes, Make task ready to run           */  
  31.                 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;  
  32.                 OS_EXIT_CRITICAL();  
  33.                 OS_Sched();  
  34.             } else {  
  35.                 OS_EXIT_CRITICAL();  
  36.             }  
  37.         } else {                                              /* Must be pending on event              */  
  38.             OS_EXIT_CRITICAL();  
  39.         }  
  40.         return (OS_NO_ERR);  
  41.     }  
  42.     OS_EXIT_CRITICAL();  
  43.     return (OS_TASK_NOT_SUSPENDED);  
  44. }  
  45. #endif  

其主要就是检测任务是否为挂起,然后更改挂起状态,并且更新就绪表。
读取任务的TCB信息:

  1. #if OS_TASK_QUERY_EN > 0  
  2. INT8U  OSTaskQuery (INT8U prio, OS_TCB *p_task_data)  
  3. {  
  4.     OS_TCB    *ptcb;  
  5. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */  
  6.     OS_CPU_SR  cpu_sr = 0;  
  7. #endif  
  8.   
  9.   
  10.   
  11. #if OS_ARG_CHK_EN > 0  
  12.     if (prio > OS_LOWEST_PRIO) {              /* Task priority valid ?                              */  
  13.         if (prio != OS_PRIO_SELF) {  
  14.             return (OS_PRIO_INVALID);  
  15.         }  
  16.     }  
  17.     if (p_task_data == (OS_TCB *)0) {            /* Validate 'p_task_data'                             */  
  18.         return (OS_ERR_PDATA_NULL);  
  19.     }  
  20. #endif  
  21.     OS_ENTER_CRITICAL();  
  22.     if (prio == OS_PRIO_SELF) {                  /* See if suspend SELF                                */  
  23.         prio = OSTCBCur->OSTCBPrio;  
  24.     }  
  25.     ptcb = OSTCBPrioTbl[prio];  
  26.     if (ptcb == (OS_TCB *)0) {                   /* Task to query must exist                           */  
  27.         OS_EXIT_CRITICAL();  
  28.         return (OS_PRIO_ERR);  
  29.     }  
  30.     if (ptcb == (OS_TCB *)1) {                   /* Task to query must not be assigned to a Mutex      */  
  31.         OS_EXIT_CRITICAL();  
  32.         return (OS_TASK_NOT_EXIST);  
  33.     }  
  34.                                                  /* Copy TCB into user storage area                    */  
  35.     OS_MemCopy((INT8U *)p_task_data, (INT8U *)ptcb, sizeof(OS_TCB));  
  36.     OS_EXIT_CRITICAL();  
  37.     return (OS_NO_ERR);  
  38. }  
  39. #endif  

将多选优先级的任务的TCB信息copy给指定的TCB结构体中,然后进行读取。

通过上述的许多的任务管理函数,有没有发现其实都是比较简单,他们的参数检测其实都是比较固定的,在μC/OS-II系统中,任务标识的最重要的参数是优先级,它可以标识唯一的一个任务。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值