vxworks下延时办法总结
最近,所作的工程需要1ms的定时器,俺参考了精华区的有关文
章并在各位大侠的帮助下,俺终于研究了1ms的精确定时,睍在看
到还有网友在求帮忙有关疑问,俺这儿就总结一下,期望对所有人有所
帮助。
1、taskDelay()
taskdelay()是最简单的延时办法,他的单位是tick。它的函数
比如调用taskDelay(1),VxWorks 会在下一个tick 到来时唤醒调用者,它延时多
长时间,就取决于调用taskDelay 时所处的时间位置,所以taskDelay(1)延时的最长时
间是一个完整的tick,而最短时间是0!
因此:taskDelay(1)的延时时间相差很大,位于0~10ms 之间
原型是
STATUS taskDelay
(
int ticks /* number of ticks to delay
task */
)
其中,tick是vxworks下时钟中断的频率,可以通过
sysClkRateSet( ) 设置单位ticks数/秒,一般在60-100之间。通
过sysClkRateGet()可以得到睍在系统的时钟频率。
在VxWorks下可以这样运用运用taskDelay()函数:
...
taskDelay(sysClkRateGet()*5);/* 延时5s */
...
利用taskdelay(),可以将调用的任务从就绪态转到睡眠态但是不
能用于中断服务代 码中。非凡的,可以通过调用taskdelay(0),将
cpu交给系统中其他相同优先级的任务。
因 为其延时的单位是tick,所以其延时精度并不高,但对于延时
10ms以上的系统足够了。
2 WatchDog
VxWorks提供了一个看门狗定时器,他的主要作用是防止代 码跑
飞,但是利用看门狗同样可研究延时。
利用提供的函数,任何任务都可以通过wdCreate( )创建一个看门
狗定时器,经过指定的延时后,研究在系统时钟ISR的上下文中运
行指定的代 码。在VxWorks中,看门狗定时器做为系统时钟中断服
务代 码的一部分来维护。因此,+看门狗定时器相联系的函数运行
在系统时钟中断级,延时单位为tick。假如你的运用代 码需要多个
看门狗函数,运用运用wdCreate( )为每个需求产生独立的看门狗ID。
由 于对于给定的看门狗ID,只有最近的wdStart()有效。
...
void windDemo(void)
{
semHighId=semBCreate(SEM_Q_PRIORITY,SEM_FULL);
semLowId=semBCreate(SEM_Q_PRIORITY,SEM_FULL);
wdHighId=wdCreate();
wdLowId=wdCreate();
windDemoId=taskIdSelf();
FOREVER
{
highPriId=taskSpawn("tHighPri",100,VX_SUPERVISOR_MODE,4000
,(FUNCPTR)taskHighPri,0,0,0,0,0,0,0,0,0,0);
lowPriId=taskSpawn("tLowPri",150,VX_SUPERVISOR_MODE,4000,(
FUNCPTR)taskLowPri,0,0,0,0,0,0,0,0,0,0);
taskSuspend(0);
}
}
LOCAL void taskHighPri(void)
{
for(;;)
{
printf("This is from taskHighPri
Task!/n");
wdStart (wdHighId, 0.05*sysClkRateGet(),
(FUNCPTR) HighCollectRoutine, (int) wdHighId);
semTake (semHighId, WAIT_FOREVER);
}
}
LOCAL void taskLowPri(void)
{
for(;;)
{
printf("This is from taskLowPri Task
!/n");
wdStart (wdLowId, sysClkRateGet(),
(FUNCPTR) LowCollectRoutine, (int) wdLowId);
semTake (semLowId, WAIT_FOREVER);
}
}
void HighCollectRoutine(WDOG_ID myWdId)
{
wdStart (myWdId, 0.05*sysClkRateGet(), (FUNCPTR)
HighCollectRoutine, (int) myWdId);
semGive(semHighId);
}
void LowCollectRoutine(WDOG_ID myWdId)
{
wdStart (myWdId, sysClkRateGet(), (FUNCPTR)
LowCollectRoutine, (int) myWdId);
semGive(semLowId);
}
适用于延时10ms以上的系统。
利用看门狗定时器,调用的任务不会被阻塞:由 于wdStart()调用
是立即返回的。
3 辅助时钟
要想达到1ms甚至us级的延时就需要运用运用辅助时钟。cpu上至少有两
个timer,timer1用于系统时钟,处理系统级任务,时钟频率一般
不可以太高。timer2用于辅助时钟,利用它可以得到精确的延时。
...
#define AUX_CLK_MAX 1000
void windDemo(void)
{
semHighId=semBCreate(SEM_Q_PRIORITY,SEM_FULL);
windDemoId=taskIdSelf();
FOREVER
{
highPriId=taskSpawn("tHighPri",100,VX_SUPERVISOR_MODE,4000
,(FUNCPTR)taskHighPri,0,0,0,0,0,0,0,0,0,0);
taskSuspend(0);
}
}
void InterISR(void)
{
semGive(semHighId);
}
void test(void)
{
sysAuxClkDisable();
/* Disable system aux clock */
sysAuxClkConnect((FUNCPTR)InterISR, 0);
sysAuxClkRateSet(AUX_CLK_MAX); /* Set system
aux clock rate */
sysAuxClkEnable();
}
LOCAL void taskHighPri(void)
{
test();
for(;;)
{
printf("This is from taskHighPri
Task!/n");
semTake (semHighId, WAIT_FOREVER);
}
}