昨天我们说了系统节拍,经过一步步的分析,了解了任务运行的基础,是怎么来的。今天就继续谈谈“时间管理”这个话题,系统节拍驱动任务的运行,时间管理就是对任务的运行时间进行管理的一种内核机制。那么下面就简单介绍几个常用的时间管理函数。

1.OSTimeDly函数,它位于os_time.c文件中,这个文件还有其他很多的时间管理函数,以下的函数都位于这个文件。

看了上面的参数是不是还是毫无感觉,那我们看看源码,注明:注释不是自己写的,是秉火团队写的。我们需要做的不光是学会使用这些别人提供的好内容,更要学会程序的设计思想(大学嵌入式老师讲的),所以每次看待问题,我都会提醒自己,这段代码的背后究竟是什么?别人这么设计的目的的是什么?这种设计的局限又是什么?吹了点牛,说了这么多题外的废话,就是提醒自己不要太肤浅,要多思考。。。还是从一步开始:读程序;简单的说就是停止当前任务的执行(任务为等待态),延时一段时间再继续运行,那为什么程序会有这么多if呢?因为计算机需要对未知的状态做提前的分析和预处理,以对各种情况作出反映,就像人一样,如果对某种状况毫无准备,将会措手不及;逻辑还是很清楚的,(1)如果使能了安全检测,在中断中调用此函数,调度器被锁,dly为0,opt超出范围,插入节拍列表出现错误的这几种情况,将不会进行延时处理;(2)否则,进入临界区,把任务状态变为等待态,将任务插到节拍列表(如果插入不出现错误的话),然后将任务拿出就绪列表,最后退出临界区。

void  OSTimeDly (OS_TICK   dly,                        //延时的时钟节拍数
                 OS_OPT    opt,                        //选项
                 OS_ERR   *p_err)                      //返回错误类型
{
    CPU_SR_ALLOC();                                    //使用到临界段(在关/开中断时)时必需该宏,该宏声明和定义一个局部变
                                                       //量,用于保存关中断前的 CPU 状态寄存器 SR(临界段关中断只需保存SR)
                                                       //,开中断时将该值还原。                

#ifdef OS_SAFETY_CRITICAL                              //如果使能(默认禁用)了安全检测
    if (p_err == (OS_ERR *)0) {                        //如果错误类型实参为空
        OS_SAFETY_CRITICAL_EXCEPTION();                //执行安全检测异常函数
        return;                                        //返回,不执行延时操作
    }
#endif

#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u                 //如果使能(默认使能)了中断中非法调用检测   
    if (OSIntNestingCtr > (OS_NESTING_CTR)0u) {        //如果该延时函数是在中断中被调用
       *p_err = OS_ERR_TIME_DLY_ISR;                   //错误类型为“在中断函数中延时”
        return;                                        //返回,不执行延时操作
    }
#endif
    /* 当调度器被锁时任务不能延时 */
    if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u) {  //如果调度器被锁   
       *p_err = OS_ERR_SCHED_LOCKED;                   //错误类型为“调度器被锁”
        return;                                        //返回,不执行延时操作
    }

    switch (opt) {                                     //根据延时选项参数 opt 分类操作
        case OS_OPT_TIME_DLY:                          //如果选择相对时间(从现在起延时多长时间)
        case OS_OPT_TIME_TIMEOUT:                      //如果选择超时(实际同上)
        case OS_OPT_TIME_PERIODIC:                     //如果选择周期性延时
             if (dly == (OS_TICK)0u) {                 //如果参数 dly 为0(0意味不延时)    
                *p_err = OS_ERR_TIME_ZERO_DLY;         //错误类型为“0延时”
                 return;                               //返回,不执行延时操作
             }
             break;

        case OS_OPT_TIME_MATCH:                        //如果选择绝对时间(匹配系统开始运行(OSStart())后的时钟节拍数)       
             break;

        default:                                       //如果选项超出范围
            *p_err = OS_ERR_OPT_INVALID;               //错误类型为“选项非法”
             return;                                   //返回,不执行延时操作
    }

    OS_CRITICAL_ENTER();                               //进入临界段
    OSTCBCurPtr->TaskState = OS_TASK_STATE_DLY;        //修改当前任务的任务状态为延时状态
    OS_TickListInsert(OSTCBCurPtr,                     //将当前任务插入到节拍列表
                      dly,
                      opt,
                      p_err);
    if (*p_err != OS_ERR_NONE) {                       //如果当前任务插入节拍列表时出现错误
         OS_CRITICAL_EXIT_NO_SCHED();                  //退出临界段(无调度)
         return;                                       //返回,不执行延时操作
    }
    OS_RdyListRemove(OSTCBCurPtr);                     //从就绪列表移除当前任务  
    OS_CRITICAL_EXIT_NO_SCHED();                       //退出临界段(无调度)
    OSSched();                                         //任务切换 
   *p_err = OS_ERR_NONE;                               //错误类型为“无错误”
}

2.OSTimeDlyHMSM()函数与上一个函数功能类似,具体看手册,再打出来就重复造轮子了,我们造一遍,而且知道怎么造,就没必要重复了;

3.OSTimeDlyResume()用于结束其他任务的延时。还是那句话,使用之前,多看手册;

4.OSTimeGet()函数用于获取当前的时钟节拍计数值,OSTimeSet()函数用于设置当前的时钟节拍计数值。

具体使用就自己区操作了,今天就先到这里啦!!!

posted on 2018-08-10 21:44  lzd626  阅读(617)  评论(0编辑  收藏  举报