VxWorks嵌入式系统几种常用的延时方法

简介: <span style="color:#0000f0;word-wrap: break-word; font-family: 宋体, Arial; font-size: 16px; line-height: 26px;"><span style="word-wrap: break-word;">1 taskDelay</span></span><br style="word-wrap: bre
1 taskDelay

    taskDelay(n)使调用该函数的任务延时n个tick(内核时钟周期)。该任务在指定的时间内主动放弃CPU,除了taskDelay(0)专用 于任务调度(将CPU交给同一优先级的其他任务)外,任务延时也常用于等待某一外部事件,作为一种定时/延时机制。在没有中断触发时,taskDelay 能很方便地实现,且不影响系统整体性能。例如写数据至EEPROM,EEPROM需要一个内部擦除时间(最大擦除时间为lOms)。以下所提及的一个 tick都假设为16.67 ms(1/60 s)。可以简单地调用taskDelay(2)来保证数据擦写完成。按理说taskDelay(1)就足以保证,为什么需要taskDelay(2)呢?
   
    这正是taskDelay使用的一个缺陷,使用时需要注意。taskDelay(n)表示任务延时至第n个系统时钟到来的时刻,如图1所示。如果在A时刻 调用taskDelay(1)仅延时5 ms,则在B时刻taskDelay(1)就刚好是一个tick周期。可见需要10 ms的延时就必须调用taskDelay(2)才能实现。taskDelay有接近一1个tick的误差存在,taskDelay(n)实际上是延时 (n-1)tick~n tick的时间。延时精度为l/n,延时1s就是taskDelay(60)的误差极限为1.6%,而taskDelay(1)的误差极限将是100%。
    使用taskDelay需注意的另外一点是:即使经过n个tick,调用延时的任务也不保证返回执行状态,可能有更高或相同优先级的任务占用了CPU。

2 WatchDog

    VxWorks提供了一种通用的看门狗定时器机制。利用提供的函数,任何任务都可以创建一个看门狗定时器,经过指定的延时后,实现在系统时钟ISR的上下 文中运行指定的程序。需要注意的是,看门狗定时触发的程序是在中断级别上执行,而不是在任务的上下文中。因此,看门狗定时挂接的程序编写有一定的限制,这个限制条件与中断服务程序的约束是一样的。比如,不能使用获取信号量的语句,以及像printf()这样的I/O系统函数。   

    通过wdCreate()可以创建一个看门狗定时器。调用wdStart()启动定时器,延时参数同taskDelay一样以tick为单位,同时还须指 定定时完成后要调用的程序。如果应用程序同时需要多个看门狗函数,则应使用wdCreate()产生多个独立的看门狗ID。因为对于给定的看门狗ID,通 过wdStart()只能关联一个看门狗函数。在指定的tick计数到达之前,要取消一个看门狗计时器,可以通过调用wdCancel()实现。每调用一次wdStart(),看门狗定时器只执行一次,因此对于一些要求周期性执行的应用程序,要获得该效果,则定时器函数本身必须通过递归调用 wdStart()来重新启动定时器。  

    如果利用看门狗定时器实现延时,则存在与taskDelay一样的精度上的缺陷,以tick为基准.并且看门狗关联的函数所受的限制很大,这也是使用不便的一个方面。不过启动看门狗的任务不会被阻塞,因为wdStart()调用立即返回并继续执行。

3 sleep/nanosleep   

    sleep()和nanosleep()是VxWorks提供的延时函数接口。sleep以s为单位,nanosleep可以提供更精确的延时;传参是时钟的结构体,参数可以精确到ns,但实际上只能做到大于或等于这个时问。因为skep或nanosleep函数延时的时间基准仍是tick,调用此函数的 任务处于任务延时状态,这点与taskDelay()一致。不同的地方是,taskDelay()是用于任务调度,taskDelay(O)有其自身的含 义,而sleep(O)则是没有意义的。前面提过,taskDelay(n)延时时间为(n-1)tick~ntick,而 sleep/nanosleep则保证实际延时时间大于或等于设定的时间参数。这一点可以通过编写一个测试程序试验证明。代码如下:

    void testTimer(int sec, int nsec){
         struct timespec tm;
         tm.tv_sec = sec;
         tm.tv_nsec = nsec;
         nanosleep(&tm, NULL); //执行延时程序
    }

4 高精度时钟sysTimeStamp
   
    sysTimeStamp()也称“时间戳”。是通过系统时钟实现的。刚开始也觉得费解,系统时钟的定时周期就是tick,怎么实现高精度时钟呢?通过读 BSP底层代码发现,sysTimeStamp其实是通过读取该定时器的当前计数值来获取高精度定时的。通过sysTimestampFreq()函数可 以得到系统时间戳的频率,它往往反映的是CPU定时器的基准频率。当然,如此高的分辨率只能是一个理想值,不同的系统不一定都能实现。毕竟该时间戳的实现方式有一个致命的弱点:通过查询方式。系统时钟定时中断是以ticb:为单位的,进一步提高分辨率读取定时器计数值(CPU的一个特殊功能寄存器),只能 是查询方式实现。代码示例如下:

    void msDelay(int ms){
       int t, t1, t2;
       t1 = sysTimestamp();       //记录上一轮时间戳
        do{         
            t=0;                  //计数清零
             while(t<sysTimestampFreq()/1000{ //时间戳小于1ms
                  t2=sysTimestamp();          //读取当前时间戳
                  if(t2>t1) t+= (t2-t1);
                  else      t+=t2;
                  t1 = t2;                     //当前时间戳保存到下一轮计算
               }
           }while(ms--);                       //循环ms次
        }
    }

    这种定时方式比较占用系统资源,且只适用于短时间的定时,但是实现方便。为确保定时准确,应在锁定中断情况下调用sysTimestamp;否则,应考虑使用sysTimes-tampLock函数。

5 辅助时钟
   
    辅助时钟是利用目标板上CPU的另一个定时器(除了系统时钟之外)中断实现的。它可以灵活配置实现高分辨率的定时,而且容易实现ms级甚至μs级定时。 VxWorks提供了一系列与系统时钟相同的操作接口,用户可以方便地挂接自己的中断处理函数,时钟分辨率的高低取决于硬件定时器的精度和用户中断函数的长短。要将辅助时钟作为精确的延时机制(如ms级延时),可以通过这种方式实现。初始化程序先调用SysAuxClkRateSet()函数设置辅助时钟中断周期为1ms(一般在contig.h文件中AUX_CLK_RATE_MIN和AUX_CLK_RATE_MAX之间,对中断频率作了限定,如果需 要可以对此宏定义修改),再通过ysAuxClkConneet()?将用户处理函数连接到辅助时钟中断上,用户处理函数可以为 SemGive(semTimer)释放一个同步信号量。编写一个msDelay(intms)作为其他任务调用接口,函数代码如下:

void msDelay(int ms){
    int i;
    sysAuxClkEnable();  //启动辅助定时器
    for(i=0; i<ms; i++)
        semTake(semTimer);//等待定时中断释放信号量
    sysAuxClkDisable();  //关闭辅助定时器
}

    这种方式能实现十分精确的定时,调用延时的任务处于任务阻塞状态。但是使用上仍存在缺陷,不能实现多个任务同时调用,且需要CPU的一个时钟资源,如果没有多余的时钟,那么这一方法就不能实现。
相关文章
|
2天前
|
Linux
xenomai与VxWorks实时性对比(Jitter对比)
本文对比了VxWorks和xenomai的实时性,聚焦于Jitter这一关键指标。在特定的硬件环境下(双核Cortex-A15,2GB内存),VxWorks和xenomai的读取时间戳耗时分别为0.249和0.163微秒。在时钟中断Jitter方面,VxWorks各项测试平均值约为4.066微秒,而xenomai在空载和加载情况下的平均值分别为0.516和0.768微秒。任务Jitter上,VxWorks和xenomai内核态任务的平均Jitter接近,但xenomai用户态任务Jitter较高。
6 0
xenomai与VxWorks实时性对比(Jitter对比)
|
1天前
|
程序员 iOS开发 MacOS
LabVIEW什么是实时操作系统(RTOS)
LabVIEW什么是实时操作系统(RTOS)
13 1
|
2月前
|
存储 小程序 中间件
单片机中MCU跑RTOS相比裸机的优势
单片机中MCU跑RTOS相比裸机的优势
29 1
|
1月前
|
芯片
嵌入式STM32中时钟系统详细分析
嵌入式STM32中时钟系统详细分析
61 0
嵌入式STM32中时钟系统详细分析
|
8月前
|
监控 Linux 项目管理
RISC-V SiFive U64内核——HPM硬件性能监视器
RISC-V SiFive U64内核——HPM硬件性能监视器
|
Linux 开发者 Perl
zynq操作系统:Linux驱动开发AXIDMA补充篇 多路DMA
Linux驱动开发AXIDMA补充篇 多路DMA
920 0
|
消息中间件 网络协议 物联网
常用RTOS详细说明
常用RTOS详细说明
531 0
常用RTOS详细说明
|
C语言
单片机中使用操作系统RTOS的好处
单片机中使用操作系统RTOS的好处
176 0
单片机中使用操作系统RTOS的好处
|
虚拟化 芯片
CORTEX-A7芯片中断系统基本原理与控制方法
CORTEX-A7芯片中断系统基本原理与控制方法
329 0
CORTEX-A7芯片中断系统基本原理与控制方法
|
Java 数据库连接 测试技术
嵌入式系统的省电模式
电源管理一直是一个热门话题,是近年来的嵌入式开发人员遇到的“一个很酷的话题”。其重要性在很大程度上取决于延长手持设备电池寿命的要求,但环境危害,散热等引起了人们的关注。嵌入式软件可以实现三种节电程序:使用动态电压和频率调整(DVFS)来根据当前需要调整CPU性能。
1219 0