xTaskCreate函式分析

2021-08-29 14:02:35 字數 4376 閱讀 3822

函式原型:

basetype_t xtaskcreate(    taskfunction_t pxtaskcode, const char * const pcname, const configstack_depth_type usstackdepth, void * const pvparameters, ubasetype_t uxpriority, taskhandle_t * const pxcreatedtask )

1.根據usstackdepth計算出任務堆疊大小並malloc相應的堆疊和tcb控制塊變數空間(tcb_t)

tcb_t *pxnewtcb;

pxnewtcb = ( tcb_t * ) pvportmalloc( sizeof( tcb_t ) );

pxnewtcb->pxstack = ( stacktype_t * ) pvportmalloc( ( ( ( size_t ) usstackdepth ) * sizeof( stacktype_t ) ) );

2.巨集定義判斷是否動態和靜態記憶體分配,如果都支援,則設定任務堆疊和tcb均為動態分配產生的。

pxnewtcb->ucstaticallyallocated = tskdynamically_allocated_stack_and_tcb;

3.初始化新任務的tcb結構體

static void prvinitialisenewtask(taskfunction_t pxtaskcode, const char * const pcname, const uint32_t ulstackdepth, void * const pvparameters, ubasetype_t uxpriority, taskhandle_t * const pxcreatedtask, tcb_t *pxnewtcb, const memoryregion_t * const xregions )

3.1如果核心設定支援堆疊溢位檢測,則設定任務tcb結構體的堆疊的最大上邊界位址

pxtopofstack = pxnewtcb->pxstack;

pxnewtcb->pxendofstack = pxnewtcb->pxstack + ( ulstackdepth - ( uint32_t ) 1 );

3.2根據設定的名稱最大長度configmax_task_name_len和'\0'字元,初始化任務名稱pcname

3.3設定任務優先順序--為什麼要減1???

uxpriority = ( ubasetype_t ) configmax_priorities - ( ubasetype_t ) 1u;

pxnewtcb->uxpriority = uxpriority;

3.4初始化tcb結構體的狀態列表項和事件列表項,

//初始化

vlistinitialiseitem( &( pxnewtcb->xstatelistitem ) );

vlistinitialiseitem( &( pxnewtcb->xeventlistitem ) );

//指定列表項所屬tcb

listset_list_item_owner( &( pxnewtcb->xstatelistitem ), pxnewtcb );

listset_list_item_owner( &( pxnewtcb->xeventlistitem ), pxnewtcb );

//設定事件列表項xeventlistitem的值

listset_list_item_value( &( pxnewtcb->xeventlistitem ), ( ticktype_t ) configmax_priorities - ( ticktype_t ) uxpriority );

3.5如果支援邊界巢狀計數,則初始化

pxnewtcb->uxcriticalnesting = ( ubasetype_t ) 0u;

3.6如果支援任務事件統計,則初始化

pxnewtcb->ulruntimecounter = 0ul;

3.7如果tcb存在本地資料儲存指標,則初始化

for( x = 0; x < ( ubasetype_t ) confignum_thread_local_storage_pointers; x++ )

//執行的判斷條件是#if( confignum_thread_local_storage_pointers != 0 ),

個人認為應該修改為#if( confignum_thread_local_storage_pointers > 0 ),這樣程式可能會更好吧

//confignum_thread_local_storage_pointers的值設定為負數,會導致編譯報錯

3.8如果核心配置支援訊息通知,則初始化

pxnewtcb->ulnotifiedvalue = 0;

pxnewtcb->ucnotifystate = tasknot_waiting_notification;

3.9如果核心支援include_xtaskabortdelay(即xtaskabortdelay函式),則初始化

pxnewtcb->ucdelayaborted = pdfalse;

3.10初始化任務堆疊

pxnewtcb->pxtopofstack = pxportinitialisestack( pxtopofstack, pxtaskcode, pvparameters );

3.11設定返回任務控制代碼(實際上就是tcb指標)

*pxcreatedtask = ( taskhandle_t ) pxnewtcb;

4.將新建的任務新增到任務就緒列表中

static void prvaddnewtasktoreadylist( tcb_t *pxnewtcb )

4.1 任務總量計數++

uxcurrentnumberoftasks++;  //uxcurrentnumberoftasks全域性變數,對所有任務計數

4.2 如果當前無任務在執行,猜測應該是當前是第一次建立任務pxcurrenttcb == null  //pxcurrenttcb用於指定當前在執行的任務tcb

4.2.1 將新建立的任務tcb複製給pxcurrenttcb

pxcurrenttcb = pxnewtcb;

4.2.2 判斷如果當前是第一次建立任務(任務計數為1)uxcurrentnumberoftasks == 1,就需要做以下全域性任務列表的初始化,主要有以下列表

privileged_data static list_t pxreadytaskslists[ configmax_priorities ];  //就緒任務列表陣列,不同的優先順序分成不同的列表

privileged_data static list_t xdelayedtasklist1;                          //阻塞任務列表1

privileged_data static list_t xdelayedtasklist2;                          //阻塞任務列表2         

privileged_data static list_t * volatile pxdelayedtasklist;                  

privileged_data static list_t * volatile pxoverflowdelayedtasklist;    

privileged_data static list_t xpendingreadylist;

4.3 如果任務當前有任務在執行

4.3.1判斷任務排程器是否在執行且新任務的優先順序是否比當前執行的任務優先順序高,將當前任務tcb指標指向新任務

pxcurrenttcb = pxnewtcb;

4.4 建立的任務總數計數++

uxtasknumber++;  //全域性變數,建立的任務總數計數

//uxtasknumber與uxcurrentnumberoftasks的區別

//首先是uxcurrentnumberoftasks,代表當前系統中存在的任務數目,建立任務時++,刪除任務時--

//uxtasknumber系統從執行到結束的建立任務總數,雖然會在建立任務時++,但刪除任務時不做--操作

4.5初始化tcb的任務控制塊編號,系統會將建立任務計數賦值給uxtcbnumber

pxnewtcb->uxtcbnumber = uxtasknumber;

4.6將任務新增到指定的任務優先順序的就緒列表中

prvaddtasktoreadylist( pxnewtcb );

4.7 如果新任務比正在執行的任務優先順序高,發起任務切換

taskyield_if_using_preemption();   //內部呼叫portyield_within_api()--->portyield()

5.返回建立結果

OSTaskCreate()函式分析

int8u ostaskcreate void task void pd void p arg,os stk ptos,int8u prio 函式返回乙個8位的整型數,呼叫該函式需要四個引數。第乙個引數乙個指標,也就是使用者 的首位址,在平時使用中我們把自己建立的任務的名字作為這個引數就可以了 第三...

getopt函式分析

函式getopt主要用於拆分命令列引數,用這個函式就不自己寫命令列引數解析程式了,以下 摘自tcpdump原始碼,對這個函式比較感興趣,故對此進行分析注釋,因水平實在不敢恭維,不足之處希望能一起 函式getopt 有三個引數,nargc,nargv就是命令列傳過來的argc和argv字串ostr,它...

uCOS OSTaskCreate()函式分析

int8u ostaskcreate void task void pd void p arg,os stk ptos,int8u prio 函式返回乙個8位的整型數,呼叫該函式需要四個引數。第乙個引數乙個指標,也就是使用者 的首位址,在平時使用中我們把自己建立的任務的名字作為這個引數就可以了 第三...