|
清單 L 1.8
建立其它任務(wù)的任務(wù)。
void TaskStart (void *data)
{
Prevent compiler warning by assigning ‗data‘ to itself;
Display banner identifying this as EXAMPLE #1; (1)
OS_ENTER_CRITICAL();
PC_VectSet(0x08, OSTickISR); (2)
PC_SetTickRate(200); (3)
OS_EXIT_CRITICAL();
Initialize the statistic task by calling ‗OSStatInit()‘; (4)
μ /C OS-II:源碼公開的實(shí)時嵌入式操作系統(tǒng)
12
Create 10 identical tasks; (5)
for (;;) {
Display the number of tasks created;
Display the % of CPU used;
Display the number of task switches in 1 second;
Display uC/OS-II‘s version number
If (key was pressed) {
if (key pressed was the ESCAPE key) {
PC_DOSReturn();
}
}
Delay for 1 Second;
}
}
在建立其他任務(wù)之前,必須調(diào)用 OSStatInit()[L1.8(4)]來確定用戶的 PC 有多快,如 程序清單 L1.9 所示。在一開始,OSStatInit()就將自身延時了兩個時鐘節(jié)拍,這樣它就可 以與時鐘節(jié)拍中斷同步[L1.9(1)]。因此,OSStatInit()必須在時鐘節(jié)拍啟動之后調(diào)用;否 則,用戶的應(yīng)用程序就會崩潰。當(dāng) μC/OS-II 調(diào)用 OSStatInit()時,一個 32 位的計(jì)數(shù)器 OSIdleCtr 被清為 0 [L1.9(2)],并產(chǎn)生另一個延時,這個延時使 OSStatInit()掛起。此 時,uCOS-II 沒有別的任務(wù)可以執(zhí)行,它只能執(zhí)行空閑任務(wù)(μC/OS-II 的內(nèi)部任務(wù))。空閑 任務(wù)是一個無線的循環(huán),它不斷的遞增 OSIdleCtr[L1.9(3)]。1 秒以后,uCOS-II 重新開始 OSStatInit(),并且將 OSIdleCtr 保存在 OSIdleMax 中[L1.9(4)。所以 OSIdleMax 是 OSIdleCtr 所能達(dá)到的最大值。而當(dāng)用戶再增加其他應(yīng)用代碼時,空閑任務(wù)就不會占用那樣 多的 CPU 時間。OSIdleCtr 不可能達(dá)到那樣多的記數(shù),(如果擁護(hù)程序每秒復(fù)位一次 OSIdleCtr)CPU 利用率的計(jì)算由 μC/OS-II 中的 OSStatTask()函數(shù)來完成,這個任務(wù)每秒 執(zhí)行一次。而當(dāng) OSStatRdy 置為 TRUE[L1.9(5)],表示 μC/OS-II 將統(tǒng)計(jì) CPU 的利用率。
程序清單 L 1.9
測試 CPU 速度。
void OSStatInit (void)
{
OSTimeDly(2); (1)
OS_ENTER_CRITICAL();
OSIdleCtr = 0L; (2)
OS_EXIT_CRITICAL();
OSTimeDly(OS_TICKS_PER_SEC); (3)
μ /C OS-II:源碼公開的實(shí)時嵌入式操作系統(tǒng)
13
OS_ENTER_CRITICAL();
OSIdleCtrMax = OSIdleCtr; (4)
OSStatRdy = TRUE; (5)
OS_EXIT_CRITICAL();
}
1.07.03 TaskN()
OSStatInit()將返回到 TaskStart()。現(xiàn)在,用戶可以建立 10 個同樣的任務(wù)(所有任 務(wù)共享同一段代碼)。所有任務(wù)都由 TaskStart()中建立,由于 TaskStart()的優(yōu)先級為 0(最 高),新任務(wù)建立后不進(jìn)行任務(wù)調(diào)度。當(dāng)所有任務(wù)都建立完成后,TaskStart()將進(jìn)入無限循 環(huán)之中,在屏幕上顯示統(tǒng)計(jì)信息,并檢測是否有 ESC 鍵按下,如果沒有按鍵輸入,則延時一 秒開始下一次循環(huán);如果在這期間用戶按下了 ESC 鍵,TaskStart()將調(diào)用 PC_DOSReturn() 返回 DOS 系統(tǒng)。 程序清單 L1.10 給出了任務(wù)的代碼。任務(wù)一開始,調(diào)用 OSSemPend()獲取信號量 RandomSem [程序清單 L1.10(1)](也就是禁止其他任務(wù)運(yùn)行這段代碼—譯者注),然后調(diào)用 Borland C/C++的庫函數(shù) random()來獲得一個隨機(jī)數(shù)[程序清單 L1.10(2)],此處設(shè) random ()函數(shù)是不可重入的,所以 10 個任務(wù)將輪流獲得信號量,并調(diào)用該函數(shù)。當(dāng)計(jì)算出 x 和 y 坐標(biāo)后[程序清單 L1.10(3)],任務(wù)釋放信號量。隨后任務(wù)在計(jì)算的坐標(biāo)處顯示其任務(wù)號 (0-9,任務(wù)建立時的標(biāo)識)[程序清單 L1.10(4)]。最后,任務(wù)延時一個時鐘節(jié)拍[程序清 單 L1.10(5)],等待進(jìn)入下一次循環(huán)。系統(tǒng)中每個任務(wù)每秒執(zhí)行 200 次,10 個任務(wù)每秒鐘將 切換 2000 次。
程序清單 L 1.10
在屏幕上顯示隨機(jī)位置顯示數(shù)字的任務(wù)。
void Task (void *data)
{
UBYTE x;
UBYTE y;
UBYTE err;
for (;;) {
OSSemPend(RandomSem, 0, &err); (1)
x = random(80); (2)
y = random(16);
μ /C OS-II:源碼公開的實(shí)時嵌入式操作系統(tǒng)
14
OSSemPost(RandomSem); (3)
PC_DispChar(x, y + 5, *(char *)data, DISP_FGND_LIGHT_GRAY); (4)
OSTimeDly(1); (5)
}
}
1.08 例2
例 2 使用了帶擴(kuò)展功能的任務(wù)建立函數(shù) OSTaskCreateExt()和 uCOS-II 的堆棧檢查操 作(要使用堆棧檢查操作必須用 OSTaskCreateExt()建立任務(wù)—譯者注)。當(dāng)用戶不知道應(yīng) 該給任務(wù)分配多少堆棧空間時,堆棧檢查功能是很有用的。在這個例子里,先分配足夠的堆 棧空間給任務(wù),然后用堆棧檢查操作看看任務(wù)到底需要多少堆棧空間。顯然,任務(wù)要運(yùn)行足 夠長時間,并要考慮各種情況才能得到正確數(shù)據(jù)。最后決定的堆棧大小還要考慮系統(tǒng)今后的 擴(kuò)展,一般多分配 10%,25%或者更多。如果系統(tǒng)對穩(wěn)定性要求高,則應(yīng)該多一倍以上。 uCOS-II 的堆棧檢查功能要求任務(wù)建立時堆棧清零。OSTaskCreateExt()可以執(zhí)行此項(xiàng) 操作(設(shè)置選項(xiàng) OS_TASK_OPT_STK_CHK 和 OS_TASK_OPT_STK_CLR 打開此項(xiàng)操作)。如果任務(wù) 運(yùn)行過程中要進(jìn)行建立、刪除任務(wù)的操作,應(yīng)該設(shè)置好上述的選項(xiàng),確保任務(wù)建立后堆棧是 清空的。同時要意識到 OSTaskCreateExt()進(jìn)行堆棧清零操作是一項(xiàng)很費(fèi)時的工作,而且取 決于堆棧的大小。執(zhí)行堆棧檢查操作的時候,uCOS-II 從棧底向棧頂搜索非 0 元素(參看圖 F 1.1),同時用一個計(jì)數(shù)器記錄 0 元素的個數(shù)。 例 2 的磁盤文件為\SOFTWARE\uCOS-II\EX2_x86L,它包含 9 個任務(wù)。加上 uCOS-II 本身 的兩個任務(wù):空閑任務(wù)(idle task)和統(tǒng)計(jì)任務(wù)。與例 1 一樣 TaskStart()由 main() 函數(shù)建立,其功能是建立其他任務(wù)并在屏幕上顯示如下的統(tǒng)計(jì)數(shù)據(jù):
|
|