恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

FreeRTOS学习日记

  • 首页
  • 资讯中心
  • /
  • FreeRTOS学习日记

相关资讯

2026年软考培训机构避坑指南:这几种班千万别报,踩过坑的人都懂 2026/10/11 5:37:07
卡尔曼滤波在行人跟踪中的建模与MATLAB实战解析 2026/10/11 5:32:07
RHCSA作业一解题思路:命令、权限与系统管理基础实践 2026/10/11 5:32:07

最新资讯

【单片机毕设案例分享】基于ESP32的智能厨房多参数监测与自动处置系统设计 基于单片机的厨房温湿度烟雾火焰监测报警装置设计(030401)
【单片机课设毕设项目】基于物联网的厨房安全隐患监测与自动响应系统设计 基于单片机的厨房环境监测与风扇水泵联动控制装置设计(030401)
英伟达DGX Station GB300技术解析:748GB统一内存背后的三个关键问题
【计算机毕业设计单片机案例】基于ESP32的厨房火灾风险监测与手机端远程告警系统设计 基于WIFI的厨房安全环境监测与自动排烟灭火系统设计(030401)
又一个神级考公脑库-22,375篇真题终于按考点整理了
【Linux操作系统学习】用户与组

今日推荐

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

FreeRTOS学习日记

发布时间:2026/10/11 5:37:07
FreeRTOS学习日记 第一章 FreeRTOS概括1.1 什么是FreeRTOS定义专为微控制器MCU如 STM32设计的轻量级实时操作系统 (RTOS)。核心价值解决复杂项目中代码排队执行效率低下的问题实现多个任务在时间上的“并发”运行看起来像是在同时执行。实时操作系统强调的是任务能否在规定的时间要求内得到响应而不是让CPU运行速度变得更快。1.2 FreeRTOS VS 传统的裸机开发本质区别裸机系统前后台系统所有业务逻辑都在main函数的一个while(1)里“排队”执行。致命弱点使用HAL_Delay()延时属于“死等阻塞”在这期间 CPU 什么都干不了系统资源被严重浪费。int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); while (1) { LED_Task_Function(); UART_Task_Function(); Sensor_Task_Function(); } }FreeRTOS 系统多任务系统程序被拆分成多个独立的“任务Task”。核心优势使用osDelay()等阻塞函数时任务会主动让出 CPU 使用权。在某个任务休息期间CPU 会立刻去执行其他需要工作的任务大大提高了系统的响应速度和资源利用率。HAL_Delay()与osDelay()的区别裸机中常见HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); HAL_Delay(500);HAL_Delay通常依靠HAL时基计数在当前执行流程中等待时间经过。等待期间中断依然可以响应当当前执行流程不会因为调用HAL_Delay()就切换到另一项业务。FreeRTOS中HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); osDelay(500);osDelay会让当前任务进入Blocked状态在等待状态不参与CPU竞争调度器可以安排其他Ready任务运行。注意CMSIS-RTOS2 中osDelay()的参数单位是内核 Tick。若内核 Tick 频率为 1000 Hz则 500 Tick 约等于 500 ms。1.3 FreeRTOS最核心的三个概念任务 (Task)操作系统的基本执行单元。每个任务都是一个独立的小宇宙必须拥有属于自己的无限循环如for(;;)或while(1)。调度器 (Scheduler)FreeRTOS 的“大脑”或“裁判”。它隐藏在后台负责决定在每一个瞬间到底把 CPU 的控制权交给哪个任务。阻塞延时 (osDelay)区别于硬件死等延时调用osDelay()会让当前任务进入“阻塞态”。时间一到调度器会再次将其唤醒。1.4 RTOS程序的生命周期在引入FreeRTOS后main函数的职责就发生了根本性改变其标准执行流程为初始化底层硬件时钟、GPIO 等。创建任务向操作系统注册有哪些任务需要执行。启动内核调度器调用osKernelStart()。注意一旦调度器启动FreeRTOS 将全面接管 CPU程序永远不会执行到main函数底部的while(1)中。使用FreeRTOS后main的主要职责变为初始化硬件、装备RTOS对象并启动调度器。经典流程main() | -- HAL_Init() | -- SystemClock_Config() | -- GPIO、UART等硬件初始化 | -- 初始化RTOS内核 | -- 创建Task、Queue、Semaphore等 | -- osKernelStart() | v Scheduler | v 各个Task运行启动调度器以后正常运行的系统不再依赖main后面while1执行周期性任务。可以总结为main负责系统启动Task负责持续运行的业务。第二章FreeRTOS工程建立与API2.1 STM32CubeMX配置1. 解决时钟冲突在STM32CubeMX配置芯片时有一个非常关键的步骤更改 HAL 库时基源Timebase Source默认情况下HAL 库和 FreeRTOS 都会抢占SysTick系统滴答定时器作为自己的心跳时钟。解决方案在 CubeMX 的System Core - SYS设置中将Timebase Source从SysTick更改为一个基本定时器例如TIM4。把SysTick专门留给 FreeRTOS 使用。2.启用FreeRTOS并创建任务开启中间件在 CubeMX 左侧的Middleware中找到FREERTOS将接口设置为CMSIS_V1对于初学者来说V1 版本的封装比较经典且易懂。配置任务Tasks在Tasks and Queues选项卡中你会看到系统已经为你建好了一个默认任务defaultTask。点击Add再创建一个新任务命名为myTask02。配置引脚接下来就可以按需编写代码然后开启实验了。2.2 什么是APIAPI 全称是 Application Programming Interface即应用程序编程接口。API可以理解为模块对外提供的一套使用入口。开发者不需要每次都重新编写底层逻辑而是通过规定好的接口完成操作。例如HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);这是 STM32 HAL API。API不只包含函数也可以包括对外公开的数据类型、宏和常量。2.3 CMSIS-RTOS V1、V2 与原生 FreeRTOSFreeRTOS是操作系统内核而CMSIS-RTOS 是ARM制定的一套RTOS接口规范。它们的层次关系为应用代码 | v CMSIS-RTOS2 API | v CMSIS适配层 | v FreeRTOS内核 | v Cortex-M处理器V1 与 V2 是 CMSIS-RTOS 接口的不同版本并不是两种不同操作系统。2.4 Task Name 和 Entry Function 的区别5.4 MSP and PSPFunctionStartLEDTask两者并不相同。Task Name是系统用来识别任务的名称方便调试和管理Entry Function是任务开始运行时调用的C函数。因此如果只把任务名改成LED_Task但 Entry Function 还是StartTask02那么生成的函数可能仍然叫void StartTask02(void *argument)需要分别设置这两项才能让工程命名保持统一。第三章 Task任务的组成和运行状态3.1 Task不只是一个函数一个FreeRTOS Task是可以被调度器独立管理的执行实体。通常包含以下内容Task | -- 任务函数 | -- 独立任务栈 Task Stack | -- 任务控制块 TCB | -- 优先级 Priority | -- 任务状态 State | -- 任务名称、链表节点等信息任务函数只是任务需要执行的代码Task Stack保存任务自己的函数调用信息和上下文TCP保存任务管理信息调度器通过状态和优先级决定任务何时运行。3.2 任务函数的基本形式void StartLEDTask(void *argument) { for (;;) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); osDelay(500); } }长期运行的任务通常采用无线循环。每次完成LED翻转后调用osDelay进入阻塞状态等待指定时间后再继续运行。需要注意的是任务不是必须永久循环。一次性任务完成工作后也可以通过合适的RTOS接口删除自身。3.3 Task的四种常见状态状态英文含义运行态Running当前正在 CPU 上执行就绪态Ready已具备运行条件等待获得 CPU阻塞态Blocked正在等待时间或某个事件挂起态Suspended被显式挂起暂时不参与正常调度其中最容易混淆的就是Ready和Running状态其中Ready表示我可以运行但还没有获得CPU。Running表示我已经获得CPU正在执行。其中阻塞并不是停止整个CPU任务调用osDelay(500);后Task A Running | v 调用 osDelay() | v Task A Blocked | v Scheduler选择其他Ready Task时间到后Task A Blocked | v Task A Ready | v 调度器决定是否运行Task A因此Blocked-Ready不等于Blocked-Running任务恢复Ready后仍要按照调度规则竞争CPU。第四章 调度器与任务优先级4.1 调度器的基本规则在抢占式FreeRTOS调度中最重要的规则是选择当前最高优先级的Ready Task运行。分析任务运行情况时可以依次考虑第一步哪些Task处于Ready 第二步Ready任务中谁的优先级最高 第三步如果优先级相同如何进行轮转需要注意任务优先级和NVIC中断优先级的区别。对于原生FreeRTOS数字越大优先级越高但是中断优先级则是数字越小优先级越高。4.2 抢占式优先级假设Task ALowRunning Task BHighBlocked当Task B 等待的条件满足后任务B会有阻塞态变为就绪态。因为B的优先级更高在允许抢占的条件下调度器会请求进行任务切换。Task A Running | v Task B变成Ready | v 发现Task B优先级更高 | v 请求PendSV | v 保存Task A上下文 | v 恢复Task B上下文 | v Task B Running当然高优先级和任务也可能让低优先级的任务运行如果高优先级的任务调用osDelay(500)它会进入Blocked状态由于它不在参与CPU竞争低优先级Ready Task就有机会运行。4.3 饥饿Starvation高优先级任务不调用osDelay时会导致低优先级的任务没有正常串口输出原因高优先级任务由于优先级更高并且始终保持可运行状态。任务是否获得CPU 不仅取决于优先级还取决于其他高优先级任务是否具有运行资格。4.4 同优先级时间片轮转实验中将LED_Task Normal Print_Task Normal两个任务都不调用osDelay()。LED 不断翻转Print 不断输出。实际现象LED看起来一直亮着 串口持续打印这是因为两个任务在相同优先级下共享 CPU。在启用抢占和时间片轮转的配置中系统 Tick 可以促使同优先级 Ready Task 轮流运行。LED 翻转速度太快时人眼无法分辨每次亮灭所以可能表现为常亮或亮度变化。时间片轮转不是按照程序中人为写定的 500 ms、1000 ms 分配执行时间而是由调度机制决定。4.5 Idle TaskIdle Task是FreeRTOS自动创建的空闲任务。当其他用户任务全部Blocked时调度器依然需要找到一个可以运行的任务。所以就有了Idle Task一般其拥有最低优先级除了提供空闲时可运行任务它还承担部分内核资源清理工作例如处理某些已经删除任务的资源回收它不能作为普通无用任务随便删除。第五章 TCB、任务栈、上下文切换5.1 TCBTCB 全称是 Task Control Block任务控制块。其中包括任务栈指针、优先级、链表节点等管理信息。需要特别注意的是TCB 并不是直接存放所有上下文寄存器的地方大量寄存器现场实际上保存在任务自己的栈中而TCB则保存相应的栈顶指针等信息。Task A TCB | -- pxTopOfStack -------- | | -- Priority | | v -- List Item Task A Stack | -- 寄存器现场 -- 函数栈帧 -- 局部数据5.2 栈栈是一块按照后进先出LIFO原则使用的内存区域。在STM32常见的Cortex-M环境中栈向低地址方向增长函数调用、局部数据保存、寄存器保护等操作都可能要使用栈空间。每一个Task都需要独立的栈假设Task A正在执行StartTaskA() | v FunctionA() | v FunctionB()此时发生任务切换Task A下次恢复的时候必须能够保证继续执行 Function B的后续指令而不是重新从StartTask A开始所以就需要每个任务都需要有自己独立的栈来保存自己函数的调用信息和上下文。5.3 栈帧栈帧是一次函数调用或异常处理在栈上使用的相关空间与现场信息。当一个函数中需要调用另外一个函数的时候就通过栈帧来指向调用链可能在栈上形成相应的函数栈帧。函数返回时相关栈空间就可以重新使用。Cortex-M异常栈帧在常见 Cortex-M3 基本异常进入过程中硬件自动保存R0 R1 R2 R3 R12 LR PC xPSR这些信息构成异常栈帧在典型 FreeRTOS 上下文切换中还需要通过软件保存和恢复 R4R11 等寄存器。这些操作共同保证任务恢复以后能从原来的位置继续执行。5.4 MSP和PSPCortex-M 具有两个重要的栈指针MSPMain Stack Pointer通常用于复位后的初始执行环境以及异常和中断处理。PSPProcess Stack Pointer在线程模式中可以使用典型 Cortex-M FreeRTOS 任务使用 PSP。关系可以理解为Task A Running | v PSP指向Task A Stack切换到 Task B 时保存Task A当前PSP | v 写入Task A TCB | v 从Task B TCB取出栈顶指针 | v 更新PSP | v 恢复Task B上下文需要记住CPU 只有一个 PSP 寄存器不是每个任务都拥有独立的硬件 PSP。每个任务保存的是属于自己的栈顶位置。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号