FreeRTOS基础知识---为什么使用FreeRTOS以及其核心功能

🎬 渡水无言个人主页渡水无言

专栏传送门 : 《linux专栏》《嵌入式linux驱动开发》《freertos专栏

⭐️流水不争先,争的是滔滔不绝

📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生

| 省级优秀毕业生获得者 | csdn新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生

在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连

目录

前言

一、裸机系统

[1.1 前后台系统:最基础的裸机架构](#1.1 前后台系统:最基础的裸机架构)

[1.2 时间片轮询系统:裸机的 "进阶版"](#1.2 时间片轮询系统:裸机的 “进阶版”)

二、FreeRTOS系统的引入

三、总结

[3.1. 裸机系统:当简单和极致性能是首选](#3.1. 裸机系统:当简单和极致性能是首选)

[3.2. FreeRTOS:当复杂度和可维护性成为刚需](#3.2. FreeRTOS:当复杂度和可维护性成为刚需)


前言

本期博客我们讲解一下为什么使用rtos以及其核心功能,并和裸机进行区别。


一、裸机系统

1.1 前后台系统:最基础的裸机架构

在没有 RTOS 的裸机开发中,典型的程序结构是一个大循环 while(1),所有任务都在这个循环里顺序执行:

复制代码
#include <stdint.h>

// 全局标志位
uint8_t flag1 = 0, flag2 = 0;

// 硬件初始化
void HardWareInit(void) {
    // 初始化GPIO、中断、定时器等硬件
}

// 任务函数
void run_task_1(void) { /* 任务1具体逻辑 */ }
void run_task_2(void) { /* 任务2具体逻辑 */ }
void run_task_3(void) { /* 任务3具体逻辑 */ }

// 中断服务程序1(前台)
void ISR1(void) {
    flag1 = 1;  // 仅置位标志位,不执行耗时操作
}

// 中断服务程序2(前台)
void ISR2(void) {
    flag2 = 1;  // 仅置位标志位
}

int main(void)
{
    HardWareInit(); /* 硬件相关初始化 */
    
    while(1) 
    {
        if(flag1)
        {
            run_task_1(); /* 执行任务1 */
            flag1 = 0;
        }   
        
        if(flag2)
        {
            run_task_2(); /* 执行任务2 */
            flag2 = 0;
        }

        run_task_3(); /* 持续执行任务3 */
    }
}

这种架构的优势是简单易实现、任务不丢失 ,但致命问题是实时性不可控

  • run_task_3执行耗时 1 分钟,即使中断 1 触发,run_task_1也需等任务 3 执行完毕才能响应;

  • 若将run_task_1直接放入中断执行,又违背 "中断快进快出" 原则 ------ 耗时 1 分钟的中断会阻塞低优先级中断,甚至导致中断丢失。

1.2 时间片轮询系统:裸机的 "进阶版"

时间片轮询是裸机开发的优化方案:以定时器为核心,按预设周期轮询执行不同任务,避免 CPU 空转,是裸机中性价比极高的实现方式。

复制代码
#include <stdint.h>

// 配置任务周期(单位:ms)
#define TASK1_PERIOD 100  // 任务1每100ms执行一次
#define TASK2_PERIOD 200  // 任务2每200ms执行一次

// 全局变量
uint8_t system_timer_flag = 0;
uint16_t task1_hander = 0, task2_hander = 0;

// 硬件初始化
void HardWareInit(void) {
    // 初始化定时器(1ms中断一次)、GPIO等
}

// 任务函数
void run_task_1(void) { /* 任务1具体逻辑 */ }
void run_task_2(void) { /* 任务2具体逻辑 */ }

// 中断服务程序(处理紧急事件)
void ISR1(void) {
    // 仅处理中断核心逻辑,耗时操作移交主循环
}

// 检查系统时标是否到达
uint8_t is_system_tick_arrive(void)
{
   uint8_t flag = system_timer_flag;
   system_timer_flag = 0;
   return flag;
}

// 定时器中断(1ms触发一次)
void Timer_ISR(void)
{
    system_timer_flag = 1;  // 置位时标标志位
}

int main(void)
{
    HardWareInit(); /* 硬件相关初始化 */   
    while(1) 
    {
        if(is_system_tick_arrive())  // 1ms时标到达
        {
            if(++task1_hander == TASK1_PERIOD)  // 任务1周期到
            {
                task1_hander = 0;
                run_task_1();  /* 执行任务1 */
            }
            
            if(++task2_hander == TASK2_PERIOD)  // 任务2周期到
            {
                task2_hander = 0;
                run_task_2();  /* 执行任务2 */
            }
        }
    }
}

时间片轮询优化了 CPU 利用率,但仍无法突破裸机的核心局限:

  • 无优先级管理:高优先级任务(如紧急通信)会被低优先级长耗时任务阻塞;

  • 响应时间不确定:若某任务执行超时(如 1ms 时间片内任务执行了 10ms),后续所有任务周期都会偏移;

  • 任务同步复杂:多任务共享资源时,需手动处理数据一致性,极易出错。

二、FreeRTOS系统的引入

在上一节的基础上,若想对时间片轮询系统的固有弊端进行改进,就需要在每次进入时钟中断前,保存CPU的当前状态和当前事务用到的一些数据,然后我们进入时钟中断进行时间片处理,若发现有新的更紧急的事务的时间片到来了,则我们改变中断的返回的地址,并在CPU中恢复这个更紧急的事务的现场,然后返回中断开始执行这个更紧急的事务。

裸机系统的核心问题是 "无法高效管理多任务",而 FreeRTOS 作为轻量级 RTOS,本质是一套 "成熟的多任务管理框架"------ 它封装了任务调度、内存管理、同步通信等底层逻辑,这就是为什么我们需要RTOS了。

作为RTOS大家庭中重要的一员,FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。其主要特性有:

轻量级和实时性 :FreeRTOS 的内核非常小,通常只需要大约 6KB 到 12KB 的内存空间(取决于平台和编译选项),适合资源受限的系统,并且具有实时任务调度能力。
可移植性 :FreeRTOS 支持多种处理器和编译环境,使得开发人员可以在不同的硬件平台上使用它。
丰富的 API :FreeRTOS 提供了一套丰富的 API,开发人员可以用来创建任务、管理内存、同步任务和通信等。
可伸缩性 :FreeRTOS 可以根据需要定制和扩展,以满足不同的系统需求。
开源和社区支持:FreeRTOS 是开源的,有一个活跃的社区提供支持。

在FreeRTOS中,根据程序的功能,把程序主体分割成一个个独立的,无限循环且不能返回的子程序,称之为任务。每个任务都是独立的,互不干扰的,且具备自身的优先级,它由操作系统调度管理。加入操作系统后,我们不需要关注每个功能模块之间的冲突,重心放在应用程序的实现即可。其执行框架如下图所示。


三、总结

我们不能简单地断言 FreeRTOS 就一定比裸机系统更优秀。技术选型的核心,永远是匹配项目的具体需求。裸机系统以其极简的架构和零操作系统开销,在某些场景下是无可替代的;而 FreeRTOS 则凭借强大的多任务管理能力,成为复杂项目的不二之选。

3.1. 裸机系统:当简单和极致性能是首选

裸机系统(Bare-metal),即不依赖任何操作系统,程序直接在硬件上运行。它在以下场景中表现卓越:

  • 项目规模极小:当你的产品功能非常单一,只需要执行几个线性的、顺序的任务,完全没有多任务并行的需求时,裸机是最高效的选择。例如一个简单的 LED 指示灯控制器或一个独立的按键检测模块。
  • 追求极致性能与响应:裸机没有操作系统调度、内存管理等额外开销,每一条指令都直接服务于业务逻辑。这对于需要亚微级响应时间的应用,如高速电机驱动、高频信号采集等,是至关重要的。
  • 硬件资源极度受限:在一些超低成本、资源极其有限的 MCU 上(如仅有几 KB RAM 和十几 KB Flash 的单片机),FreeRTOS 的内核本身就可能超出硬件的承载能力,此时裸机开发是唯一可行的道路。

3.2. FreeRTOS:当复杂度和可维护性成为刚需

FreeRTOS 作为一款轻量级实时操作系统,为我们提供了强大的工具集,在以下场景中能极大地提升开发效率和系统稳定性:

  • 多任务并行处理:当你的项目需要同时处理多个相互独立的功能模块时,例如一个智能网关需要同时进行 Wi-Fi 通信、传感器数据采集、本地显示和按键响应,FreeRTOS 的任务调度器可以轻松管理这些任务,确保高优先级的任务得到及时响应。
  • 动态内存与复杂数据处理:FreeRTOS 提供了完善的动态内存管理 API,这在处理网络数据包、动态生成 UI 元素或其他需要大量可变数据的场景中,能有效避免内存碎片和泄漏问题。
  • 任务间的同步与互斥:当多个任务需要访问同一个共享资源(如 UART 外设、SPI 总线或一块共享内存)时,FreeRTOS 提供的互斥量、信号量、消息队列等机制,能优雅地解决数据竞争和同步问题,让代码更健壮、更易于维护。
相关推荐
乔碧萝成都分萝17 小时前
二十六、IIO子系统 + SPI子系统 + ICM20608
linux·驱动开发·嵌入式
炸膛坦客18 小时前
FreeRTOS 学习:(二十八)任务调度器 + 启动第一个任务(了解)
stm32·单片机·操作系统·freertos
序安InToo18 小时前
第3课|第一个Ada程序:Hello World深入解析
后端·操作系统·嵌入式
炸膛坦客21 小时前
FreeRTOS 学习:(二十七)死等延时函数会对任务调度产生什么影响
stm32·操作系统·freertos
隔壁大炮1 天前
【中断】中断的概念
单片机·嵌入式·硬件
Zevalin爱灰灰2 天前
基于STM32实现OTA&BootLoader 第二章——外设功能开发
stm32·单片机·物联网·嵌入式
Zevalin爱灰灰2 天前
基于STM32实现OTA&BootLoader 第一章——概述
stm32·单片机·物联网·嵌入式
Zeku3 天前
TCP交错传输多通道实现原理
stm32·freertos·linux应用开发
7yewh3 天前
AM57X Processor SDK Linux - run Installer
linux·嵌入式硬件·硬件架构·嵌入式