uCOS-II函数解析

时间管理服务函数是以系统节拍为处理单位的,实际的时间与希望的时间是有误差的,最坏的情况下误差接近一个系统节拍。因此时间管理服务函数只能用在对时间精度要求不高的场合,或者时间间隔较长的场合。


1. void  OSSchedLock(void);

void  OSSchedLock (void)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif
    if (OSRunning == OS_TRUE) {                  /* Make sure multitasking is running                  */
        OS_ENTER_CRITICAL();
        if (OSIntNesting == 0) {                 /* Can't call from an ISR                             */
            if (OSLockNesting < 255u) {          /* Prevent OSLockNesting from wrapping back to 0      */
                OSLockNesting++;                 /* Increment lock nesting level                       */
            }
        }
        OS_EXIT_CRITICAL();
    }
}

这个函数又叫上锁函数,如果在一个任务里面调用了上锁函数,那么OSSched()这个任务切换函数就不会执行也就是说不会进任务调度。

调用OSSchedLock()以后,用户的应用程序不得使用任何能将现行任务挂起的系统调用。也就是说,用户程序不得调用OSMboxPend()、OSQPend()、OSSemPend()、OSTaskSuspend(OS_PR1O_SELF)、OSTimeDly()或OSTimeDlyHMSM(),直到OSLockNesting回零为止因为调度器上了锁,用户就锁住了系统,任何其它任务都不能运行。

但是上锁了任务是可以中断,若任务遇到中断,则中断函数的执行会为OSIntNesting变量加1,当中断返回时又要判断OSLockNesting是否为0,如果不为0说明系统仍被锁,直接退出中断。如果OSLockNesting为0说明系统未被锁,CPU进入任务就绪表查找优先级最高的任务。所以上锁函数执行后,CPU一直处于当前任务与中断服务函数之间的运行,直到解锁函数将OSLockNesting和OSIntNesting的值减到0时,方可解除系统锁定。

OSSchedUnlock() 取消函数上锁。



2.void  OSTimeDly (INT16U ticks);

void  OSTimeDly (INT16U ticks)
{
    INT8U      y;
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr = 0;
#endif
    if (OSIntNesting > 0) {                      /* See if trying to call from an ISR                  */
        return;
    }
    if (ticks > 0) {                             /* 0 means no delay!                                  */
        OS_ENTER_CRITICAL();
        y            =  OSTCBCur->OSTCBY;        /* Delay current task                                 */
        OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;
        if (OSRdyTbl[y] == 0) {
            OSRdyGrp &= ~OSTCBCur->OSTCBBitY;         /*取消当前任务的就绪状态
        }
        OSTCBCur->OSTCBDly = ticks;              /* 延时节拍数存入任务控制块TCB                               */
        OS_EXIT_CRITICAL();
        OS_Sched();                              /* 调度函数                           */
    }
}

      将一个任务延时若干个时钟节拍。如果延时时间大于0,系统将立即进行任务调度。延时时间的长度可从0到65535个时钟节拍。延时时间0表示不进行延时,函数将立即返回调用者。延时的具体时间依赖于系统每秒钟有多少时钟节拍(由文件OS_CFG.H中的常量OS_TICKS_PER_SEC设定): 

#define OS_TICKS_PER_SEC       1000  

   调用该函数会使uCOS-II进行一次任务调度,并且执行下一个优先级最高的就绪态任务。任务调用OSTimeDly()后,一旦规定的时间期满或者有其它的任务通过调用OSTimeDlyResume()取消了延时,它就会马上进入就绪状态。注意,只有当该任务在所有就绪任务中具有最高的优先级时,它才会立即运行。


uCOS-II函数解析_第1张图片



3.INT8U  OSTimeDlyHMSM (INT8U hours, INT8U minutes, INT8U seconds, INT16U ms);

这个函数是以小时(H)、分(M)、秒(S)和毫秒(m)四个参数来定义延时时间的,函数在内部把这些参数转换为时钟节拍,再通过单次或多次调用OSTimeDly()进行延时和任务调度,所以延时原理和调用延时函数OSTimeDly()是一样的。

uCOS-II函数解析_第2张图片


4.INT8U  OS_TCBInit(INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt);

任务控制块初始化  

描述:这个函数是uCOS-II内部函数,在建立任务时调用的初始化任务控制块OS_TCB函数,含7个参数,查看OSTaskCreate()和OSTaskCreateExt()  

初始化任务控制块TCB(优先级指针,堆栈指针,栈底指针,任务标志符,堆栈容量,扩展指针,选择项)  

   INT8U  OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)  

    {  

     #if OS_CRITICAL_METHOD == 3                                //中断函数被设定为模式3 

      OS_CPU_SR  cpu_sr;  

  1. #endif      
  2.     OS_TCB    *ptcb;                                      //定义一个PCB变量  
  3.   
  4.   
  5.     OS_ENTER_CRITICAL();                                  //关闭中断  
  6.     ptcb = OSTCBFreeList;                                 //分配一个空任务控制块给ptcb  
  7.     if (ptcb != (OS_TCB *)0) {                            //如果缓冲池有空余TCB,这个TCB被初始化  
  8.         OSTCBFreeList        = ptcb->OSTCBNext;           //指向TCB的双向链接的后链接  
  9.         OS_EXIT_CRITICAL();                               //打开中断  
  10.         ptcb->OSTCBStkPtr    = ptos;                       //指向当前TCB的栈顶指针(输入的数据)  
  11.         ptcb->OSTCBPrio      = (INT8U)prio;                //保存当前TCB的优先级别(输入的数据)  
  12.         ptcb->OSTCBStat      = OS_STAT_RDY;                //设定当前TCB的状态字(内容为(准备完毕))  
  13.         ptcb->OSTCBDly       = 0;                          //允许任务等待的最大字节节拍为0  
  14.   
  15. #if OS_TASK_CREATE_EXT_EN > 0                               //允许生成OSTaskCreateExt()函数  
  16.         ptcb->OSTCBExtPtr    = pext;                       //指向用户定义的任务控制块(扩展指针)  
  17.         ptcb->OSTCBStkSize   = stk_size;                   //设定堆栈的容量  
  18.         ptcb->OSTCBStkBottom = pbos;                       //指向堆栈栈底的指针  
  19.         ptcb->OSTCBOpt       = opt;                        //保存OS_TCB的选择项  
  20.         ptcb->OSTCBId        = id;                         //保存任务标志符  
  21. #else   //否则使用旧的参数  
  22.         pext                 = pext;                       //扩展指针  
  23.         stk_size             = stk_size;                   //堆栈的容量  
  24.         pbos                 = pbos;                       //栈底的指针  
  25.         opt                  = opt;                        //选择项  
  26.         id                   = id;                         //任务标志符  
  27. #endif  
  28.   
  29. #if OS_TASK_DEL_EN > 0           //允许生成OSTaskDel()函数代码函数  
  30.         ptcb->OSTCBDelReq    = OS_NO_ERR;                    //如果可以删除任务本身,可以从每个OS_TCB中节省出一个布尔量  
  31. #endif  
  32.   
  33.         ptcb->OSTCBY         = prio >> 3;                  //对一些参数提前运算,为了节省CPU的操作事件  
  34.         ptcb->OSTCBBitY      = OSMapTbl[ptcb->OSTCBY];  
  35.         ptcb->OSTCBX         = prio & 0x07;  
  36.         ptcb->OSTCBBitX      = OSMapTbl[ptcb->OSTCBX];  
  37.   
  38. #if OS_EVENT_EN > 0                  //如果不打算在应用程序中使用各类事件  
  39.         ptcb->OSTCBEventPtr  = (OS_EVENT *)0;              //OS_TCB中OSTCBEventPtr就不会出现  
  40. #endif  
  41.   
  42. //针对的事件为信号量,互斥型信号量,消息邮箱,消息队列,当满足版本大于2.51且事件标志允许且有最大事件标志及允许删除任务  
  43. #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)  
  44.         ptcb->OSTCBFlagNode  = (OS_FLAG_NODE *)0;          //则向事件标志节点的指针被初始化为空指针  
  45. #endif  
  46.   
  47. #if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))  
  48.         ptcb->OSTCBMsg       = (void *)0;                  //满足以上条件,指向传递给任务的消息指针为0空指针  
  49. #endif  
  50.   
  51. #if OS_VERSION >= 204            //如果版本大于2.04  
  52.         OSTCBInitHook(ptcb);                              //允许使用OSTCBInitHook(ptcb)函数,可对其加代码  
  53. #endif              //主要增加OS_TCB扩展,浮点运算,MMU寄存器,与任务相关内容,调用此程序时中断开着的  
  54.   
  55.         OSTaskCreateHook(ptcb);                            //调用户建立任务钩子程序  
  56.           
  57.         OS_ENTER_CRITICAL();  
  58.         OSTCBPrioTbl[prio] = ptcb;  
  59.         ptcb->OSTCBNext    = OSTCBList;                    //链接到任务控制块链接串  
  60.         ptcb->OSTCBPrev    = (OS_TCB *)0;  
  61.         if (OSTCBList != (OS_TCB *)0) {  
  62.             OSTCBList->OSTCBPrev = ptcb;  
  63.         }  
  64.         OSTCBList               = ptcb;                   //让该任务进入就绪表  
  65.         OSRdyGrp               |= ptcb->OSTCBBitY;         /* Make task ready to run                   */  
  66.         OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;  
  67.         OS_EXIT_CRITICAL();             //打开中断  
  68.         return (OS_NO_ERR);             //调用成功,最后让此函数返回到调用函数[OSTaskCreate()或OSTaskCreateExt()函数],  
  69.                                         //返回值表示分配到任务控块,并初始化了  
  70.     }  
  71.     OS_EXIT_CRITICAL();                 //打开中断  
  72.     return (OS_NO_MORE_TCB);            //没有更多的任务控制块被分配,将无法创建新的任务  


5.INT8U  OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio);


  1. //建立一个新任务  
  2. #if OS_TASK_CREATE_EN > 0                //允许生成OSTaskCreate()函数  
  3. INT8U  OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)  
  4. {  
  5. #if OS_CRITICAL_METHOD == 3                  //中断函数被设定为模式3  
  6.     OS_CPU_SR  cpu_sr;  
  7. #endif  
  8.     OS_STK    *psp;                         //初始化任务堆栈指针变量,返回新的栈顶指针  
  9.     INT8U      err;                         //定义(获得并定义初始化任务控制块)是否成功  
  10.   
  11.   
  12. #if OS_ARG_CHK_EN > 0                        //所有参数必须在指定的参数内  
  13.     if (prio > OS_LOWEST_PRIO) {            //检查任务优先级是否合法  
  14.         return (OS_PRIO_INVALID);           //参数指定的优先级大于OS_LOWEST_PRIO  
  15.     }  
  16. #endif  
  17.     OS_ENTER_CRITICAL();            //关闭中断  
  18.     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { //确认优先级未被使用,即就绪态为0  
  19.         OSTCBPrioTbl[prio] = (OS_TCB *)1;    //保留这个优先级,将就绪态设为1  
  20.                                               
  21.         OS_EXIT_CRITICAL();             //打开中断  
  22.         psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0);    //初始化任务堆栈  
  23.         err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);       //获得并初始化任务控制块  
  24.         if (err == OS_NO_ERR) {     //任务控制初始化成功  
  25.             OS_ENTER_CRITICAL();    //关闭中断  
  26.             OSTaskCtr++;            //任务计数器加1  
  27.             OS_EXIT_CRITICAL();     //打开中断  
  28.             if (OSRunning == TRUE) {         //检查是否有(某个)任务在运行  
  29.                 OS_Sched();                  //任务调度,最高任务优先级运行  
  30.             }  
  31.         } else {        //否则,任务初始化失败  
  32.             OS_ENTER_CRITICAL();        //关闭中断  
  33.             OSTCBPrioTbl[prio] = (OS_TCB *)0;       //放弃任务,设此任务就绪态为0  
  34.             OS_EXIT_CRITICAL();                     //打开中断  
  35.         }  
  36.         return (err);           //返回(获得并定义初始化任务控制块是否成功)  
  37.     }  
  38.     OS_EXIT_CRITICAL();         //打开中断  
  39.     return (OS_PRIO_EXIST);     //返回(具有该优先级的任务已经存在)  
  40. }  
  41. #endif  

6.static  void  OS_InitTaskStat (void) ;

  1. //创建统计任务  
  2. #if OS_TASK_STAT_EN > 0  
  3. static  void  OS_InitTaskStat (void)   
  4. {  
  5. #if OS_TASK_CREATE_EXT_EN > 0        //允许生成OSTaskCreateExt()函数  
  6.     #if OS_STK_GROWTH == 1          //堆栈生长方向向下  
  7.     (void)OSTaskCreateExt(OS_TaskStat,                                 //建立扩展任务;产生一个统计任务  
  8.       (void *)0,                                   //没有(传递参数指针)  
  9.       &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],   //分配任务堆栈栈顶指针  
  10.       OS_STAT_PRIO,                                //分配任务优先级  
  11.       OS_TASK_STAT_ID,                             //(未来的)优先级标识(与优先级相同)  
  12.       &OSTaskStatStk[0],                           //分配任务堆栈栈底指针  
  13.        OS_TASK_STAT_STK_SIZE,                       //指定堆栈的容量(检验用)  
  14.       (void *)0,                                   //没有(指向用户附加的数据域的指针)  
  15.      OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */  
  16.     #else                                                             //建立扩展任务;堆栈生长方向向上  
  17.     (void)OSTaskCreateExt(OS_TaskStat,                                //产生一个统计任务  
  18.        (void *)0,                                  //没有(传递参数指针)  
  19.        &OSTaskStatStk[0],                          //分配任务堆栈栈底指针  
  20.        OS_STAT_PRIO,                               //分配任务优先级  
  21.        OS_TASK_STAT_ID,                            //(未来的)优先级标识(与优先级相同)  
  22.        &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],  //分配任务堆栈栈顶指针  
  23.        OS_TASK_STAT_STK_SIZE,                      //指定堆栈的容量(检验用)  
  24.        (void *)0,                                  //没有(指向用户附加的数据域的指针)  
  25.         OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);  /* Enable stack checking + clear  */  
  26.     #endif  
  27. #else                   //否则只能生成OSTaskCreate()函数  
  28.     #if OS_STK_GROWTH == 1          //堆栈生长方向向下  
  29.     (void)OSTaskCreate(OS_TaskStat,     //产生一个统计任务  
  30.                        (void *)0,                                      //没有(传递参数指针)  
  31.                        &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],      //分配任务堆栈栈顶指针  
  32.                        OS_STAT_PRIO);                                  //分配任务优先级  
  33.     #else               //否则堆栈生长方向向上  
  34.     (void)OSTaskCreate(OS_TaskStat,     //产生一个统计任务  
  35.                        (void *)0,                                      //没有(传递参数指针)  
  36.                        &OSTaskStatStk[0],                              //分配任务堆栈栈底指针  
  37.                        OS_STAT_PRIO);                                  //分配任务优先级  
  38.     #endif  
  39. #endif  
  40. }  
  41. #endif  

7.static  void  OS_InitTCBList (void);


  1. //初始化空闲TCB链表  
  2. static  void  OS_InitTCBList (void)  
  3. {  
  4.     INT8U    i;  
  5.     OS_TCB  *ptcb1;  
  6.     OS_TCB  *ptcb2;  
  7.   
  8.   
  9.     OSTCBList     = (OS_TCB *)0;                                 //任务控制块链接表的指针清0  
  10.     for (i = 0; i < (OS_LOWEST_PRIO + 1); i++) {                   
  11.         OSTCBPrioTbl[i] = (OS_TCB *)0;        //清除所有的优先级控制块优先级列表  
  12.     }  
  13.     ptcb1 = &OSTCBTbl[0];    //查找任务控制块列表(0)的对应地址  
  14.     ptcb2 = &OSTCBTbl[1];    //查找任务控制块列表(1)的对应地址  
  15.     for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {    
  16.         ptcb1->OSTCBNext = ptcb2;//释放所有的任务控制块列表  
  17.         ptcb1++;  
  18.         ptcb2++;  
  19.     }  
  20.     ptcb1->OSTCBNext = (OS_TCB *)0;             //将最后的任务块双向链接表的后链接为0  
  21.     OSTCBFreeList    = &OSTCBTbl[0];   //空任务控制块地址为当前任务控制块列表的首地址  



























































你可能感兴趣的:(uCOS-II函数解析)