![Rank: 8](images/default/star_level3.gif) ![Rank: 8](images/default/star_level3.gif)
- UID
- 872238
|
![](http://images.eccn.com/silabs/silicon_chip_980x60_202203.jpg)
3 多重定时器设计
3.1 设计方案
选用看门狗定时器机制来设计。看门狗定时器操作较为简单,只有4个函数,即wdCreate()、wdDelete()、wdStart()、wdCancel()。看门狗定时器与调用任务异步执行,并不阻塞调用任务,所以看门狗定时器很适合多任务的非阻塞计时。
当看门狗定时器启动后,如果在规定的30 ms内收到了正确的确认包,就会将定时器取消掉,继续发送下面的数据包。如果30 ms规定时间内没有收到确认数据包ACK,则需要重新发送数据包,并启动第2个40 ms的定时器。VxWorks中单CPU的任务间常用通信机制是消息队列。当定时器到时后利用消息队列向发送任务发送消息,通知发送任务重新发送数据包,启动下一定时器。看门狗定时器的回调函数可以执行msgQSend()这种向消息队列发送消息的函数,我们通过msgQSend()函数向主任务发送时限已达消息。但是,将msgQSend()的延时参数设为wAIT_FOREVER时,消息队列中一旦没有了可用缓冲,则进入等待状态。由于中断服务程序优先级高,而从消息队列中接收消息的优先级低,当有任务准备从消息队列中取消息时,要等待中断服务程序执行完毕,则消息队列始终处于已满状态,造成系统死锁。如果将msgQSend()函数中的延时参数改为NO_WAIT,则可避免一直等待向消息队列发消息的情况,一旦消息队列已满就将该消息丢弃。但这样一来,向接收端发送数据包任务接收不到定时器超时消息,不会重发原序列号数据包和启动下一定时器,所以使用参数NO_WAIT也不可行。
![](http://embed.chinaitlab.com/UploadFiles_4615/201002/20100222110812312.jpg) 这里提出一种避免上述情况造成系统死锁的方法,即使用信号量机制来使msgQSend()不在中断服务程序中执行。通过使用信号量的任务间同步机制来实现这个功能。释放信号量函数semGive()不像msgQSend()那样需要在消息队列中等待,一旦执行就可以马上释放信号量,从而避免了冲突。
由于任务中事件发生有一定间隔,不必选用计数器信号量,所以选用最常用的二进制信号量。首先建立3个先进先出的二进制信号量,设定可调用信号量为空。然后在看门狗定时器的回调函数中使用semGive()函数来释放信号量,重建一个任务在任务起始使用semTake()函数来获取信号量。当获得信号量后,通过msgQSend(,,,WAIT_FOREVER,)函数向消息队列中发送超时消息,而且保证只要消息队列有可用缓冲,就一定可以将消息送出。本文给出一个多重定时器的任务框架,如图3所示。
![](http://embed.chinaitlab.com/UploadFiles_4615/201002/20100222110812112.jpg)
|
|