發布日期:2022-04-27 點擊率:117 品牌:EMB
實時調度機制(Real-Time Scheduler)是Windows Embedded Compact區別于其他所有Windows系統的最顯著特性,同時也是開發嵌入式系統時需要著重考慮的部分。在工程領域對“實時”的理解,我非常欣賞下面的定義:“一個實時系統必須要滿足明確的(受限的)響應時間約束或風險的嚴重后果,包括失效狀態”- 出自于Phillip A. Laplante 《Real-Time System Design and Analysis》所以,一個實時系統中執行一個代碼必須在規定的時間約束內有明確的結果,否則就可能會導致系統失效,實時并不一定意味著快速處理能力。而Windows Embedded Compact正符合上述對于實時系統的定義,因此為了進一步理解,我們首先來了解它的任務調度機制,WinCE的任務調度內核每隔1ms查詢一次現有任務并依據下面兩個原則來決定處理哪個任務:
a). 具有更高優先級的任務先被執行
b). 同樣優先級的任務按100ms時間間隔(或Task Quantum定義的時間間隔)循環輪流執行
對于第一條規則,WinCE提供256個優先級等級(0-255),數字越小優先級越高,因此0級為最高優先級,關于優先級的應用本文不做重點描述,請參考下面文章:
Real-TimePriority System Levels (Windows Embedded CE 6.0)
對于第二條規則,當多個待處理任務擁有同樣的優先級,將按照100ms時間間隔(可以根據Thread Quantum自定義)循環輪流執行。例如有N個同樣優先級的任務,當第一個運行了上述定義時間片(WinCE稱其為Quantum,如100ms),系統內核就會將其中斷然后執行第二個任務,依此類推,直到N個任務都執行過一個Quantum時間后再重新回到第一個任務執行,如此循環。任一個線程最多只能運行一個Quantum的時間,除非另一個更高優先級的任務需要占用CPU,則按照第一條規則,這個線程會被更高優先級任務占用。
下面我們通過兩個例子來驗證上述兩個規則,硬件平臺使用ToradexColibri VF61(NXP/Freescale Vybrid Cortex-A5 )計算機模塊搭配Iris 載板,軟件使用Toradex提供的對應此平臺的工業級的WinCE6OS和GPIO庫。
a). 軟硬件平臺搭建請參考開發指南,如下圖所示
b). 驗證原理為在系統中啟動兩個任務,第一個任務驅動硬件某個GPIO輸出為低電平,而另一個則將同一個GPIO輸出為高電平;再將這兩個任務的優先級分別設置為相同和不同時候,通過觀測GPIO連接的示波器輸出來判定上述的兩個調度規則。關鍵代碼如下:創建兩個線程入口函數ThreadON和ThreadOFF,分別用來將選定的GPIO輸出為高電平和低電平,而從函數內部代碼可見會持續輸出高電平或者低電平,因此我們通過示波器觀察GPIO管腳的輸出即可得出目前是哪個函數在運行。
--------------------------------------------------------------------------------------------------------------
#include
#include"gpio.h"
// ===define constant pins / gpios ===
// SODIMMpin 101
uIo io1 =COLIBRI_PIN(101);
HANDLE hGpio;
HANDLE hThreadON,hThreadOFF;
//defineThreadON
DWORD WINAPI ThreadON( LPVOID lpParam ){
//Set ThreadPriority
CeSetThreadPriority(GetCurrentThread(), 100);
Sleep(5); //Allowthe orther Thread to configure it's PRIO
//FNFINITELOCKING LOOP
while(1){
//Set GPIOlogic high
Gpio_SetLevel(hGpio, io1, ioHigh);
}
return 0;
}
//defineThreadOFF
DWORD WINAPI ThreadOFF( LPVOID lpParam ){
//Set ThreadPriority
CeSetThreadPriority(GetCurrentThread(),100);
//FNFINITELOCKING LOOP
while(1){
//Set GPIOlogic low
Gpio_SetLevel(hGpio, io1, ioLow);
}
return 0;
}
//=============================================================================
//Application Entry Point
//
// Thesimple error handling using ASSERT statements is only effective when
// theapplication is run as a debug version.
//=============================================================================
int wmain(int argc, _TCHAR* argv[])
{
BOOL success;
// === InitializeGPIO library. ===
// We don't useregistry-based configuration, thus wecan
// pass NULL goGpio_Init()
hGpio = Gpio_Init(NULL);
ASSERT(hGpio != 0);
success = Gpio_Open(hGpio);
ASSERT (success);
// Configure thepin to act as GPIO (as opposed to an Alternate function)
// Set it toOutput, High
Gpio_ConfigureAsGpio(hGpio, io1);
Gpio_SetDir (hGpio, io1, ioOutput);
Gpio_SetLevel (hGpio, io1, ioHigh);
CeSetThreadPriority(GetCurrentThread(),99);
//Create twoconcorrent Threads, one set GPIO to High and other to Low
hThreadON = CreateThread(NULL, 0, ThreadON,NULL, 0, NULL);
hThreadOFF = CreateThread(0, 0, ThreadOFF,NULL, 0, NULL);
//Time to finish the Program
Sleep(3000);
return(TRUE);
}
--------------------------------------------------------------------------------------------------------------
c). 首先我們來測試第二條規則,將兩個任務的優先級設置為相同值(如上面代碼為100),運行程序后示波器圖形如下,可以看到每隔100ms GPIO輸出循環交替變化,完全符合我們第二條規則。
d). 然后我們再來測試第一條規則,如下修改一個任務(ThreadON)的代碼,將其優先級提高到99,另外在循環中增加一個5ms的暫停時間。
--------------------------------------------------------------------------------------------------------------
DWORD WINAPI ThreadON( LPVOID lpParam ){
//Set ThreadPriority
CeSetThreadPriority(GetCurrentThread(), 99);
Sleep(5); //Allowthe orther Thread to configure it's PRIO
//FNFINITELOCKING LOOP
while(1){
//Set GPIOlogic high
Gpio_SetLevel(hGpio, io1, ioHigh);
Sleep(5);
}
return 0;
}
--------------------------------------------------------------------------------------------------------------
e). 運行修改后的程序,示波器輸出如下結果,每隔7ms左右有一個拉高的脈沖,表示每次當高優先級的任務(ThreadON)從5ms 暫停時間恢復后,都會中斷低優先級任務的執行,這樣完全符合第一條規則的描述。
當然,以上所有測試都是基于單核心系統,從Windows Embedded Compact 7 開始,WinCE內核提供了對多核心處理器的支持,同時也有一個新的屬性“affinity”來定義哪一個核心來執行哪一個線程,所以如果在多核系統和WEC7上面運行上述例子,同時并未限定線程在同一個核心上面執行,則結果會不同因為兩個線程會同時在不同核心上面運行。當然,其實正常應用情況下我們是不建議設置“affinity”參數的,因為這樣就無法使得內核調度來自動安排線程在最先空閑的核心上面運行,達不到降低延遲提高系統性能的要求了。
實時系統目前在包括工業自動化,機器人和醫療領域等嵌入式設備上面有廣泛的需求,因此了解WinCE的實時調度工作機制以及如何使用線程可以讓我們的應用程序實時穩定的執行,讓我們更高效可靠的利用WinCE搭建我們的實時系統!
下一篇: PLC、DCS、FCS三大控
上一篇: 索爾維全系列Solef?PV