一般說來,任務可在OSStart()啟動任務調度之前來創建,也可在任務中創建,但是UC/OS有個規定:在調用OSStart()啟動任務調度之前,必須創建了至少一個任務。因此一般習慣上,在OSStart()啟動任務調度之前先創建一個任務,並賦予它最高的優先級,從而使它成為起始任務,然后在這個起始任務中再創建其他任務。如果要使用統計任務,則統計任務的初始化函數也必須在這個起始任務中來調用。
注意:
UC/OS不允許在中斷服務程序中創建任務。
下面是創建任務的示意性代碼:
/******************主函數*****************/ void main(void) { ... ... OSInit(); //對ucos-ii進行初始化 ... ... OSTaskCreate(TaskStart,... ...); //創建起始任務 OSStart(); //開始多任務調度 } /*****************起始任務***************/ void TaskStart(void *pdata) { ... ... //在這個位置安裝並啟動ucos-ii的時鍾 OSStatInit(); //初始化統計任務 ... ... //在這個位置創建其他任務 for(; ;) { /*起始任務TaskStart的代碼*/ } }
創建任務函數
任務的創建實質上是創建一個任務控制塊,並通過任務控制塊把任務代碼和任務堆棧關聯起來形成一個完整的任務。UC/OS提供兩個函數創建任務OSTaskCreate()和OSTaskCreateExt()。一般前者用的多,OSTaskCreate()如下所示:
1 INT8U OSTaskCreate (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio) 2 { 3 OS_STK *psp; 4 INT8U err; 5 #if OS_CRITICAL_METHOD == 3 6 OS_CPU_SR cpu_sr = 0; 7 #endif 8 #if OS_ARG_CHK_EN > 0 9 if (prio > OS_LOWEST_PRIO) { //檢測任務的優先級是否合法 10 return (OS_PRIO_INVALID); 11 } 12 #endif 13 OS_ENTER_CRITICAL(); 14 if (OSIntNesting > 0) { /* Make sure we don't create the task from within an ISR */ 15 OS_EXIT_CRITICAL(); 16 return (OS_ERR_TASK_CREATE_ISR); 17 } 18 if (OSTCBPrioTbl[prio] == (OS_TCB *)0) {//確認優先級未被使用 19 OSTCBPrioTbl[prio] = (OS_TCB *)1; //保留優先級 20 21 OS_EXIT_CRITICAL(); 22 psp = OSTaskStkInit(task, p_arg, ptos, 0);//初始化堆棧 23 err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);//初始化任務控制塊 24 if (err == OS_NO_ERR) { 25 if (OSRunning == OS_TRUE) { /* Find highest priority task if multitasking has started */ 26 OS_Sched();//任務調度 27 } 28 } else { 29 OS_ENTER_CRITICAL(); 30 OSTCBPrioTbl[prio] = (OS_TCB *)0;//放棄任務 31 OS_EXIT_CRITICAL(); 32 } 33 return (err); 34 } 35 OS_EXIT_CRITICAL(); 36 return (OS_PRIO_EXIST); 37 } 38 #endif
在“啟動任務”中完成與系統硬件有關的各種初始化工作,然后創建各個實質任務和所需要的各種通信工具,至此系統才真正完成准備工作,“啟動任務”的使命也就結束了,最
后將自己刪除。為了保證“啟動任務”能夠連續運行,必須將“啟動任務”的優先級選擇為最高。否則,當“啟動任務”創建一個優先級高於自己的任務時,剛剛創建的任務就會立即
進入運行狀態,而與這個任務關聯的其它任務可能還沒有創建,它使用的通信工具也還沒有創建,系統必然出錯。“啟動任務”調用的“自我刪除”函數會進行任務調度操作,從而使
系統開始運行各個實質任務
