**
一、xTaskCreate函数
**
main函数中的start_task:
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); //任务句柄
xTaskCreate的原型:
xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
1。申请堆栈内存。
pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
2.申请任务控制块内存
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */
3.刚申请的堆栈内存首地址pxStack 保存到任务控制块pxNewTCB 的 pxStack成员变量当中。
pxNewTCB->pxStack = pxStack;
4.调用prvInitialiseNewTask函数初始化任务:
prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
5.调用prvAddNewTaskToReadyList( pxNewTCB );将新任务添加到就绪列表中。
**
二、prvInitialiseNewTask函数
**
1.可选功能,用内存填充函数memset把pxStack整个堆栈全部填上 tskSTACK_FILL_BYTE(0XA5)(检测堆栈溢出用,当不等于0XA5时说明已经被使用):
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
堆栈地址:0X20000578

填充前:

填充后:

2.获取栈顶指针,及保存到pxTopOfStack:
pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
3.保存任务名字到pxNewTCB->pcTaskName[ x ]
pxNewTCB->pcTaskName[ x ] = pcName[ x ];
pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = ‘\0’;
4.保存任务优先级到pxNewTCB->uxPriority:
pxNewTCB->uxPriority = uxPriority;
5.初始化两个列表项:
vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
6.初始化各种任务控制块成员变量:
7.调用pxPortInitialiseStack(),初始化堆栈:
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
pxPortInitialiseStack函数将在下一节《freertos 源码详解四 堆栈初始化》中讲解
8.保存任务句柄,其实就是任务控制块:
传进来的参数:
prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );参数六:pxCreatedTask为调用时xTaskCreate()函数时传入的创建任务任务的句柄(TaskHandle_t* )&StartTask_Handler);
参数七:TCB_t *pxNewTCB, :pxNewTCB
实为 xTaskCreate()函数步骤2.申请的任务控制块内存pxNewTCB
经赋值:
*pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
后,StartTask_Handler保存了任务控制块内存pxNewTCB的地址。

*pxCreatedTask 为指向Start_Handler的指针:

本文详细介绍了FreeRTOS中创建任务的xTaskCreate函数及其内部调用的prvInitialiseNewTask函数。首先,xTaskCreate负责申请堆栈和任务控制块内存,然后将堆栈地址保存到任务控制块,并调用prvInitialiseNewTask进行初始化。prvInitialiseNewTask主要任务是填充堆栈、设置栈顶指针、保存任务名、优先级以及初始化任务列表项。最后,任务被添加到就绪列表中,任务句柄也被正确地保存。
2202

被折叠的 条评论
为什么被折叠?



