
前在使用 51、AVR、STM32 单片机裸机(未使用系统)的时候一般都是在main 函数里面用 while(1)做一个大循环来完成所有的处理,即应用程序是一个无限的循环,循环中调用相应的函数完成所需的处理。有时候我们也需要中断中完成一些处理。相对于多任务系统而言,这个就是单任务系统,也称作前后台系统,中断服务函数作为前台程序,大循环while(1)作为后台程序。
前后台系统的实时性差,前后台系统各个任务(应用程序)都是排队等着轮流执行,不管你这个程序现在有多紧急,没轮到你就只能等着!相当于所有任务(应用程序)的优先级都是一样的。但是前后台系统简单啊,资源消耗也少啊!在稍微大一点的嵌入式应用中前后台系统就明显力不从心了,此时就需要多任务系统出马了。



多任务系统会把一个大问题(应用)“分而治之”,把大问题划分成很多个小问题,逐步的把小问题解决掉,大问题也就随之解决了,这些小问题可以单独的作为一个小任务来处理。这些小任务是并发处理的,注意,并不是说同一时刻一起执行很多个任务,而是由于每个任务执行的时间很短,导致看起来像是同一时刻执行了很多个任务一样。多个任务带来了一个新的问题,究竟哪个任务先运行,哪个任务后运行呢?完成这个功能的东西在 RTOS 系统中叫做任务调度器。不同的系统其任务调度器的实现方法也不同,比如 FreeRTOS 是一个抢占式的实时多任务系统,那么其任务调度器也是抢占式的。


下载FreeRTOS源文件
配置文件
INCLUDE
Config文件
在使用 RTOS 的时候一个实时应用可以作为一个独立的任务。每个任务都有自己的运行环境,不依赖于系统中其他的任务或者 RTOS 调度器。
任何一个时间点只能有一个任务运行,具体运行哪个任务是由 RTOS 调度器来决定的,RTOS 调度器因此就会重复的开启、关闭每个任务。
任务不需要了解 RTOS 调度器的具体行为,RTOS 调度器的职责是确保当一个任务开始执行的时候其上下文环境(寄存器值,堆栈内容等)和任务上一次退出的时候相同。
为了做到这一点,每个任务都必须有个堆栈,当任务切换的时候将上下文环境保存在堆栈中,这样当任务再次执行的时候就可以从堆栈中取出上下文环境,任务恢复运行。
任务特性:
任务状态:
FreeRTOS 中的任务永远处于下面几个状态中的某一个:


优先级:
每 个 任 务 都 可 以 分 配 一 个 从 0~31 (configMAX_PRIORITIES-1) 的 优 先 级,configMAX_PRIORITIES 在文件 FreeRTOSConfig.h 中有定义。

数字越大,优先级越高。优先级数字越低表示任务的优先级越低,0 的优先级最低,configMAX_PRIORITIES-1 的优
先级最高。空闲任务的优先级最低,为 0。
FreeRTOS 调度器确保处于就绪态或运行态的高优先级的任务获取处理器使用权,换句话说就是处于就绪态的最高优先级的任务才会运行。当宏 configUSE_TIME_SLICING 定义为 1 的时候多个任务可以共用一个优先级,数量不限。默认情况下宏 configUSE_TIME_SLICING 在文件FreeRTOS.h 中已经定义为 1。此时处于就绪态的优先级相同的任务就会使用时间片轮转调度器获取运行时间。
任务实现
任务控制块
任务堆栈
示例:
#include "system.h"
//Task priority //任务优先级
#define START_TASK_PRIO 1
//Task stack size //任务堆栈大小
#define START_STK_SIZE 256
//Task handle //任务句柄
TaskHandle_t StartTask_Handler;
//Task function //任务函数
void start_task(void *pvParameters);
//Main function //主函数
int main(void)
{
systemInit(); //Hardware initialization //硬件初始化
//Create the start task //创建开始任务
xTaskCreate((TaskFunction_t )start_task, //Task function //任务函数
(const char* )"start_task", //Task name //任务名称
(uint16_t )START_STK_SIZE, //Task stack size //任务堆栈大小
(void* )NULL, //Arguments passed to the task function //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //Task priority //任务优先级
(TaskHandle_t* )&StartTask_Handler); //Task handle //任务句柄
vTaskStartScheduler(); //Enables task scheduling //开启任务调度
}
//Start task task function //开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //Enter the critical area //进入临界区
//Create the task //创建任务
xTaskCreate(Balance_task, "Balance_task", BALANCE_STK_SIZE, NULL, BALANCE_TASK_PRIO, NULL); //Vehicle motion control task //小车运动控制任务 任务优先级BALANCE_TASK_PRIO = 4
xTaskCreate(ICM20948_task, "ICM20948_task", ICM20948_STK_SIZE, NULL, ICM20948_TASK_PRIO, NULL); //IMU data read task //IMU数据读取任务 任务优先级为3
xTaskCreate(show_task, "show_task", SHOW_STK_SIZE, NULL, SHOW_TASK_PRIO, NULL); //The OLED display displays tasks //OLED显示屏显示任务 任务优先级为3
xTaskCreate(led_task, "led_task", LED_STK_SIZE, NULL, LED_TASK_PRIO, NULL); //LED light flashing task //LED灯闪烁任务 任务优先级为3
xTaskCreate(pstwo_task, "PSTWO_task", PS2_STK_SIZE, NULL, PS2_TASK_PRIO, NULL); //Read the PS2 controller task //读取PS2手柄任务 任务优先级为4
xTaskCreate(data_task, "DATA_task", DATA_STK_SIZE, NULL, DATA_TASK_PRIO, NULL); //Usartx3, Usartx1 and CAN send data task //串口3、串口1、CAN发送数据任务 优先级为4
// 删除任务
vTaskDelete(StartTask_Handler); //Delete the start task //删除开始任务
taskEXIT_CRITICAL(); //Exit the critical section//退出临界区
}

