RTOS背景知识介绍
前在使用 51、AVR、STM32 单片机裸机(未使用系统)的时候一般都是在main 函数里面用 while(1)做一个大循环来完成所有的处理,即应用程序是一个无限的循环,循环中调用相应的函数完成所需的处理。有时候我们也需要中断中完成一些处理。相对于多任务系统而言,这个就是单任务系统,也称作前后台系统,中断服务函数作为前台程序,大循环while(1)作为后台程序。
前后台系统的实时性差,前后台系统各个任务(应用程序)都是排队等着轮流执行,不管你这个程序现在有多紧急,没轮到你就只能等着!相当于所有任务(应用程序)的优先级都是一样的。但是前后台系统简单啊,资源消耗也少啊!在稍微大一点的嵌入式应用中前后台系统就明显力不从心了,此时就需要多任务系统出马了。
多任务系统会把一个大问题(应用)“分而治之”,把大问题划分成很多个小问题,逐步的把小问题解决掉,大问题也就随之解决了,这些小问题可以单独的作为一个小任务来处理。这些小任务是并发处理的,注意,并不是说同一时刻一起执行很多个任务,而是由于每个任务执行的时间很短,导致看起来像是同一时刻执行了很多个任务一样。多个任务带来了一个新的问题,究竟哪个任务先运行,哪个任务后运行呢?完成这个功能的东西在 RTOS 系统中叫做任务调度器。不同的系统其任务调度器的实现方法也不同,比如 FreeRTOS 是一个抢占式的实时多任务系统,那么其任务调度器也是抢占式的。
FreeRTOS官网
FreeRTOS在STM32F4xx上的移植
下载FreeRTOS源文件 配置文件
FreeConfig.h配置文件
INCLUDE Config文件
FreeRTOS 任务基础知识
在使用 RTOS 的时候一个实时应用可以作为一个独立的任务。每个任务都有自己的运行环境,不依赖于系统中其他的任务或者 RTOS 调度器。
任何一个时间点只能有一个任务运行,具体运行哪个任务是由 RTOS 调度器来决定的,RTOS 调度器因此就会重复的开启、关闭每个任务。
任务不需要了解 RTOS 调度器的具体行为,RTOS 调度器的职责是确保当一个任务开始执行的时候其上下文环境(寄存器值,堆栈内容等)和任务上一次退出的时候相同。
为了做到这一点,每个任务都必须有个堆栈,当任务切换的时候将上下文环境保存在堆栈中,这样当任务再次执行的时候就可以从堆栈中取出上下文环境,任务恢复运行。
任务特性:
- 简单
- 没有使用限制
- 支持抢占
- 支持优先级
- 每个任务都拥有堆栈导致了ARM使用量增大
- 如果使用抢占,必须仔细考虑重入的问题
任务状态:
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"
#define START_TASK_PRIO 1
#define START_STK_SIZE 256
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);
int main(void)
{
systemInit();
xTaskCreate((TaskFunction_t )start_task,
(const char* )"start_task",
(uint16_t )START_STK_SIZE,
(void* )NULL,
(UBaseType_t )START_TASK_PRIO,
(TaskHandle_t* )&StartTask_Handler);
vTaskStartScheduler();
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
xTaskCreate(Balance_task, "Balance_task", BALANCE_STK_SIZE, NULL, BALANCE_TASK_PRIO, NULL);
xTaskCreate(ICM20948_task, "ICM20948_task", ICM20948_STK_SIZE, NULL, ICM20948_TASK_PRIO, NULL);
xTaskCreate(show_task, "show_task", SHOW_STK_SIZE, NULL, SHOW_TASK_PRIO, NULL);
xTaskCreate(led_task, "led_task", LED_STK_SIZE, NULL, LED_TASK_PRIO, NULL);
xTaskCreate(pstwo_task, "PSTWO_task", PS2_STK_SIZE, NULL, PS2_TASK_PRIO, NULL);
xTaskCreate(data_task, "DATA_task", DATA_STK_SIZE, NULL, DATA_TASK_PRIO, NULL);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
任务创建和删除
参考资料
|