FreeRTOS在校期间自学过一段时间,然而出来工作却用不上。 最近在搞东西需要用到RTOS,特意把笔记整理一下,算是复习了。笔记整理主要来源于正点原子的开发文档、视频教程。


一、FreeRTOS简介

  1. RTOS:Real Time Operating System,实时操作系统,FreeTROS是一个免费的操作系统。它相对其他操作系统而已更加简单,文件数量更少,文档资料相对齐全。

  2. 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移植

  1. 前往官网下载资料:https://www.freertos.org
    然后点击下载即可。
    下载之后会看到有这么多东西:
    实际上,我们只用到第一个文件夹FreeRTOS里的内容,其他文件都暂时用不到。

  2. 移植步骤:

    (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动图都那么麻烦)
完整程序和FreeRTOS相关资料放在gitee仓库,链接:https://gitee.com/tang176084/free-rtos-learning