概述

本文对FreeRTOS源码进行概述,包括其核心文件作用,及其编程规范,有助于阅读rtos的内核源码,更好的帮助理解。

一、FreeRTOS 源码核心结构概述

FreeRTOS 是轻量级实时操作系统,核心功能围绕 “任务调度” 和 “任务间通信” 展开,源码结构清晰,可分为内核核心文件可选组件

类别 核心文件 主要功能
任务管理 task.c 任务创建(xTaskCreate())、删除、挂起 / 恢复,以及核心的调度器实现(vTaskStartScheduler())。
调度器核心 同上(调度逻辑嵌入task.c 基于优先级的抢占式调度(可配置为时间片轮转),上下文切换(portYIELD())。
队列 / 通信 queue.c/list.c 实现队列(任务间数据传递)、信号量(SemaphoreHandle_t)、互斥锁(MutexHandle_t)等。
时间管理 timers.c 软件定时器(xTimerCreate()),基于系统时基触发回调函数。
配置文件 FreeRTOSConfig.h 内核裁剪配置(如任务最大优先级、栈大小、钩子函数使能等),是适配硬件的关键。
硬件接口 port.c/portmacro.h 与 CPU 架构相关的底层实现(如 ARM Cortex-M 的上下文切换、中断处理),由芯片厂商适配。

二、STM32CubeMX 生成的 RTOS 中间件文件及作用

CubeMX 会自动集成 FreeRTOS 源码,并生成适配 STM32 的配置文件初始化代码,核心文件如下(以 STM32 工程为例):

  1. FreeRTOSConfig.h

    • 作用:FreeRTOS 的 “开关面板”,由 CubeMX 根据用户配置(如任务优先级数量、栈大小、是否启用互斥锁等)自动生成。
    • 关键配置项:
      • configMAX_PRIORITIES:最大任务优先级(如5,数值越大优先级越高);
      • configTOTAL_HEAP_SIZE:内核堆大小(任务、队列等动态内存从这里分配);
      • configUSE_PREEMPTION:是否启用抢占式调度(1启用,实时性核心);
      • configUSE_IDLE_HOOK:是否启用空闲任务钩子函数(自定义空闲任务行为)。
  2. MX_FreeRTOS_Init.c/MX_FreeRTOS_Init.h

    • 作用:用户任务的初始化入口,CubeMX 会在此文件中生成任务创建代码(基于用户在 CubeMX 中配置的任务)。

    • 典型内容:

      void MX_FreeRTOS_Init(void) {
      // 创建任务(参数:任务函数、名称、栈大小、参数、优先级、任务句柄)
      xTaskCreate(StartDefaultTask, "DefaultTask", 128, NULL, 1, &DefaultTaskHandle);
      // 若配置了其他任务(如Task1、Task2),会在此处继续创建
      }
  3. stm32f1xx_it.c(中断服务函数文件)

    • 作用:集成 FreeRTOS 的中断适配,主要是系统时基中断(通常用 SysTick 定时器)。

    • 关键代码:

      void SysTick_Handler(void) {
      HAL_IncTick(); // HAL库时基
      if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
      xPortSysTickHandler(); // 调用FreeRTOS的SysTick处理函数,用于任务调度计时
      }
      }
  4. FreeRTOS 官方源码文件

    CubeMX 会将task.cqueue.ctimers.c等核心文件复制到工程的Middlewares/Third_Party/FreeRTOS/Source目录下,与硬件无关的逻辑保持不变。

三、FreeRTOS 源码的 “入口函数”

FreeRTOS 的运行始于调度器启动,整体流程如下(结合 CubeMX 生成的代码):

  1. 用户程序入口:main()函数

    CubeMX 生成的main.c中,main()先初始化硬件(HAL_Init()、时钟配置等),再调用MX_FreeRTOS_Init()创建任务,最后启动调度器:

    /* Init scheduler */
    osKernelInitialize(); /* 初始化FreeRTOS运行环境 */
    MX_FREERTOS_Init(); /* 创建任务 */ /* Start scheduler */
    osKernelStart(); /* 启动调度器 里面调用vTaskStartScheduler()函数*/
  2. 调度器启动:vTaskStartScheduler()

    位于task.c,是 FreeRTOS 内核真正开始工作的入口,主要做三件事:

    • 初始化内核数据结构(任务链表、就绪列表、堆内存等);
    • 创建空闲任务prvIdleTask,优先级最低,用于释放删除的任务内存);
    • 触发第一次上下文切换(portRESTORE_CONTEXT()),切换到最高优先级的就绪任务执行。
  3. 第一个执行的任务

    调度器启动后,会从 “就绪列表” 中选择优先级最高的任务执行。若用户在MX_FreeRTOS_Init()中创建了StartDefaultTask(默认任务),且它是最高优先级,则第一个执行的就是该任务。

四、FreeRTOS 源码的 “编程规则”

1、基础数据类型的前缀规则

FreeRTOS 不直接使用 C 语言原生类型(如intlong,因不同平台长度可能不同),而是通过自定义类型实现跨平台,这些类型的前缀有明确含义:

前缀 含义 对应原生类型(举例) 用途场景
u Unsigned(无符号) unsigned charunsigned int 无符号整数(如计数、长度)
s Signed(有符号) signed charsigned int 有符号整数(如差值、偏移量)
x 结构体 / 枚举 / 大型类型(自定义) 无固定原生类型(如任务控制块、队列) 复杂结构(任务、队列、事件组)
p Pointer(指针) 任意类型的指针 指向变量、数组、结构体的指针
ul Unsigned Long(无符号长整数) unsigned long(通常 32 位) 较大的无符号数值(如系统时间)
l Long(有符号长整数) long(通常 32 位) 较大的有符号数值

2、典型组合示例(前缀 + 类型)

这些组合在源码中高频出现,掌握后能快速识别变量用途:

变量 / 类型示例 前缀解析 含义说明
uint8_t u(无符号)+ int8 8 位无符号整数(等价于unsigned char
int32_t s(隐含)+ int32 32 位有符号整数(等价于int32_t
pucBuffer p(指针)+ u(无符号)+ c(字符) 指向无符号字符数组的指针(缓冲区指针)
pxTaskTCB p(指针)+ x(结构体) 指向任务控制块(TCB,结构体)的指针
ulTickCount ul(无符号长整数) 以系统时基为单位的计数器(如uint32_t
xQueueHandle x(自定义类型) 队列句柄(本质是指向队列结构体的指针)
s16Error s(有符号)+ 16(16 位) 16 位有符号错误码

3、FreeRTOS 核心自定义类型(带固定前缀)

除了基础类型,FreeRTOS 定义了大量用于特定功能的类型,其命名也遵循规则:

自定义类型 前缀 / 后缀 含义与用途
BaseType_t Base(基础) 平台默认的 “基础整数类型”(通常是 32 位有符号),作为多数 API 的返回值类型(如成功返回pdPASS)。
TickType_t Tick(时基) 用于表示系统时基( ticks )的类型(通常是uint32_t),如vTaskDelay()的参数类型。
TaskHandle_t Handle_t(句柄) 任务句柄(本质是指向TCB_t结构体的指针),用于操作任务(如vTaskSuspend(TaskHandle_t))。
QueueHandle_t Handle_t 队列句柄(指向队列结构体的指针),用于队列操作(如xQueueSend(QueueHandle_t))。
SemaphoreHandle_t Handle_t 信号量句柄(与队列句柄通用,因信号量基于队列实现)。
TCB_t TCB(任务控制块) 任务控制块结构体(x类型),存储任务的所有信息(栈、优先级、状态等)。

4、特殊标识:宏定义与常量的前缀

FreeRTOS 的宏和常量也有前缀规则,用于区分功能:

前缀 含义 示例
pd Portable Define(可移植定义) pdTRUE(真)、pdFALSE(假)、pdPASS(成功)、pdFAIL(失败)。
config 配置项(来自FreeRTOSConfig.h configMAX_PRIORITIES(最大优先级)、configTICK_RATE_HZ(时基频率)。
err 错误码 errQUEUE_FULL(队列满)、errTIMEOUT(超时)。

5、通过前缀快速理解源码的技巧

  1. 看到p开头的变量:立即识别为指针(如pxCurrentTCB是当前任务 TCB 的指针)。
  2. 看到x开头的类型 / 变量:通常是结构体或复杂类型(如xTaskCreate()返回的是BaseType_t,但xQueue是队列结构体实例)。
  3. 看到ul开头的变量:多为 32 位无符号整数(如ulTaskNumber表示任务编号)。
  4. 看到Handle_t结尾的类型:均为 “句柄”,本质是指针,用于操作内核对象(任务、队列等)。

五、阅读源码的建议路径

  1. main()开始,跟踪到freertos.c文件,看到vTaskStartScheduler(),理解调度器启动流程;
  2. 重点看task.c中的xTaskCreate()(任务创建)和vTaskSwitchContext()(任务切换);
  3. 结合FreeRTOSConfig.h的配置项,理解 “可裁剪” 特性(如关闭某个功能后,对应源码不参与编译);
  4. 先忽略硬件相关的port.c,聚焦通用逻辑(任务、队列),再深入架构适配细节。

04-FreeRTOS的概述及编程规范的更多相关文章

  1. 中兴软件编程规范C/C++

    Q/ZX 深圳市中兴通讯股份有限公司企业标准 (设计技术标准) Q/ZX 04.302.1–2003      软件编程规范C/C++                               20 ...

  2. JAVA编程规范(下)

    JAVA编程规范(下) 2016-03-27 6. 代码的格式化 6.1 对代码进行格式化时,要达到的目的 1.     通过代码分割成功能块和便于理解的代码段,使代码更容易阅读和理解: 2.     ...

  3. 华为C语言编程规范

    DKBA华为技术有限公司内部技术规范DKBA 2826-2011.5C语言编程规范2011年5月9日发布 2011年5月9日实施华为技术有限公司Huawei Technologies Co., Ltd ...

  4. C#编程规范

    C#编程规范 Version 1.0   目录 第一章 概述.... 4 规范制定原则.... 4 术语定义.... 4 Pascal 大小写.... 4 Camel 大小写.... 4 文件命名组织 ...

  5. 快速构建Windows 8风格应用23-App Bar概述及使用规范

    原文:快速构建Windows 8风格应用23-App Bar概述及使用规范 本篇博文主要介绍App Bar概述.App Bar命令组织步骤.App Bar最佳实践.   App Bar概述 Windo ...

  6. .NET编程规范

    .NET开发编程规范 第1章 程序的版式 版式虽然不会影响程序的功能,但会影响可读性.程序的版式追求清晰.美观,是程序风格的重要构成因素. 可以把程序的版式比喻为"书法".好的&q ...

  7. jQuery编程规范与最佳实践(附带一些个人的笔记)

    加载jQuery-Loading jQuery 1.坚持使用CDN来加载jQuery,这种别人服务器免费帮你托管文件的便宜干嘛不占呢.点击查看使用CDN的好处,点此查看一些主流的jQuery CDN地 ...

  8. 国内大型的内部 C# 编程规范

    C#编程规范 改动记录 Ver. No 发版日期 编制人 批准人 改动的说明 目   录 1 1.1 1.2 2 2.1 2.1.1      Pascal 大写和小写 2.1.2      Came ...

  9. Qt编程规范

    一.概述 良好的编程规范可以大幅提高一个程序的可读性.可理解性和可维护性. 本规范参考Effective C++中文版.Google C++编码规范及Qt编码风格. 二.头文件 1)      #de ...

  10. 第04章 AOP概述

    第04章 AOP概述 1.AOP概述 ●AOP(Aspect-Oriented Programming,面向切面编程):是一种新的方法论,是对传统 OOP(Object-Oriented Progra ...

随机推荐

  1. 【字节跳动高频面试题】不超过 N 的最大数拼接

    [字节跳动高频面试题]不超过 N 的最大数拼接 题目描述 给定一个按 非递减顺序 排列的数字字符数组 digits(如 ["1","3","5&quo ...

  2. node调用powershell脚本

    前提 .bat 是 Windows 批处理脚本文件的扩展名,用于编写和执行一系列 Windows 命令. .ps1才是是 PowerShell 脚本文件的扩展名,用于编写和执行 PowerShell ...

  3. jenkins部署完微信推送

    前言 我需要一款使用简单方便: 支持微信.企业微信.短信.邮件等通知: 消息多样化,支持markdown等格式消息: 支持消息存储: 免费使用: 于是我找到了一款插件.目前还是免费pushplus. ...

  4. 前端开发系列034-基础篇之RegExp正则表达式

    本文介绍RegExp相关的知识点,包括正则表达式的创建.匹配规则等内容. RegExp简单介绍 正则表达式Regular Expression是描述字符模式的对象,在JavaScript语言中提供了内 ...

  5. 模拟退火 python 实现

    简介 一直以为是一个高深的算法,好像据说在量子计算机中可以应用.发现原理并不难 参考链接 https://blog.csdn.net/google19890102/article/details/45 ...

  6. Day7 备战CCF-CSP练习

    Day 7 题目描述 栋栋最近开了一家餐饮连锁店,提供外卖服务. 随着连锁店越来越多,怎么合理的给客户送餐成为了一个急需解决的问题. 栋栋的连锁店所在的区域可以看成是一个 \(n×n\)的方格图(如下 ...

  7. ETL数据集成丨SQLServer到Doris的无缝数据同步策略

    在数据驱动的新时代,企业对数据的需求日益增加,尤其是数据同步的速度和准确性.随着数据源和数据目标的多样化,如何实现高效.无缝的数据同步成为了许多企业的关注焦点.ETLCloud正是这一领域的先锋,为用 ...

  8. RestCloud ETL抽取动态库表数据实践

    RestCloud ETL社区版是一款数据集成工具,提供可视化多数据管道构建.数据源管理.运行监控及权限管理功能.   1.场景说明: 对于一些业务系统每天运行自动产生一张新数据表,希望通过1条数据流 ...

  9. SciTech-Mathmatics - Advanced Linear Algebra: 矩阵乘法 的 四种理解方式 + 向量 的空间&基、坐标&坐标变换 + Eigenvalue Decompression(特征值分解) + SVD(奇异值分解, Singular Value Decomposition)

    SciTech-Mathmatics - Advanced Linear Algebra(高等线性代数): 矩阵乘法 的 四种理解方式 矩阵乘法有四种理解方式: 线性方程组视角:将矩阵看作行向量与向量 ...

  10. 题解:Luogu-P9433 [NAPC-#1] Stage5 - Conveyors

    传送门 个人认为,做这种题把思路想清晰代码自然就写出来了,所以要注重思考的过程,重点把握一些自己想不到的性质或技巧. 本篇题解在现有题解的基础上对解法进行了更详细的说明.阅读前建议确保自己会树链剖分和 ...