任务创建和删除
1. 任务创建和删除API函数
xTaskCreate()函数:动态创建一个新的任务,每个任务都需要RAM来保存任务状态(任务控制块+任务栈),此接口采用动态分配内存资源
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,
const char *const pcName,
unsigned short usStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask);
返回值:pdPASS:创建成功
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY:堆空间不足,失败
|
xTaskCreateStatic()函数:静态创建一个新的任务,每个任务都需要RAM来保存任务状态(任务控制块+任务栈),此接口采用静态分配内存资源
TaskHandle_t xTaskCreateStatic(TaskFunction_t pvTaskCode,
const char *const pcName,
uint32_t ulStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
StackType_t *const puxStackBuffer,
StaticTask_t *const pxTaskBuffer);
返回值:NULL:任务创建失败
其他值:任务句柄
|
任务删除函数
函数原型:void vTaskDelete(TaskHandle_t xTaskToDelete)
参 数:xTaskToDelete 要删除的任务的任务句柄
返 回 值:无
|
2. 任务创建和删除函数源码分析
2.1 FreeRTOS任务创建函数源码分析
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
{
TCB_t *pxNewTCB;
BaseType_t xReturn;
#define portSTACK_GROWTH
#if( portSTACK_GROWTH > 0 ){
}
#else{
StackType_t *pxStack;
pxStack = ( StackType_t *) pvPortMalloc(((( size_t) usStackDepth ) * sizeof( StackType_t)));
if( pxStack != NULL ){
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
if( pxNewTCB != NULL ){
pxNewTCB->pxStack = pxStack;
}
else{
vPortFree( pxStack );
}
}
else{
pxNewTCB = NULL;
}
}
#endif
if( pxNewTCB != NULL )
{
prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
prvAddNewTaskToReadyList( pxNewTCB );
xReturn = pdPASS;
}
else{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
return xReturn;
}
|
2.2 任务初始化函数源码分析
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 ){
StackType_t *pxTopOfStack;
UBaseType_t x;
#if( portSTACK_GROWTH < 0 ){
pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
pxTopOfStack = (StackType_t *)(((portPOINTER_SIZE_TYPE) pxTopOfStack) & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK)));
configASSERT((((portPOINTER_SIZE_TYPE) pxTopOfStack & (portPOINTER_SIZE_TYPE) portBYTE_ALIGNMENT_MASK) == 0UL));
}
#else
{
}
#endif
for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ){
pxNewTCB->pcTaskName[ x ] = pcName[ x ];
if( pcName[ x ] == 0x00 ){
break;
}
else{
mtCOVERAGE_TEST_MARKER();
}
}
pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ){
uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
}
else{
mtCOVERAGE_TEST_MARKER();
}
pxNewTCB->uxPriority = uxPriority;
vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority );
listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
#if( portUSING_MPU_WRAPPERS == 1 ){
}
#else{
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
}
#endif
if( ( void * ) pxCreatedTask != NULL ){
*pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
}
else{
mtCOVERAGE_TEST_MARKER();
}
}
|
2.3 任务堆栈初始化函数源码分析
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters){
pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR;
pxTopOfStack--;
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) prvTaskExitError;
pxTopOfStack -= 5;
*pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXEC_RETURN;
pxTopOfStack -= 8;
return pxTopOfStack;
}
|
以STM32(堆栈为向下增长模式)为例,经过上面的初始化后,此时的堆栈结果如下图所示
2.4 任务删除函数源码分析
void vTaskDelete( TaskHandle_t xTaskToDelete ){
TCB_t *pxTCB;
taskENTER_CRITICAL();
{
pxTCB = prvGetTCBFromHandle( xTaskToDelete );
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ){
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
else{
mtCOVERAGE_TEST_MARKER();
}
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ){
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
}
else{
mtCOVERAGE_TEST_MARKER();
}
uxTaskNumber++;
if( pxTCB == pxCurrentTCB ){
vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
++uxDeletedTasksWaitingCleanUp;
portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
}
else{
--uxCurrentNumberOfTasks;
prvDeleteTCB( pxTCB );
prvResetNextTaskUnblockTime();
}
traceTASK_DELETE( pxTCB );
}
taskEXIT_CRITICAL();
if( xSchedulerRunning != pdFALSE ){
if( pxTCB == pxCurrentTCB ){
configASSERT( uxSchedulerSuspended == 0 );
portYIELD_WITHIN_API();
}
else{
mtCOVERAGE_TEST_MARKER();
}
}
}
|
3. 任务创建和删除函数实例
本实验设计三个任务:
start_task:用来创建其他两个任务
task1_task:此任务运行5次后调用vTaskDelete函数删除任务task2_task,同时控制LED0的闪烁
task2_task:此任务控制控制LED1的闪烁
任务设置
#define START_TASK_PRIO 1
#define START_STK_SIZE 128
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);
#define TASK1_TASK_PRIO 2
#define TASK1_STK_SIZE 128
TaskHandle_t Task1Task_Handler;
void task1_task(void *pvParameters);
#define TASK2_TASK_PRIO 3
#define TASK2_STK_SIZE 128
TaskHandle_t Task2Task_Handler;
void task2_task(void *pvParameters);
|
main()函数
int main(void){
......
xTaskCreate((TaskFunction_t )start_task,
(const char* )"start_task",
(uint16_t )START_STK_SIZE,
(void* )NULL,
(UBaseType_t )START_TASK_PRIO,
(TaskHandle_t* )&StartTask_Handler);
vTaskStartScheduler();
}
|
任务函数
void start_task(void *pvParameters){
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t )task1_task,
(const char* )"task1_task",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_TASK_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
xTaskCreate((TaskFunction_t )task2_task,
(const char* )"task2_task",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
void task1_task(void *pvParameters){
uint8_t task1_num=0;
while(1){
task1_num++;
LED0=!LED0;
printf("任务1已经执行: %d 次\r\n",task1_num);
if(task1_num==5){
vTaskDelete(Task2Task_Handler);
printf("任务 1 删除了任务 2!\r\n");
}
vTaskDelay(1000);
}
}
void task2_task(void *pvParameters){
uint8_t task2_num=0;
while(1){
task2_num++;
LED1=!LED1;
printf("任务 2 已经执行: %d 次\r\n",task2_num);
vTaskDelay(1000);
}
}
|
编译程序并下载到开发板中,打开串口助手,显示如下图示:一开始任务1和任务2是同时运行的,由于任务2的优先级比任务1高,所以任务2先输出信息;任务1运行了5次以后任务1就删除了任务2,最后只剩下任务1在运行
|