目录
1、什么是任务
我们平时在使用 51、 AVR、 STM32 单片机裸机(未使用系统)的时候一般都是在main 函数里面用 while(1)做一个大循环来完成所有的处理, 即应用程序是一个无限的循环,循环中调用相应的函数完成所需的处理。
有时候我们也需要中断中完成一些处理。相对于多任务系统而言,这个就是单任务系统,也称作前后台系统,中断服务函数作为前台程序,大循环while(1)作为后台程序。
具体可参考本人另一篇关于前后台系统与RTOS的介绍:https://blog.csdn.net/weixin_42108484/article/details/80557273
2、任务的特性
①简单。
②没有使用限制。
③支持抢占
④支持优先级
⑤每个任务都拥有堆栈导致了 RAM 使用量增大。
⑥如果使用抢占的话的必须仔细的考虑重入的问题。
3、任务的状态
3.1 运行态
当一个任务正在运行时, 那么就说这个任务处于运行态, 处于运行态的任务就是当前正在使用处理器的任务。 如果使用的是单核处理器的话那么不管在任何时刻永远都只有一个任务处于运行态。
3.2 就绪态
处于就绪态的任务是那些已经准备就绪(这些任务没有被阻塞或者挂起), 可以运行的任务,但是处于就绪态的任务还没有运行,因为有一个同优先级或者更高优先级的任务正在运行!
3.3 阻塞态
如果一个任务当前正在等待某个外部事件的话就说它处于阻塞态, 比如说如果某个任务调用了函数 vTaskDelay()的话就会进入阻塞态, 直到延时周期完成。任务在等待队列、信号量、事件组、通知或互斥信号量的时候也会进入阻塞态。任务进入阻塞态会有一个超时时间,当超过这个超时时间任务就会退出阻塞态,即使所等待的事件还没有来临!
3.4 挂起态
像阻塞态一样,任务进入挂起态以后也不能被调度器调用进入运行态, 但是进入挂起态的任务没有超时时间。任务进入和退出挂起态通过调用函数 vTaskSuspend()和 xTaskResume()。
总结:处于就绪态的最高优先级的任务才会运行
4、任务的优先级
每个任务都可以分一个从 0~(configMAX_PRIORITIES-1)的优先级,configMAX_PRIORITIES 在文件 FreeRTOSConfig.h 中有定义,也就是优先级不能超过 32 级。优先级数字越低表示任务的优先级越低,0的优先级最低, configMAX_PRIORITIES-1 的优先级最高。空闲任务的优先级最低,为 0。
处于就绪态的最高优先级的任务才会运行,获取处理器使用权 ,当宏 configUSE_TIME_SLICING 定义为 1 的时候多个任务可以共用一个优先级,数量不限 就绪态的优先级相同的任务就会使用时间片轮转调度器获取运行时间。
5、任务的实现
void vATaskFunction(void *pvParameters)//任务函数本质也是函数,任务名为void类型
{
for( ; ; )//执行过程
{
//编写要实现的任务代码
vTaskDelay(); //FreeRTOS的延时函数
}
//任务函数一般不允许跳出循环,如果一定要跳出循环的话在跳出循环以后一定要调用函数 vTaskDelete(NULL)删除此任务
vTaskDelete(NULL);
}
6、任务控制块
FreeRTOS 的每个任务都有一些属性需要存储, FreeRTOS 把这些属性集合到一起用一个结构体来表示, 这个结构体叫做任务控制块: TCB_t,在使用函数 xTaskCreate()创建任务的时候就会自动的给每个任务分配一个任务控制块。 此结构体在文件 tasks.c 中有定义typedef struct tskTaskControlBlock {}tskTCB;
7、任务堆栈
FreeRTOS 之所以能正确的恢复一个任务的运行就是因为有任务堆栈在保驾护航,任务调度器在进行任务切换的时候会将当前任务的现场(CPU 寄存器值等)保存在此任务的任务堆栈中,等到此任务下次运行的时候就会先用堆栈中保存的值来恢复现场,恢复现场以后任务就会接着从上次中断的地方开始运行。
创建任务的时候需要给任务指定堆栈,如果使用的函数 xTaskCreate()创建任务(动态方法)的话那么任务堆栈就会由函数 xTaskCreate()自动创建,如果使用函数 xTaskCreateStatic()创建任务(静态方法)的话就需要程序员自行定义任务堆栈,然后堆栈首地址作为函数的参数 puxStackBuffer 传递给函数:
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer, //任务堆栈,需要用户定义
StaticTask_t * const pxTaskBuffer )
任务堆栈的数据类型为 StackType_t, StackType_t 本质上是 uint32_t,在 portmacro.h 中有定义 :
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; //StackType_t 类型的变量为 4 个字节
typedef long BaseType_t;
typedef unsigned long UBaseType_t;