0 引言 VxWorks是目前應用最多的嵌入式實時操作系統之一,廣泛應用于工業控制、醫療器械、通信、航空航天以及武器裝備等領域。VxWorks是32位實時嵌入式操作系統,自20世紀80年代由風河公司推出以來,其良好的實時性、對多任務的支持、體積精簡、可剪裁等優點得到眾多公司、開發者及用戶的喜愛。 在實時性要求高的應用系統中,定時器是經常被用到的重要器件。而對于VxWorks操作系統本身來說,并未提供一個通用、高效的定時器組件。文章所提出的共享看門狗定時機制就是針對這種情況實現的一種通用型定時器組件。 1 VxWorks定時的方法 1.1 使用taskDely函數 函數原型為:STATUS taskDelay(int ticks)該函數提供一種簡單的任務休眠機制,常用于需要不精確定時或延時的應用中,其定時的單位為tick,默認情況下60(ticks)為1s (利用sysClkRateSet函數可以修改系統默認的時鐘速率)。在任務中調用taskDelay函數可以在指定的ticks期間空出CPU的使用權,同時改變該任務的狀態為DELAY.由于經常受到任務調度的影響,該定時機制并不精確。 1.2 看門狗watchDog VxWorks提供了一個看門狗定時器(watchDog timer),它由以下四個函數維護: wdCreate( ) 創建并初始化一個看門狗定時器;wdDelete( ) 終止并刪除一個看門狗定時器;wdStart( ) 啟動看門狗定時器;wdCancel( ) 暫停當前看門狗定時器運行。 利用wdCreate函數,在任何任務中都可以創建一個看門狗定時器,經過設置的時間段后,實現指定的C函數。 watchDog定時器作為系統時鐘中斷服務程序的一部分來維護。因此看門狗所定時執行的程序工作在系統中斷級別具有很高的優先級,該程序必須遵守一般ISR程序的規定,不能使用任何可能被阻塞的程序。文章所介紹的高效定時器就是在看門狗定時器的基礎上設計的。 1.3 POSIX標準的timer VxWorks同時也提供IEEE的POSIX 1003.1b標準定時器接口。POSIX標準保證了應用程序與操作系統之間接口的簡易性,利用這些接口編程,可以使得應用程序很輕松地從一個操作系統移植到另外的操作系統。使用該定時機制,在指定時間段后,任務將向自身發送SIGNAL,該定時器是建立在時鐘和信號之上。POSIX標準的timer定時器常常用來編寫跨平臺、需要在多個操作系統下運行、易移植的程序。 2 基于看門狗定的高效定時機制 2.1 共享看門狗高效定時器 在一些基于嵌入式實時系統的項目中,經常使用定時器來實現某一時間段后執行某一段程序或函數,而往往計時長度都存在差異,定時器的使用也往往來自不同任務,既要求實時性,又要保證資源竟爭的有序性。鑒于這些特點,經常采用的一個定時任務使用一個看門狗定時器的模式已不再適用,如果按照這種模式構建定時器機制,在定時任務較多的情況下,由于看門狗定時器運行在中斷級別,資源消耗就會變得很大,從而對系統的實時性產生影響。 共享看門狗定時器的定時機制可以解決這種資源嚴重浪費的現象。共享看門狗定時機制,顧名思義,就是多個定時任務通過共享同一個看門狗定時器來實現定時操作,其優點是資源消耗小、實時性好、無須產生額外的定時任務。 2.2 定時算法 共享看門狗高效定時器的基本原理是動態改變看門狗的定時任務。 如圖1所示,系統中存在A、B、C三個定時任務。首先A任務提交一個500ms的定時任務,200ms后B提交一個200ms的定時任務,再100ms后C提交一個150ms的定時任務。除此之外再無其他計時,A、B、C運行情況如圖1所示。 圖1 共享看門狗定時器計時機制 圖1 共享看門狗定時器計時機制(參見下頁)定時器A在時間軸50ms處向共享定時器發起定時申請,共享定時器在其維護的定時列表中加入A的時延與執行程序的函數指針,并計算出定時器下一執行時刻TA(系統運行時間加上A的定時時延),此時由于還沒有其他定時器申請定時任務,該列表中只存在A的定時信息。當時間軸到達250ms時,定時器B發起定時申請,由于定時器A的時延為500ms,B的時延為200ms,也就是說B將在時間軸450ms處執行,比A提前了100ms(550ms減去450ms),此時定時列表將完成兩件事情,一是修改下一執行時刻TB為系統運行時間加上B的時延,二是針對執行時刻TA、TB對列表進行從小到大的順序排序。此時列表中B為表頭,A在B之后。同樣的道理當時間軸到達350ms時,定時器C發起定時申請,定時任務C被加入到定時列表,計算得出TC為系統運行時刻加上C的時延,然后依據TA、TB、TC重新進行排序,此時列表順序為B、C、A.當時間軸執行到450ms時,定時器B的ISR將被執行,同時B定時任務將從定時列表中刪除;同理,500ms、550ms時C任務與A任務將分別從列表中刪除。 此時所有定時任務執行結束,定時列表為空,共享看門狗定時器進入休眠狀態。 2.3 定時器實現 2.3.1 定時器軟件結構 共享定時器軟件結構如圖2所示: 圖2 共享看門狗定時器計時機制 CWatchDogTimer類完成了對看門狗定時器的封裝,它由一些通用的函數來維護一個看門狗定時器。其中Create()函數用來創建一個看門狗定時器;Delete()用來刪除該定時器;Start()用來啟動定時任務;Cancel()用來暫停定時器工作,此時再使用Start()函數可以恢復定時器的運行。 TimerInfo數據結構由tExe與tInterval兩個屬性構成,tExe記錄定時器的執行時間,tInterval表示定時器的時間間隔。 TimerList用來維護多個TimerInfo結構的變量,每個TimerInfo變量記錄一個定時器參數信息。 CEfficientTimer類完成對多個定時任務的管理,包括RegistTimer()函數實現注冊一個定時器;UnRegistTimer()用來注銷一個定時器;ClearTimerList()用來清空定時器列表中所有定時器任務;IsEmpty()用來判斷定時器列表是否為空。 2.3.2 看門狗定時模塊實現 看門狗定時模塊處理流程如圖3所示。 圖3 看門狗定時模塊處理流程 看門狗定時器模塊是共享定時器的基礎,它實現了單一定時器的建立、啟動、刪除、取消等功能。首先通過Create()函數建立一個看門狗定時器,同時設定定時器時延、定時次數等參數;然后通過Start()函數啟動定時器;看門狗程序判斷是否到達時間間隔,如果到達則開始執行ISR程序,如果沒有到達則繼續等待;當執行完ISR程序后,定時器將判斷當前執行次數是否到達執行總次數,如果是則結束該次定時任務,若不是程序將跳轉到重新啟動定時器后依次執行。 2.3.3 定時器管理模塊實現 定時器管理模塊是共享定時機制的核心,用來維護定時器的注冊、注銷以及定時器鏈表的排序、刪除、清空等操作。 定時器的注冊流程如圖4所示,首先使用RegistTimer()函數注冊一個新的定時器任務, 并將該定時器的TimerInfo結構插入鏈表中維護,然后針對該結構中的tExe變量對鏈表按照升序排列,執行時間最小的將置于表頭;若在插入該定時器任務之前鏈表中為空,則定時器處于休眠狀態,此時置定時器狀態為運行;若插入前鏈表中已存在其他定時器任務,則無須重啟定時器。 圖4 看門狗定時器注冊流程 定時器的注銷流程如圖5所示, 首先使用UnRegistTimer ()函數注銷一個已注冊的定時器任務,并將該定時器的TimerInfo結構從鏈表中刪除,然后針對該結構中的tExe變量對鏈表按照升序排列,執行時間最小的將置于表頭;若在刪除該定時器任務之前鏈表中除了該定時任務沒有其他定時任務時,則置定時器為休眠狀態;反之,則無須重置定時器狀態。 圖5 看門狗定時器注銷流程 3 結束語 共享定時器提供了簡單、高效、通用的定時方法,使用者可以拋開管理諸多看門狗定時器的煩惱,從而專心于系統其他方面的設計。作為一個通用的系統組件,開發人員不僅可以直接使用,縮短開發時間,也可以繼承此定時器類,實現更多豐富的功能,提供了良好的擴展性與靈活性。 該機制在VxWorks的網絡報文應答、設備狀態監控等方面得到了廣泛應用,在有效節省系統資源的同時提高了系統定時機制的靈活性。 |