μ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.     }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值