VxWorks下幾種定時延時方法的小結


1 taskDelay
taskdelay()提供了一個簡單的任務睡眠機制,也常用於需要定時/延時機制的應用中。

它的格式是 STATUS taskDelay(int ticks   /* number of ticks to delay task */   ),

可以看出使用該函數實現延時的單位為tick(一般系統中一個tick都是ms級的)。

在VxWorks下可以這樣使用taskDelay()函數:  taskDelay(sysClkRateGet()*1)。

函數sysClkRateGet()返回系統的時鍾速率,單位是tick數/每秒(利用函數sysClkRateSet()可以改變系統的時鍾速率)。在POSIX中有一個與taskdelay()相對應的函數――nanosleep()(下文中有介紹)。這兩個函數僅僅是延時單位不同,效果是相同的。
利用taskdelay(),可以將調用的任務移動到具有相同優先級的就緒隊列尾部。特別的,可以通過調用taskdelay(0),將cpu交給系統中其他相同優先級的任務。延時為0的調用只能用於taskdelay()中,nanosleep()認為這種調用是錯誤的。
taskdelay()會導致調用的任務在指定的延時期間(以ticks計數)放棄cpu,使任務處於DELAY狀態(因此,其不能用於中斷服務程序中)。通常其受到任務調度的影響,但在等待一些與中斷無關聯的外部條件時,其是有用的。如果調用的任務受到一個信號,指出其沒有被阻塞或被忽略,taskDelay()將返回ERROR,並在信號處理程序運行后設置errno為EINTR。
2 WatchDog
VxWorks提供了一個看門狗定時器(watchdog timer)機制,利用提供的函數,任何任務都可以創建一個看門狗定時器,經過指定的延時后,實現在系統時鍾ISR的上下文中運行指定的程序。在VxWorks中,看門狗定時器作為系統時鍾中斷服務程序的一部分來維護。函數因此,與看門狗定時器相聯系的運行在系統時鍾中斷級。在使用看門狗定時器實現定時/延時時,經過指定的時間,應用程序中斷在系統時鍾中斷優先級上面,然而,如果內核不能立即執行這個中斷服務程序,這個任務就被排隊到tExcTask 工作隊列中去,處在 tExcTask 工作隊列中的任務的優先級為 tExcTask (通常是 0)。對於使用看門狗定時器的中斷服務程序,仍然必須遵守一般的ISR所要遵守的規則。
通過wdCreate( )可以創建一個看門狗定時器。調用wdStart()啟動定時器,延時參數以tick為單位,同時還要指定定時完成后要調用的程序。如果你的應用程序需要多個看門狗函數,使用wdCreate( )為每個需求產生獨立的看門狗ID。因為對於給定的看門狗ID,只有最近的wdStart()有效。在指定的tick計數到達之前,要取消一個看門狗計時器,可以調用wdCancel()實現。
每調用一次wdStart(),看門狗定時器只執行一次。對於一些要求周期性執行的應用程序。要獲得該效果,定時器函數本身必須通過遞歸調用wdStart()來重新啟動定時器。
利用看門狗定時器,調用的任務不會被阻塞:因為wdStart()調用是立即返回的。使用該方法實現延時,關聯函數所受限制太大,好多系統調用不可用,郁悶也…
3 timer(POSIX)
3.1 timer
VxWorks提供IEEE的POSIX 1003.1b標准定時器接口。使用這種定時器機制,在指定的時間間隔后,任務向自身發信號。定時器是建立在時鍾和信號之上。
程序可以創建創建、設置和刪除一個定時器。當定時器到達期限,將向任務發送默認的信號(SIGALRM)。
使用timer的一般流程:
/* 創建定時器 */
if(timer_create(CLOCK_REALTIME,0,&mytimer)==ERROR)
return(ERROR);
/* 用戶程序與定時器相連 */
if(timer_connect(mytimer,(VOIDFUNCPTR)my_handler,0)==ERROR)
return(ERROR);
/* 設置定時器值 */
if(timer_settime(mytimer,0,&value,0)==ERROR)
     return(ERROR);
/* 一段延時 */
。。。。。。
/* 刪除定時器 */
if (timer_delete(mytimer)==ERROR)
     return(ERROR);
在使用定時器時,容易忽略定時結束后任務向自身發信號這一處理步驟。即在定時結束后,要向創建定時器的任務發送信號,如果此時任務已不存在,定時程序將不能執行,提示的錯誤是“interrupt: timerWdHandler : kill failed (timer=******,tid=******,errno=0x16)”(有一個《關於timer(定時器)中幾個函數的疑問!》帖子,其中提到該問題)。在上機時,我設置了一個較長時間的定時器,在創建定時器任務中使用相等的延時操作(taskDelay()、nanosleep()隨便哪個都行),此時程序正常運行,定時結束后正確地執行關聯到定時器的程序;再次運行,在定時結束前,我在shell下刪除掉創建定時器的任務,定時結束后又出現上述的錯誤。因此,使用POSIX定時器時,一定要注意不能讓創建定時器的任務在觸發定時程序之前結束,否則。。。准備reset吧
3.2 nanosleep()
函數nanosleep()的功能與VxWorks提供的taskDelay()類似,nanosleep()允許指定以秒和納秒為單位的定時/延時時間,taskDelay()以tick作為定時/延時時間。兩者只是延時單位不同,而不是精度不同,都由系統時鍾頻率決定。與taskDelay()一樣,使用nanosleep()實現定時/延時的任務也受調度的影響,在實際操作中一定要注意這一點。
使用nanosleep()時,定時參數使用的是結構itimerspe中的it_value,可以指定it_value中的秒和納秒為定時/延時時間。函數的使用較為簡單,不再贅述。

4 其它
使用帶有超時值timeout的msgQReceive()、semTask()也可以實現延時(有使用這種方式來進行延時的人嗎?不有嗎?有嗎?不有嗎?有嗎?不有嗎?。。。)。
該方法將阻塞任務,讓其等待超時,利用該方法實現延時可以使用函數semTask(…,timeout)、msgQReceive(…,…,…,timeout)。調用任務被放進阻塞隊列中(注意,使用semTask和msgQReceive時,time的值不能是NO_WAIT,如果指定NO_WAIT的話,將立即返回,也就達不到延時的效果了^_^)。如果你希望任務不被阻塞,還能繼續執行,sorry,此法不行,使用看門狗吧。
當阻塞的任務滿足繼續執行的條件后,將被放入ready隊列。這里要注意的是,任務被放入ready隊列並不意味着立刻就被執行。想想看,如果比它高優先級的任務正在占用資源,或也在等資源,那么…延時將是不確定的。

新代碼定時器采用 3、timer


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com