Ucos II 建立第一個任務之二
下面具體講解下任務建立的過程
就是建立任務函數的實現程式。
INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio) |
{ |
void *psp; |
INT8U err; |
|
|
if (prio > OS_LOWEST_PRIO) { (1) |
return (OS_PRIO_INVALID); |
} |
OS_ENTER_CRITICAL(); |
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { (2) |
OSTCBPrioTbl[prio] = (OS_TCB *)1; (3) |
OS_EXIT_CRITICAL(); (4) |
psp = (void *)OSTaskStkInit(task, pdata, ptos, 0); (5) |
err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0); (6) |
if (err == OS_NO_ERR) { (7) |
OS_ENTER_CRITICAL(); |
OSTaskCtr++; (8) |
OSTaskCreateHook(OSTCBPrioTbl[prio]); (9) |
OS_EXIT_CRITICAL(); |
if (OSRunning) { (10) |
OSSched(); (11) |
} |
} else { |
OS_ENTER_CRITICAL(); |
OSTCBPrioTbl[prio] = (OS_TCB *)0; (12) |
OS_EXIT_CRITICAL(); |
} |
return (err); |
} else { |
OS_EXIT_CRITICAL(); |
return (OS_PRIO_EXIST); |
} |
} |
1.OSTaskCreate()一開始先檢測分配給任務的優先順序是否有效[L4.1(1)]。任務的優先順序必須在0到OS_LOWSEST_PRIO之間。OS_LOWSEST_PRIO的定義是在os_cfg.h這個檔案,定義如下:#define OS_LOWEST_PRIO 12 。這個地方mcu21就有些搞不懂,為什麼不是64,而是12?有明白的可以告知mcu21同學。
2.接著,OSTaskCreate()要確保在規定的優先順序上還沒有建立任務[L4.1(2)]。在使用μC/OS-Ⅱ時,每個任務都有特定的優先順序。如果某個優先順序是空閑未使用的,μC/OS-Ⅱ通過放置一個非null 指標在OSTCBPrioTbl[]中來保留該優先順序[L4.1(3)]。這就使得OSTaskCreate()在設定任務資料結構的其他部分時能重新允許中斷[L4.1(4)]。
3.然後,OSTaskCreate()調用OSTaskStkInit()[L4.1(5)],它負責建立任務的堆棧。沒錯,就是OSTaskStkInit(),系統移植時候,我們辛辛苦苦在OS_CPU_C.C編寫了它,原來是跑到這裡耀武揚威來了。OSTaskStkInit()函數返回新的堆棧棧頂(psp),並被儲存在任務的0S_TCB中。注意使用者必須將傳遞給OSTaskStkInit()函數的第四個參數opt置0,因為OSTaskCreate()與OSTaskCreateExt()不同,它不支援使用者為任務的建立過程設定不同的選項,所以沒有任何選項可以通過opt參數傳遞給OSTaskStkInit()。
4.一旦OSTaskStkInit()函數完成了建立堆棧的任務,OSTaskCreate()就調用OSTCBInit()[L4.1(6)],這也是任務建立的核心,從閒置OS_TCB池中獲得並初始化一個OS_TCB。OSTCBInit()函數首先從OS_TCB緩衝池中獲得一個OS_TCB,如果OS_TCB池中有閒置OS_TCB,它就被初始化。注意一旦OS_TCB被分配,該任務的建立者就已經完全擁有它了,即使這時核心又建立了其它的任務,這些新任務也不可能對已指派的OS_TCB作任何操作,所以OSTCBInit()在這時就可以允許中斷,並繼續初始化OS_TCB的資料單元。
5. 從OSTCBInit()返回後,OSTaskCreate()要檢驗傳回碼[L4.1(7)],如果成功,就增加OSTaskCtr[L4.1(8)],OSTaskCtr用於儲存產生的任務數目。如果OSTCBInit()返回失敗,就置OSTCBPrioTbl[prio]的入口為0[L4.1(12)]以放棄該任務的優先順序。
6.然後,OSTaskCreate()調用OSTaskCreateHook()[L4.1(9)],OSTaskCreateHook()是使用者自己定義的函數,用來擴充OSTaskCreate()的功能。這一步驟可有有可無,在mcu21的項目裡,移植的時候是沒有編寫OSTaskCreateHook()的,所以也沒有調用這一函數。。
7. 如果OSTaskCreate()函數是在某個任務的執行過程中被調用(即OSRunning置為True[L4.1(10)]),則任務調度函數會被調用[L4.1(11)]來判斷是否建立立的任務比原來的任務有更高的優先順序。如果新任務的優先順序更高,核心會進行一次從舊任務到新任務的任務切換。如果在多任務調度開始之前(即使用者還沒有調用OSStart()),新任務就已經建立了,則任務調度函數OS_Sched()不會被調用。
經過以上7步,一個任務大致就建立好了。
上面程式中多次使用了這兩句程式,非常重要,多次使用。
OS_ENTER_CRITICAL(); //關中斷 |
|
OS_EXIT_CRITICAL(); //開中斷 |