??从系统的角度看,任务是竞争系统资源的最小运行单元。
??FreeRTOS 是一个支持多任务的操作系统,在 FreeRTOS 中,任务可以使用或等待 CPU、使用内存空间等系统资源,并独立于其他任务运行。
??每个任务在自己的环境中运行,在任何时刻,只有一个任务得到运行,FreeRTOS 调度器决定运行哪个任务。调度器会不断的启动、停止每一个任务,宏观上看,所有的任务都在同时进行。
??在 FreeRTOS 中,每个任务都有自己的栈空间 (一段连续的内存),用于保存任务运行环境。任务越多,需要的栈空间就越大,而一个系统能运行多少个任务,取决于系统可用的内存。
??任务通常会运行在一个死循环中,不会退出,如果不需要某个任务,可以调用 FreeRTOS 中的删除任务 API 函数将任务删除,释放系统资源。
FreeRTOS 系统中的任务有四种状态:
? Running—运行态
??当任务处于实际运行时被称之为运行态,即 CPU 的使用权被这个任务占用。
? Ready—就绪态
??处于就绪态的任务是指那些能够运行(没有被阻塞和挂起),但是当前没有运行的任务,因为同优先级或更高优先级的任务正在运行。
? Blocked—阻塞态
??由于等待信号量,消息队列,事件标志组等而处于的状态被称之为阻塞态,另外任务调用延迟函数也会处于阻塞态。
? Suspended—挂起态
??类似阻塞态,通过调用函数 vTaskSuspend() 对指定任务进行挂起,挂起后这个任务将不被执行,只有调用函数 xTaskResume() 才可以将这个任务从挂起态恢复。
使用如下函数启动 FreeRTOS 调度:
vTaskStartScheduler();
启动函数介绍:
函数原型:void vTaskStartScheduler(void);
函数描述:函数 vTaskStartScheduler 用于启动 FreeRTOS 调度器,即启动 FreeRTOS 的多任务执行。
使用这个函数要注意以下几个问题:
空闲任务和可选的定时器任务是在调用这个函数后自动创建的。
正常情况下这个函数是不会返回的。如果有返回,极有可能是用于定时器任务或者空闲任务的内存空间不足造成创建失败,此时需要加大 FreeRTOS 可管理的内存空间。
??空闲任务是 FreeRTOS 系统中没有其它任务运行时自动进入的系统任务,不需要用户创建,启用调度器时,调度器会自动创建空闲任务。
空闲任务的作用:
① 执行删除任务时,系统并不会立即释放任务的内存空间,只会将任务添加到结束列表中,真正的系统资源回收工作在空闲任务中完成。
②可以在空闲任务中实现低功耗功能,后续会详细讲解。
创建任务的方式:
① 静态创建任务,xTaskCreateStatic(),需要自行定义任务栈空间与任务控制块,一般不采用,不作介绍。
②动态创建任务,xTaskCreate(),系统动态分配任务栈空间与任务控制块,应用采用此方式。
动态创建任务函数详解:
函数原型:
函数描述:
函数 xTaskCreate 用于实现 FreeRTOS 操作系统的任务创建,并且还可以自定义任务栈的大小。
第 一 个参数填创建任务的函数名
第 二 个参数是任务名,这个参数主要用于调试的时候方便看是哪个任务
第 三 个参数是任务栈大小,单位 word,也就是 4 字节
第 四 个参数是创建的任务函数的形参
第 五 个参数是定义任务优先级
第 六 个参数是任务句柄,用于区分不同的任务
使用举例:
STM32cubeMX 创建方法:
方法详解:
① 首先利用宏定义定义任务参数结构体变量
#name:将 name 转化为字符串,等效于 “name”
os_thread_def__name: 将 name 以字符串方式拼接,等效于 “os_thread_def_name”
① 调用动态创建函数创建任务,形参为上面的结构体地址
删除任务函数详解:
函数原型:void vTaskDelete(TaskHandle_t xTask); /* 任务句柄 */
函数描述:函数 vTaskDelete 用于实现 FreeRTOS 操作系统的任务删除。
? 第 1 个参数填要删除任务的句柄
使用这个函数要注意以下问题:
① 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1#define INCLUDE_vTaskDelete 1
② 如果此函数里面填的任务 ID 是 NULL,即数值 0 的话,那么删除的就是当前正在执行的任务,此任务被删除后,FreeRTOS 会切换到任务就绪列表里面下一个要执行的最高优先级任务。
③ 在 FreeRTOS 中,创建任务所需的内存需要在空闲任务中释放,如果用户在 FreeRTOS 中调用了这个函数的话,一定要让空闲任务有执行的机会,否则这块内存是无法释放的。另外,创建的这个任务在使用中申请了动态内存,这个内存不会因为此任务被删除而删除,这一点要注意,一定要在删除前将此内存释放。
使用举例:
挂起任务函数详解:
函数原型:void vTaskSuspend(TaskHandle_t xTaskToSuspend); /* 任务句柄 */
函数描述:函数 vTaskSuspend 用于实现 FreeRTOS 操作系统的任务挂起。
? 第 1 个参数填要挂起任务的句柄
使用这个函数要注意以下问题:
① 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1#define INCLUDE_vTaskSuspend 1
② 如果此函数里面填的任务 ID 是 NULL,即数值 0 的话,那么挂起的就是当前正在执行的任务,此任务被挂起后,FreeRTOS 会切换到任务就绪列表里面下一个要执行的高优先级任务。
③ 多次调用此函数的话,只需调用一次 vTaskResume 即可将任务从挂起态恢复。
使用举例:
函数原型:void vTaskResume(TaskHandle_t xTaskToResume); /* 任务句柄 */
函数描述:函数 vTaskResume 用于实现 FreeRTOS 操作系统的任务挂起
? 第 1 个参数填要恢复任务的句柄
使用这个函数要注意以下问题:
① 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1#define INCLUDE_vTaskSuspend 1
② 多次调用函数 vTaskSuspend 的话,只需调用一次 vTaskResume 即可将任务从挂起态恢复。
③ 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的 xTaskResumeFromISR(),以后缀 FromISR 结尾。
使用举例:
函数原型:void vTaskResumeFromISR(TaskHandle_t xTaskToResume); /* 任务句柄 */
函数描述:函数 vTaskResumeFromISR 用于实现 FreeRTOS 操作系统的任务恢复。
? 第 1 个参数填要恢复任务的句柄
使用这个函数要注意以下问题:
① 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1#define INCLUDE_xResumeFromISR 1
② 多次调用函数 vTaskSuspend 的话,只需调用一次 vTaskResumeFromISR 即可将任务从挂起态恢复。
③ 如果用户打算采用这个函数实现中断与任务的同步,要注意一种情况,如果此函数的调用优先于函数 vTaskSuspend 被调用,那么此次同步会丢失,这种情况下建议使用信号量来实现同步。
使用举例:
说明:按键任务手动创建。