全网最全最细 FreeRTOS 手册详解——3-Task Management

本文深入探讨了FreeRTOS的任务管理,包括任务函数、状态、创建、优先级、调度算法等内容。详细解析了xTaskCreate API的使用,介绍了任务的阻塞、挂起和就绪状态,以及空闲任务和钩子函数的实现。还讨论了如何改变任务优先级和销毁任务,并概述了不同的调度策略,如抢占式和协作式调度。
摘要由CSDN通过智能技术生成

这一章节的概念是理解如何使用 FreeRTOS 和 FreeRTOS 应用行为的基础。

3.1 Task Function

// Task 函数原型
void ATaskFunction(void* pvParameters);

// 例子
void ATaskFunction(void* pvParameters) {
   
    int32_t lVariableExample = 0;
    
    for (;;) {
   };
    
    // NULL 表示的是销毁的任务应该是调用销毁函数的那个任务
    vTaskDelete(NULL);
}

每个任务都是一个小程序。任务函数有一个入口,并且通常会在死循环中执行,不会退出循环。任务禁止在他们的实现函数中以任何方式 return,不允许包含任何 return 语句,并且不允许执行到函数的结尾。如果一个任务不再被需要,他应该被显示的销毁。一个任务的定义可以用来创建任意数量的任务实例,每个实例都有其栈和任务函数中定义的变量的拷贝副本。

3.2 顶级任务状态(Top Level Task States)

在这里插入图片描述
一个应用可以由多个任务组成。单核上执行应用,则任意时刻最多只有一个任务在运行。因此一个任务可以看作两种状态:运行态或未运行。这是一个过度简化的模型。其实未运行态还有很多子状态。

  • 运行态:处理器执行相关 task 的代码
  • 非运行态:任务处于休眠,他的一些状态信息应该保存好,以便下次调度器决定让其进入运行态时可以恢复执行相关代码
  • 恢复执行:当一个任务恢复执行时,他应该从上次离开运行态之前将要执行的指令开始执行。

一个任务从非运行态切换到运行态叫做换入,相反叫做换出。在整个系统中只有 FreeRTOS 调度器可以切换任务进出。

3.3 创建任务

xTaskCreate API

FreeRTOS v9.0.0 也包含了 xTaskCreateStatic 函数,可以在编译阶段静态的创建一个任务,并为其分配所需内存。
差不多是所有 API 中最复杂的,上来就遇到不是很幸运,但是是必须的。因为创建任务是多任务系统的最基础的组件。

BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
                        const char* const pcName,
                        uint16_t usStackDepth,
                        void* pvParameters,
                        UBaseType_t uxPriority,
                        TaskHandle_t* pxCreatedTask );
  • pvTaskCode:是简单的永远不退出的 C 函数。因此常用一个无限循环实现。 pvTaskCode 是一个指向任务实现函数的指针。(实际上函数指针,typedef void (* TaskFunction_t)( void * ) )
  • pcName:任务的描述性名称。FreeRTOS 不会使用,纯粹是为了 debug 方便。以人可阅读的方式标识一个任务。通过常量 configMAX_tASK_NAME_LEN 定义最大长度,超过则自动截断。长度 = 字符个数 + 终止符。
  • usStackDepth:当任务创建的时候,每个任务都会有一个由内核分配的栈。该参数告诉内核创建多大的栈。单位是字长。例如,栈是 32 位宽的,那么传入 100,将会分配 400 字节。栈深度乘以栈宽度不能超过 uint16_t 可以表示的最大值。在 demo 应用中,根据使用的处理器架构为常量所赋的值是推荐给任何任务的最小值。如果任务需要很多栈空间,那么值一定要比这个值大。没有很好的方法确定一个任务需要的栈空间。可以尝试去计算,但是大多数情况下是赋一个差不多合理的值,然后通过 FreeRTOS 提供的特性确保栈空间充足而且不会造成不必要的浪费。Stack Overflow 包含了如何查询任务使用过的最大栈空间
  • pvParameters:void* 类型的指针,指向了要传给任务的参数。
  • uxPriority:定义了任务以什么样的优先级执行。优先级范围 [0, configMAX_PRIORITIES - 1]。传入大于最大值的值,会默认赋予任务最大的合法优先级。
  • pxCreatedTask:传递一个正在创建的任务的 handle,这个 handle 可以在其他 API 调用中引用这个任务,例如 改变任务优先级,销毁任务等。如果不使用则传入 NULL。
  • Returned value:pdPASS、pdFAIL。前者说明任务成功创建,后者说明没有足够的 heap 空间可用,来分配给任务的数据结构和任务。

xTaskCreate 函数流程

  1. 如果栈增长方向,地址减小,那么先为任务分配栈,后分配 TCB(Task Control Block),否则先 TCB 后分配栈。(保证栈增长不会占用 TCB,那会不会越界到其他内核对象或应用的地址里呢?)下面 m1, m2 代指分配顺序第一个和第二个。为 Stack 分配的字节数为 depth * sizeof(StackType_t) 即深度 * 栈的位宽
    1. 分配 m1,成功则下一步,否则释放 m1 后结束分配
    2. 分配 m2,成功则用 TCB->Stack 指向 Stack 的地址,否则释放 m1 后结束分配
  2. 分配成功则进行下一步,否则返回指定的错误代码,函数结束
  3. 如果支持动态分配, 把 TCB 标记为动态创建的,防止之后被删除(【暂时不太理解为什么会被删除】源代码是这样备注的)。
  4. 根据函数指针、函数名字、栈深度、任务参数、优先级、handle、TCB 起始地址调用初始化新任务的函数
  5. 把 TCB 加入到 ReadList
  6. 返回 pdPASS

初始化新的任务

  1. 任务是否应以私有模式创建?(【暂时不理解私有模式创建任务】)
  2. 栈是否需要设置为已知的值(以帮助 debug。此外应尽量减少对 memset 的依赖【为什么需要减少未知】)
  3. 根据栈增长方向,取到栈顶,然后内存对齐。(TCB->pxEndOfStack 记录栈的高地址,而不是记录栈空间用完后的位置)
  4. 按 UBaseType_t 类型拷贝任务名字(遇到 0x00 就意味着肯定拷贝完了,就停止)
  5. 检查优先级是否合法(大于等于最大优先级,则置为最大优先级 - 1),并赋给 TCB
  6. 初始化列表项(State 列表项、Event 列表项,确保列表项不属于任何列表,并设置两个检查值,防止列表项被复写造成数据污染)
    1. 设置 State\Event 列表项所属的 TCB
    2. 设置 Event 列表项的 item value 值为 最高优先级减去其优先级(代码中这里注释,事件总是按优先级排序,我猜测这里就是从小到大排序,值越小表明优先级越高)
  7. 然后就是一些杂七杂八的配置(【MPU wrapper】这里重点是根据 MPU 及其是否有 wrapper 的工作比较重要,需要 CPU 一些知识)

加入创建新任务到 ReadList

  1. 使用 taskENTER_CRITICAL 进入操作任务队列的临界区,确保中断不会访问正在更新的列表
  2. 如果 pxCurremtTCB 当前没有指向一个任务(如果是第一个任务,则初始化一下任务列表,当前任务指向 创建的新任务。【当前任务指调度器开始运行应该运行的任务】)
  3. 否则如果 pxCurremtTCB 已经有指向,检查调度器如果还未开始运行(pxCurremtTCB 指向优先级较大的任务)
  4. 任务数量 ++
  5. 把 TCB 加入到就绪任务列表(其实是按优先级的指针数组),并设置其状态为就绪
  6. 退出临界区使用 taskEXIT_CRITICAL
  7. 如果调度器还未运行且当前任务优先级小于新创建的,那么执行 taskYIELD_IF_USING_PREEMPTION(当前任务让出,如果使用抢占式调度器)

example1:普通的创建任务

void vTask1 ( void* pvParameters ) 
{
   
    const char* pcTaskName = "task1 is running\r\n";
    volatile uint32_t ul;
    for (;;)
    {
   
        vPrintString( pcTaskName );
        for ( ul = 0; ul < mainDELAY_LOOP_COUNT; ul ++ ) 
        {
   
        }
    }
}

void vTask2 ( void* pvParameters ) 
{
   
    const char* pcTaskName = "task2 is running\r\n";
    volatile uint32_t ul;
    for (;;)
    {
   
        vPrintString( pcTaskName );
        for ( ul = 0; ul < mainDELAY_LOOP_COUNT; ul ++ ) 
        {
   
        }
    }
}
int main()
{
   
    /*......*/
    
    xTaskCreate(    vTask1,      // function pointer
                    "task 1",    // pcName
                    1000,        // stack depth
                    NULL,        // task parameters
                    1,           // task priority 
                    NULL );      // task handle
    
    
    xTaskCreate(    vTask2,      // function pointer
                    "task 2",    // pcName
                    1000,        // stack depth
                    NULL,        // task parameters
                    1,           // task priority 
                    NULL );      // task handle
                    
    vTaskStartScheduler();    // 任务调度器
    
    /*......*/
}

在这里插入图片描述
众所周知的一张图,就不详细介绍了,意思就是单核处理器上任务一、二肯定不是同时运行的,而是每个任务占一定的时间,之后就会被换出,换另一个任务执行。

example2:任务中创建任务

void vTask1 ( void* pvParameters ) 
{
   
    const char* pcTaskName = "task1 is running\r\n";
    volatile uint32_t ul;
    
    
    xTaskCreate(    vTask2,      // function pointer
                    "task 2",    // pcName
                    1000
中文的参考手册 内容 Contents5..................................................................................................................................................... 列表 Figures8............................................................................................................................................... 代码清单 Listings9....................................................................................................................................... Tables15 名单.............................................................................................................................................. 列表 Notation15........................................................................................................................................... 章节 1 关于这............................................................................................................................. Manual16 1.1Scope17............................................................................................................................................. 章节 2Task 和调度........................................................................................................................... API20 2.1 portSWITCH_TO_USER_MODE() 21.................................................................................. 2.2 vTaskAllocateMPURegions() 22........................................................................................... 2.3 xTaskAbortDelay() 25............................................................................................................. 2.4 xTaskCallApplicationTaskHook() 27.................................................................................... 2.5 xTaskCheckForTimeOut() 30................................................................................................ 2.6 xTaskCreate() 32..................................................................................................................... 2.7 xTaskCreateStatic() 37........................................................................................................... 2.8 xTaskCreateRestricted() 41................................................................................................... 2.9 vTaskDelay() 46....................................................................................................................... 2.10 vTaskDelayUntil() 48............................................................................................................... 2.11 vTaskDelete() 51..................................................................................................................... 2.12 taskDISABLE_INTERRUPTS() 53........................................................................................ 2.13 taskENABLE_INTERRUPTS() 55......................................................................................... 2.14 taskENTER_CRITICAL() 56.................................................................................................. 2.15 taskENTER_CRITICAL_FROM_ISR() 59........................................................................... 2.16 taskEXIT_CRITICAL() 61....................................................................................................... 2.1 taskEXIT_CRITICAL_FROM_ISR() 63................................................................................ 2.2 xTaskGetApplicationTaskTag() 65....................................................................................... 2.3 xTaskGetCurrentTaskHandle() 67........................................................................................ 2.4 xTaskGetIdleTaskHandle() 68............................................................................................... 2.1 xTaskGetHandle() 69.............................................................................................................. 2.2 uxTaskGetNumberOfTasks() 71........................................................................................... 2.3 vTaskGetRunTimeStats() 72................................................................................................. 2.4 xTaskGetSchedulerState() 76...............................................................................................六 2.5 uxTaskGetStackHighWaterMark() 77.................................................................................. 2.6 eTaskGetState() 79................................................................................................................. 2.7 uxTaskGetSystemState() 81.................................................................................................. 2.8 vTaskGetTaskInfo() 85........................................................................................................... 2.9 pvTaskGetThreadLocalStoragePointer() 87.......................................................................7 2.10 pcTaskGetName() 89.............................................................................................................. 2.11 xTaskGetTickCount() 90........................................................................................................ 2.12 xTaskGetTickCountFromISR() 92........................................................................................ 2.13 vTaskList() 94........................................................................................................................... 2.14 xTaskNotify() 97....................................................................................................................... 2.15 xTaskNotifyAndQuery() 100.................................................................................................. 2.16 xTaskNotifyAndQueryFromISR() 104.................................................................................. 2.17 xTaskNotifyFromISR() 108.................................................................................................... 2.18 xTaskNotifyGive() 113............................................................................................................ 2.19 vTaskNotifyGiveFromISR() 116............................................................................................ 2.20 xTaskNotifyStateClear() 119.................................................................................................. 2.21 ulTask​ ​ NotifyTake() 121.................................................................................................. 2.22 xTaskNotifyWait() 124............................................................................................................ 2.23 uxTaskPriorityGet() 127.......................................................................................................... 2.24 vTaskPrioritySet() 129............................................................................................................ 2.25 vTaskResume() 131................................................................................................................ 2.26 xTaskResumeAll() 133........................................................................................................... 2.27 xTaskResumeFromISR() 136................................................................................................ 2.28 vTaskSetApplicationTaskTag() 139...................................................................................... 2.29 vTaskSetThreadLocalStoragePointer() 141........................................................................ 2.30 vTaskSetTimeOutState() 143................................................................................................ 2.31 vTaskStartScheduler() 145.................................................................................................... 2.32 vTaskStepTick() 147............................................................................................................... 2.33 vTaskSuspend() 149............................................................................................................... 2.34 vTaskSuspendAll() 151.......................................................................................................... 2.35 taskYIELD() 153...................................................................................................................... 章节 3Queue.................................................................................................................................. API155 3.1 vQueueAddToRegistry() 156................................................................................................. 3.2 xQueueAddToSet() 158.......................................................................................................... 3.3 xQueueCreate() 160............................................................................................................... 3.4 xQueueCreateSet() 162......................................................................................................... 3.5 xQueueCreateStatic() 166..................................................................................................... 3.6 vQueueDelete() 168................................................................................................................ 3.7 pcQueueGetName() 170........................................................................................................ 3.8 xQueueIsQueueEmptyFromISR() 171................................................................................. 3.9 xQueueIsQueueFullFromISR() 172...................................................................................... 3.10 uxQueueMessagesWaiting() 173.......................................................................................... 3.11 uxQueueMessagesWaitingFromISR() 174..........................................................................六 3.12 xQueueOverwrite() 176.......................................................................................................... 3.13 xQueueOverwriteFromISR() 178.......................................................................................... 3.14 xQueuePeek() 180.................................................................................................................. 3.15 xQueuePeekFromISR() 183.................................................................................................. 3.16 xQueueReceive() 184............................................................................................................. 3.17 xQueueReceiveFromISR() 187............................................................................................. 3.18 xQueueRemoveFromSet() 190............................................................................................. 3.19 xQueueReset() 192................................................................................................................. 3.20 xQueueSelectFromSet() 193................................................................................................. 3.21 xQueueSelectFromSetFromISR() 195................................................................................. 3.22 xQueueSend() , xQueueSendToFront() , xQueueSendToBack() 197............... 3.23 xQueueSendFromISR() , xQueueSendToBackFromISR() , xQueueSendToFrontFromISR() ............................................................200 3.24 uxQueueSpacesAvailable() 204............................................................................................ 章节 4Semaphore......................................................................................................................... API206 4.1 vSemaphoreCreateBinary() 207........................................................................................... 4.2 xSemaphoreCreateBinary() 210........................................................................................... 4.3 xSemaphoreCreateBinaryStatic() 213................................................................................. 4.4 xSemaphoreCreateCounting() 216....................................................................................... 4.5 xSemaphoreCreateCountingStatic() 219............................................................................. 4.6 xSemaphoreCreateMutex() 222............................................................................................ 4.7 xSemaphoreCreateMutexStatic() 224.................................................................................. 4.8 xSemaphoreCreateRecursiveMutex() 226.......................................................................... 4.9 xSemaphoreCreateRecursiveMutexStatic() 229................................................................ 4.10 vSemaphoreDelete() 231....................................................................................................... 4.11 uxSemaphoreGetCount() 232............................................................................................... 4.12 xSemaphoreGetMutexHolder() 233...................................................................................... 4.13 xSemaphoreGive() 234.......................................................................................................... 4.14 xSemaphoreGiveFromISR() 236.......................................................................................... 4.15 xSemaphoreGiveRecursive() 239......................................................................................... 4.16 xSemaphoreTake() 242.......................................................................................................... 4.17 xSemaphoreTakeFromISR() 245.......................................................................................... 4.18 xSemaphoreTakeRecursive() 247........................................................................................ 章节 5Software 定时器................................................................................................................. API251 5.1 xTimerChangePeriod() 252.................................................................................................... 5.2 xTimerChangePeriodFromISR() 255.................................................................................... 5.3 xTimerCreate() 257................................................................................................................. 5.4 xTimerCreateStatic() 261.......................................................................................................9 5.5 xTimerDelete() 265.................................................................................................................. 5.1 xTimerGetExpiryTime() ....................................................................................................267 5.1 pcTimerGetName() 269.......................................................................................................... 5.2 xTimerGetPeriod() 270........................................................................................................... 5.3 xTimerGetTimerDaemonTaskHandle() 271........................................................................ 5.4 pvTimerGetTimerID() 272...................................................................................................... 5.5 xTimerIsTimerActive() 274..................................................................................................... 5.6 xTimerPendFunctionCall() 276.............................................................................................. 5.7 xTimerPendFunctionCallFromISR() 278..............................................................................8 5.8 xTimerReset() 281................................................................................................................... 5.9 xTimerResetFromISR() 284................................................................................................... 5.10 vTimerSetTimerID() 286......................................................................................................... 5.11 xTimerStart() 288..................................................................................................................... 5.12 xTimerStartFromISR() 290..................................................................................................... 5.13 xTimerStop() 292..................................................................................................................... 5.14 xTimerStopFromISR() 294..................................................................................................... 章节 6Event 组............................................................................................................................... API296 6.1 xEventGroupClearBits() 297.................................................................................................. 6.2 xEventGroupClearBitsFromISR() 299.................................................................................. 6.3 xEventGroupCreate() 302...................................................................................................... 6.4 xEventGroupCreateStatic() 304............................................................................................ 6.1 vEventGroupDelete() 306...................................................................................................... 6.2 xEventGroupGetBits() 307..................................................................................................... 6.1 xEventGroupGetBitsFromISR() 308..................................................................................... 6.2 xEventGroupSetBits() 309..................................................................................................... 6.3 xEventGroupSetBitsFromISR() 311..................................................................................... 6.1 xEventGroupSync() 314......................................................................................................... 6.2 xEventGroupWaitBits() 318................................................................................................... 章节 7Kernel................................................................................................................. Configuration321 7.1 FreeRTOSConfig.h322............................................................................................................... 7.2 常量开始“INCLUDE_”...........................................................................................................323 7.3 常量开始“配置”.......................................................................................................................327 附录 1: 数据类型和编码样式.................................................................................................. Guide347
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥羊也

感谢给肥羊投喂!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值