网站优化排名软件哪些最好,dedecms调用不同数据库wordpress,wordpress 后台输入表格有框_预览没有边框,wordpress登陆重定向在应用编程的时候#xff0c;通常会碰到需要一个任务在特定的延时之后执行一个指定的动作#xff0c;如等待外设以确保数据可靠#xff0c;控制扬声器发声时间以及串口通信超时重发等。这就需要利用定时器机制来计量特定长度的时间段。 vxWorks作为实时嵌入式系统#xff0… 在应用编程的时候通常会碰到需要一个任务在特定的延时之后执行一个指定的动作如等待外设以确保数据可靠控制扬声器发声时间以及串口通信超时重发等。这就需要利用定时器机制来计量特定长度的时间段。 vxWorks作为实时嵌入式系统提供多样的定时接口函数。下面结合我的项目经历和网上的参考资料列举一些常用的定时方式并说明其注意事项。
一、taskDelay taskDelay(n)使调用该函数的任务延时n个tick(内核时钟周期)。该任务在指定的时间内主动放弃CPU除了taskDelay(0)专用于任务调度(将CPU交给同一优先级的其他任务)外任务延时也常用于等待某一外部事件作为一种定时延时机制。在没有中断触发时taskDelay能很方便地实现且不影响系统整体性能。例如写数据至EEPROMEEPROM需要一个内部擦除时间(最大擦除时间为l0ms)。以下所提及的一个tick都假设为1667 ms(160 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)tickn tick的时间。延时精度为ln延时1s就是taskDelay(60)的误差极限为16而taskDelay(1)的误差极限将是100。 使用taskDelay需注意的另外一点是即使经过n个tick调用延时的任务也不保证返回执行状态可能有更高或相同优先级的任务占用了CPU。看了上面的介绍就可以用它模拟实现Sleep函数了代码如下 [cpp] view plaincopy ST_VOID sMsSleep (ST_LONG ms) { int m sysClkRateGet();/*获取内核时钟频率*/ m 1000/m; m ms/m 1;/* taskDelay(n)实际上是延时(n-1)tick~n*tick的时间*/ taskDelay(m); } 下面是taskDelay的延时示意图 二、WatchDog VxWorks提供了一种通用的看门狗定时器机制。利用提供的函数任何任务都可以创建一个看门狗定时器经过指定的延时后实现在系统时钟ISR的上下文中运行指定的程序。需要注意的是看门狗定时触发的程序是在中断级别上执行而不是在任务的上下文中。因此看门狗定时挂接的程序编写有一定的限制这个限制条件与中断服务程序的约束是一样的。比如不能使用获取信号量的语句以及像printf()这样的IO系统函数。 通过wdCreate()可以创建一个看门狗定时器。调用wdStart()启动定时器延时参数同taskDelay一样以tick为单位同时还须指定定时完成后要调用的程序。如果应用程序同时需要多个看门狗函数则应使用wdCreate()产生多个独立的看门狗ID。因为对于给定的看门狗ID通过wdStart()只能关联一个看门狗函数。在指定的tick计数到达之前要取消一个看门狗计时器可以通过调用wdCancel()实现。每调用一次wdStart()看门狗定时器只执行一次因此对于一些要求周期性执行的应用程序要获得该效果则定时器函数本身必须通过递归调用wdStart()来重新启动定时器。 如果利用看门狗定时器实现延时则存在与taskDelay一样的精度上的缺陷以tick为基准并且看门狗关联的函数所受的限制很大这也是使用不便的一个方面。不过启动看门狗的任务不会被阻塞因为wdStart()调用立即返回并继续执行。
三、sleepnanosleep sleep()和nanosleep()是VxWorks提供的延时函数接口。但是在实际应用时默认是没有添加的得手动添加。sleep以s为单位nanosleep可以提供更精确的延时传参是时钟的结构体参数可以精确到ns但实际上只能做到大于或等于这个时问。因为skep或nanosleep函数延时的时间基准仍是tick调用此函数的任务处于任务延时状态这点与taskDelay()一致。不同的地方是taskDelay()是用于任务调度taskDelay(O)有其自身的含义而sleep(O)则是没有意义的。前面提过taskDelay(n)延时时间为(n-1)tickntick而sleepnanosleep则保证实际延时时间大于或等于设定的时间参数。实验代码如下 [cpp] view plaincopy void testTimer(int sec,int nsec) { struct timespec tm; tm.tv_sec sec; tm.tv_nsec nsec; nanosleep(tm,NULL); } 四、高精度时钟sysTimeStamp sysTimeStamp()也称“时间戳”。是通过系统时钟实现的。刚开始也觉得费解系统时钟的定时周期就是tick怎么实现高精度时钟呢?通过读BSP底层代码发现sysTimeStamp其实是通过读取该定时器的当前计数值来获取高精度定时的。通过sysTimestampFreq()函数可以得到系统时间戳的频率它往往反映的是CPU定时器的基准频率。当然如此高的分辨率只能是一个理想值不同的系统不一定都能实现。毕竟该时间戳的实现方式有一个致命的弱点通过查询方式。系统时钟定时中断是以ticb为单位的进一步提高分辨率读取定时器计数值(CPU的一个特殊功能寄存器)只能是查询方式实现。代码示例如下 [cpp] view plaincopy void msDelay(int ms) { int t,t1,t2; t1 sysTimestamp(); /*记录上一轮的时间戳*/ do{ t 0; /*计数清零*/ while(t sysTimestampFreq()/1000) { t2 sysTimestamp(); /*读取当前时间戳*/ if(t2 t1) t (t2-t1); else t t2; t1 t2; } }while(ms--); } 这种定时方式比较占用系统资源且只适用于短时间的定时但是实现方便。为确保定时准确应在锁定中断情况下调用sysTimestamp否则应考虑使用sysTimes-tampLock函数。
五、辅助时钟 辅助时钟是利用目标板上CPU的另一个定时器(除了系统时钟之外)中断实现的。它可以灵活配置实现高分辨率的定时而且容易实现ms级甚至μs级定时。VxWorks提供了一系列与系统时钟相同的操作接口用户可以方便地挂接自己的中断处理函数时钟分辨率的高低取决于硬件定时器的精度和用户中断函数的长短。要将辅助时钟作为精确的延时机制(如ms级延时)可以通过这种方式实现。初始化程序先调用SysAuxClkRateSet()函数设置辅助时钟中断周期为1ms(一般在contigh文件中AUX_CLK_RATE_MIN和AUX_CLK_RATE_MAX之间对中断频率作了限定如果需要可以对此宏定义修改)再通过ysAuxClkConneet()?将用户处理函数连接到辅助时钟中断上用户处理函数可以为SemGive(semTimer)释放一个同步信号量。编写一个msDelay(intms)作为其他任务调用接口函数代码如下 [cpp] view plaincopy void msDelay(int ms) { int i; sysAuxClkEnable(); /*启动辅助定时器*/ for(i 0;i ms;i) semTake(semTimer); /*等待定时中断释放信号量*/ sysAuxClkDisable(); } 这种方式能实现十分精确的定时调用延时的任务处于任务阻塞状态。但是使用上仍存在缺陷不能实现多个任务同时调用且需要CPU的一个时钟资源如果没有多余的时钟那么这一方法就不能实现。 另外还需要注意一点Tornado的调试工具Browser一SpyChart的实现原理是利用辅助定时器产生中断并记录当前被中断的任务由抽样数据反映各任务CPU占用率的情况。因此如果调试程序中使用了辅助定时器那么使用Spy Chart时定时处理函数会被重新挂接原有定时挂接的程序将得不到进行。反之如果在Spy Chart运行之后挂接辅助定时处理函数那么Spy Chart的运行将出现问题。实验发现运行Spy Chart后重新挂接辅助定时处理函数Spy Chart即使选中自动刷新各任务状态也不会更新。 VxWorks提供的定时接口(不一定专门用于定时也可间接实现)远不只这些。具体使用哪种方式应根据其精度、资源状态和优先级要求而定。