FreeRTOS在校期间自学过一段时间,然而出来工作却用不上。 最近在搞东西需要用到RTOS,特意把笔记整理一下,算是复习了。笔记整理主要来源于正点原子的开发文档、视频教程。
文章目录
- 一、FreeRTOS简介
- 二、FreeTROS移植
- 三、测试例程
- 四、实验效果
一、FreeRTOS简介
-
RTOS:Real Time Operating System,实时操作系统,FreeTROS是一个免费的操作系统。它相对其他操作系统而已更加简单,文件数量更少,文档资料相对齐全。
-
FreeRTOS和裸机的区别
裸机是在一个while循环中执行任务,只有执行完了上一个才能执行下一个:
int main()
{
while(1)
{
打游戏();
吃饭();
}
}
RTOS是将多任务分散开,每个任务执行一个时间,然后切换到下一个任务:
int main()
{
/*创建任务1*/
xTaskCreate(打游戏);
/*创建任务2*/
xTaskCreate(吃饭);
}
void 游戏(void)
{
while(1)
{
打游戏();
}
}
void 干饭(void)
{
while(1)
{
吃饭();
}
}
裸机与RTOS的区别如下:
裸机 | RTOS |
---|---|
裸机要轮流执行,执行速度很慢 | 操作系统可以实现多线程,虽然同一时间只能做一件事但是切换很快, |
裸机只能使用中断实现,要一步步执行到中断的程序才可以触发 | 操作系统可以抢占线程 |
裸机在等待延时的时候,还占用cpu | 操作系统在等待延时的时候,可以让出cpu |
裸机是全部任务在一个无限循环中 | rtos是每个任务一个无限循环 |
二、FreeTROS移植
-
前往官网下载资料:https://www.freertos.org
然后点击下载即可。
下载之后会看到有这么多东西:
实际上,我们只用到第一个文件夹FreeRTOS里的内容,其他文件都暂时用不到。 -
移植步骤:
本
(1)复制一个裸机的例程,新建一个命名为FreeRTOS的文件夹
(2)把下载好的FreeRTOS\Source的内容复制到上一步新建的FreeRTOS文件夹内:
(3)打开keil工程,新建两个目录,FreeRTOS_CODE、FreeRTOS_PORTABLE
(4)FreeRTOS_CODE内添加FreeRTOS目录里的几个.c文件
在FreeRTOS_PORTABLE内添加port.c(在FreeRTOS\portable\RVDS\ARM_CM4F),然后添加heap_4.c(在FreeRTOS\portable\MemMang)
到此,所需的文件添加好了。
如果直接编译程序会报错:
如何处理这些错误是十分关键的。详情参考:STM32F103–移植FreeRTOS完整教程
三、测试例程
主函数 main.c代码如下:
//main.c
#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 FLOAT_TASK_PRIO 3 //任务优先级
#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);
//浮点测试任务
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任务函数
void led0_task(void *pvParameters)
{
while(1)
{
LED0=~LED0;
vTaskDelay(500);
}
}
//浮点测试任务
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);
}
}
四、实验效果
实验效果如下:
LED引脚电平500ms改变一次,一闪一闪的
与此同时,接上串口,可以看到大约每1000ms打印一次累加的浮点数
(想不到弄个GIF动图都那么麻烦)
程序晚一会贴出来,未完待续…