vxworks下延时办法总结

时间:2022-08-24 00:26:15

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);
}
}