任务的创建
受博客限制,如果您想获得更好的阅读体验,请前往https://github.com/Nrusher/FreeRTOS-Book或者https://gitee.com/nrush/FreeRTOS-Book下载PDF版本阅读,如果您觉得本文不错也可前往star,以示对作者的鼓励。如发现问题欢迎交流。
FreeRTOS提供了以下4种任务创建函数
-
xTaskCreateStatic():以静态内存分配的方式创建任务,也就是在编译时便要分配好TCB等所需要内存。
-
xTaskCreateRestrictedStatic():以静态内存分配的方式创建任务,需要MPU。
-
xTaskCreate():以动态内存分配方式创建任务,需要提供portMolloc()函数的实现,在程序实际运行时分配TCB等所需要内存。
-
xTaskCreateRestricted():以动态内存分配方式创建任务,需要MPU。
任务创建函数大致可以按内存分配的方式分为静态和动态两种,简单来说就是是否用到了portMolloc()函数(关于portMolloc()会在FreeRTOS内存管理的章节中单独分析),其内容大致相同(MPU没有研究)。以xTaskCreate()函数为例分析任务创建的过程。xTaskCreate()函数的原型为
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 )
各参数的含义如下
-
pxTaskCode:指向任务函数的函数指针。
-
pcName:任务的名称。
-
usStackDepth:栈的深度,这里的栈的单位不是byte而是根据平台的位数决定的,8位,16位,32位分别对应1,2,3,4byte。
-
pvParameters:传入任务的参数。
-
uxPriority:任务的优先级。数值越大,任务的优先级越高。
-
pxCreatedTask:创建的任务的句柄,本质就是一个指向创建任务TCB的指针。
-
返回值:pdPass代表创建任务成功,errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY(pdFalse)代表分配内存时出现错误。
个人认为任务初始化的工作主要分为三步:
-
第一步分配存储空间;
-
第二步初始化栈、填充TCB结构体;
-
第三步是将TCB挂接到就绪链表中并根据优先级进行任务切换;
下面就对每一步的相关代码进行分析
分配存储空间
根据栈的生长方向,FreeRTOS采用了两种内存分配顺序。暂且将栈向上生长的分配方式放一边,看一下在栈向下生长时,内存分配过程是怎样的
TCB_t *pxNewTCB;
BaseType_t xReturn;
StackType_t *pxStack;
// 分配栈空间
pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );
if( pxStack != NULL )
{
// 分配栈空间成功,分配TCB结构体空间
pxNewTCB = ( TCB_t * )