目录
1. 什么是FreeRTOS?
2. FreeRTOS 特点
3. FreeRTOS 移植
3.1 验证程序
1. 什么是FreeRTOS?
我们先看 FreeRTOS 的名字,可以分成两部分:Free 和 RTOS,Free 就是免费的、自由的、不受约束的意思,RTOS 全称是 Real Time Operating System,中文名就是实时操作系统。RTOS 不是指某一个确定的系统,而是指一类系统。比如说 UCOS,FreeRTOS,RTX,RT - Thread 等这些都是 RTOS 类操作系统。
操作系统允许多个任务同时运行,叫做多任务,实际上,一个处理器核心在某一时刻只能运行一个任务。操作系统中任务调度器的责任就是决定在某一时刻究竟运行哪个任务,任务调度在各个任务之间的切换非常快!给人们造成了同一时刻有多个任务同时运行的错觉。
操作系统的分类方式可以由任务调度器的工作方式决定,比如有的操作系统给每个任务分配同样的运行时间,时间到了就轮到下一个任务,Unix操作系统就是如此。RTOS 的任务调度器被设计为可预测的,而这正是嵌入式实时操作系统所需要的,实时环境中要求操作系统必须对某一个事件做出实时的响应,因此系统任务调度器的行为必须是可预测的。像 FreeRTOS 这种传统的 RTOS 类操作系统是由用户给每个任务分配一个任务优先级,任务调度器就可以根据此优先级来决定下一刻应该运行哪个任务。
FreeRTOS 是 RTOS 系统的一种,FreeRTOS 十分的小巧,可以在资源有限的微控制器中运行,当然,FreeRTOS 不仅局限于在微控制器中使用。
2. FreeRTOS 特点
FreeRTOS 是一个可裁剪的小型 RTOS 系统,包括:
- FreeRTOS的内核支持抢占式,合作式和时间片调度。
- SafeRTOS衍生自FreeRTOS,SafeRTOS在代码完整性上相比 FreeRTOS 更胜一筹。
- 提供了一个用于低功耗的 Tickless 模式。
- 系统的组件在创建时可以选择动态或者静态的 RAM ,比如 任务、消息队列、信号量、软件定时器等等。
- 已经在超过 30 种架构的芯片上进行了移植。
- FreeRTOS-MPU 支持 Cortex-M 系列中的 MPU单元,如STM32F407.
- FreeRTOS 系统简单、小巧、易用,通常情况下内核占用 4k-9k字节的空间。
- 高可移植性,代码主要 C 语言编写。
- 支持实时任务和协程(co-routines 也有称为合作式、协同程序)
- 任务与任务、任务与中断之间可以使用任务通知、消息队列、二值信号量、数值型信号量、递归互斥信号量和互斥信号量进行通信和同步。
- 创新的事件组(或者事件标志)。
- 具有优先级继承特性的互斥信号量。
- 高效的软件定时器。
- 强大的跟踪执行功能。
- 堆栈溢出检测功能。
- 任务数量不限。
- 任务优先级不限。
3. FreeRTOS 移植
首先需要先创建一个STM32F407的基本工程,完成初始的配置;
FreeRTOS的移植需要在工程中添加 FreeRTOS_CORE 和 FreeRTOS_PORTABLE 文件;(具体文件的内容去FreeRTOS官方或者正点原子的资料中都有,直接移植即可)
紧接着要在原有的基础之上,修改 stm32f4xx_it.c 、delay.c、sys.c 和 uart.c 文件。
3.1 验证程序
该程序在移植完成 FreeRTOS 的基础之上,实现 LED0 和 LED1 闪烁,且闪烁的频率不同;
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "FreeRTOS.h"
#include "task.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED0_TASK_PRIO 2
//任务堆栈大小
#define LED0_STK_SIZE 50
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 3
//任务堆栈大小
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
//任务优先级
#define FLOAT_TASK_PRIO 4
//任务堆栈大小
#define FLOAT_STK_SIZE 128
//任务句柄
TaskHandle_t FLOATTask_Handler;
//任务函数
void float_task(void *pvParameters);
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口
LED_Init(); //初始化LED端口
//创建开始任务
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(); //进入临界区
//创建LED0任务
xTaskCreate((TaskFunction_t )led0_task,
(const char* )"led0_task",
(uint16_t )LED0_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED0_TASK_PRIO,
(TaskHandle_t* )&LED0Task_Handler);
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//浮点测试任务
xTaskCreate((TaskFunction_t )float_task,
(const char* )"float_task",
(uint16_t )FLOAT_STK_SIZE,
(void* )NULL,
(UBaseType_t )FLOAT_TASK_PRIO,
(TaskHandle_t* )&FLOATTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED0任务函数,控制LED0闪烁,提示系统正在运行
void led0_task(void *pvParameters)
{
while(1)
{
LED0=~LED0;
vTaskDelay(500);
}
}
//LED1任务函数,控制LED1的闪烁
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
}
}
//浮点测试任务,用于测试STM32F4的FPU是否工作正常
void float_task(void *pvParameters)
{
static float float_num=0.00;
while(1)
{
float_num+=0.01f;
printf("float_num的值为: %.4f\r\n",float_num);
vTaskDelay(1000);
}
}