創建新的任務並添加到任務隊列中,準備運行
- Parameters:
-
pvTaskCode |
指向任務的入口函數. 任務必須執行並且永不返回 (即:無限循環). |
pcName |
描述任務的名字。主要便於調試。最大長度由configMAX_TASK_NAME_LEN.定義 |
usStackDepth |
指定任務堆棧的大小 ,堆棧能保護變量的數目- 不是字節數. 例如,如果堆棧爲16位寬度,usStackDepth定義爲 100, 200 字節,這些將分配給堆棧。堆棧嵌套深度(堆棧寬度)不能超多最大值——包含了size_t類型的變量 |
pvParameters |
指針用於作爲一個參數傳向創建的任務 |
uxPriority |
任務運行時的優先級( 0 : 優先級最低) |
pvCreatedTask |
用於傳遞一個處理——引用創建的任務 |
- 返回:
- pdPASS 是如果任務成功創建並且添加到就緒列中,另外錯誤代碼在projdefs. H文件定義
使用例子:
// 使用句柄來刪除任務
vTaskDelete( xHandle );
}
// 創建任務,存儲處理。注意傳遞的參數爲ucParameterToPass
//它在任務中不能始終存在, 所以定義爲靜態變量. 如果它是動態堆棧的變量,可能存在
// 沒有那麼長,或者至少隨着時間毀滅,
// 新的時間, 嘗試存儲它
xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
// 函數來創建一個任務
void vOtherFunction( void )
{
static unsigned char ucParameterToPass;
xTaskHandle xHandle;
// 創建任務
void vTaskCode( void * pvParameters )
{
for( ;; )
{
// 任務代碼
}
}
portBASE_TYPE xTaskCreate(
pdTASK_CODE pvTaskCode,
const portCHAR * const pcName,
unsigned portSHORT usStackDepth,
void *pvParameters,
unsigned portBASE_TYPE uxPriority,
xTaskHandle *pvCreatedTask
);
[注
:以下爲FreeRTOS_v4
.5
.0在at91sam7s64處理器上的task任務創建函數
(gliethtp
)]
signed portBASE_TYPE xTaskCreate
( pdTASK_CODE pvTaskCode
, const signed portCHAR
* const pcName
, unsigned portSHORT usStackDepth
, void *pvParameters
, unsigned portBASE_TYPE uxPriority
, xTaskHandle
*pxCreatedTask
)
{
signed portBASE_TYPE xReturn
;
tskTCB
* pxNewTCB
;
#if ( configUSE_TRACE_FACILITY
== 1
)
//uxTaskNumber爲任務id號,一般用來調試,每個任務會唯一對應一個處於[0,0xffffffff]範圍之間的數值
//因爲優先級並不能唯一表示一個task,所以爲了能夠唯一標識一個task,
//可以使用TCB或者TCB->uxTCBNumber
static unsigned portBASE_TYPE uxTaskNumber
= 0
;
#endif
//動態申請tskTCB存儲區和usStackDepth堆棧存儲區
//FreeRTOS提供3中動態內存分配機制,具體可參見《淺析FreeRTOS_v4.5.0內存分配與回收及其改進方案》
//文章地址:http://blog.chinaunix.net/u1/38994/showart_392500.html
pxNewTCB
= prvAllocateTCBAndStack
( usStackDepth
);
if( pxNewTCB
!= NULL )
{
portSTACK_TYPE
*pxTopOfStack
;
//對task的
//pxTCB->pcTaskName
//pxTCB->uxBasePriority
//pxTCB->xGenericListItem
//pxTCB->xEventListItem進行初始化,
//將xEventListItem->xItemValue值置爲configMAX_PRIORITIES - ( portTickType ) uxPriority
//所以xEventListItem->xItemValue的最小值爲1.(注:非0[gliethttp])
prvInitialiseTCBVariables
( pxNewTCB
, pcName
, uxPriority
);
#if portSTACK_GROWTH
< 0
{
//堆棧是向下生長的,at91sam7s64就是以這種方式來生長堆棧
pxTopOfStack
= pxNewTCB
->pxStack
+ ( usStackDepth
- 1
);
}
#else
{
pxTopOfStack
= pxNewTCB
->pxStack
;
}
#endif
//初始化該task對應的堆棧空間
//具體可參見《淺析FreeRTOS_v4.5.0的任務切換原理和棧結構》
//文章地址:http://blog.chinaunix.net/u1/38994/showart_391270.html
//需要注意的是pvTaskCode應該+4,即lr-4,這樣來模擬IRQ,
//pxNewTCB->pxTopOfStack存放了當前task使用到的sp棧頂值
pxNewTCB
->pxTopOfStack
= pxPortInitialiseStack
( pxTopOfStack
, pvTaskCode
, pvParameters
);
portENTER_CRITICAL
();//原子操作
{
uxCurrentNumberOfTasks
++;
if( uxCurrentNumberOfTasks
== ( unsigned portBASE_TYPE
) 1
)
{
//這是FreeRTOS系統創建的第1個任務,那麼初始化FreeRTOS的一些基礎量:
//1.pxReadyTasksLists隊列鏈表
//2.xDelayedTaskList1隊列鏈表
//3.xDelayedTaskList2隊列鏈表
//4.xPendingReadyList隊列鏈表
//5.xTasksWaitingTermination隊列鏈表
//6.xSuspendedTaskList隊列鏈表
//7.pxDelayedTaskList = &xDelayedTaskList1;暫時的前臺時間隊列鏈表
//8.pxOverflowDelayedTaskList = &xDelayedTaskList2;暫時的後臺時間隊列鏈表
pxCurrentTCB
= pxNewTCB
;
prvInitialiseTaskLists
();
}
else
{
if( xSchedulerRunning
== pdFALSE
)
{//當前FreeRTOS還沒有啓動調度器,
//那麼當前pxCurrentTCB需要是指向最高優先級任務
if( pxCurrentTCB
->uxPriority
<= uxPriority
)
{
//比它高,所以pxNewTCB應該做當前任務
pxCurrentTCB
= pxNewTCB
;
}
}
}
if( pxNewTCB
->uxPriority
> uxTopUsedPriority
)
{
uxTopUsedPriority
= pxNewTCB
->uxPriority
;//在vTaskList()中使用到了
}
#if ( configUSE_TRACE_FACILITY
== 1
)
{
pxNewTCB
->uxTCBNumber
= uxTaskNumber
;//存儲新創建的task的id號
uxTaskNumber
++;//id號+1,以便供下一個創建的task使用
}
#endif
//#define prvAddTaskToReadyQueue( pxTCB ) \
//{ \
// if( pxTCB->uxPriority > uxTopReadyPriority ) \
// { \
// uxTopReadyPriority = pxTCB->uxPriority; \
// } \
// vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) );\
//}
//把新創建的task添加到就緒運行隊列鏈表中,
//本task會被插入到pxReadyTasksLists中自己優先級所對應的數組下
//這時本task對應優先級的數組可能已經有同優先級的任務在上邊了,
//沒關係,只需要將本task添加到輪轉調度的最後位置即可,對於FreeRTOS輪轉調度的理解,
//可以參見《淺析FreeRTOS_v4.5.0的任務切換原理和棧結構》
//文章地址:http://blog.chinaunix.net/u1/38994/showart_391270.html
prvAddTaskToReadyQueue
( pxNewTCB
);
xReturn
= pdPASS
;//標示成功創建
}
portEXIT_CRITICAL
();//原子操作結束
}
else
{
xReturn
= errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
;
}
if( xReturn
== pdPASS
)
{
if( ( void * ) pxCreatedTask
!= NULL )
{
*pxCreatedTask
= ( xTaskHandle
) pxNewTCB
;//把創建的TCB,傳遞到外界參數pxCreatedTask中
}
if( xSchedulerRunning
!= pdFALSE
)
{//os已經正常啓動
if( pxCurrentTCB
->uxPriority
< uxPriority
)
{
//新創建的task-B的優先級比調用創建函數xTaskCreate()的task-A的優先級高
//那麼task-B立即搶佔task-A,取得cpu的使用權
//可以參見《淺析FreeRTOS_v4.5.0的任務切換原理和棧結構》
//文章地址:http://blog.chinaunix.net/u1/38994/showart_391270.html
taskYIELD
();
}
}
}
return xReturn
;//返回xTaskCreate()函數的執行結果
}