当前位置: 首页 > news >正文

从FreeRTOS的Task API出发

从FreeRTOS的Task API出发

前言

笔者注意到,不少教程是真的直接上来就告诉你FreeRTOS的架构是如何的,库库的告诉你要理解什么是 RTOS、FreeRTOS 在嵌入式的作用与应用场景;环境准备。但是实际上,如果我们只是先把宏观的知识塞到期盼学习FreeRTOS的嵌入式人,恐怕只会学的有些难受(尽管后面显然会意识到FreeRTOS到底适合在哪些场景)

所以这篇博客压根不打算跟你起手扯大的,而是带你先体验一圈RTOS的编程范式(或者更加通俗的说——如果你使用RTOS组织你的工程,你的代码看起来像是什么样子的)。这里,我们就能带出来基本的任务相关的API(注意笔者不计划在这片博客疯狂讲RTOS的原理,不在这里讲)

从前后台程序到 RTOS 任务模型

笔者认为,在真正学习 Task API 之前,先建立正确的编程范式认知非常重要。

在最传统的无RTOS的单片机上,也就是在绝大多数 8 位 / 32 位单片机裸机工程中,程序结构通常是:

intmain(void){init();// <- 一部分硬件初始化的工作while(1){TaskA();TaskB();TaskC();}}

同时辅以若干中断:

voidSysTick_Handler(void){tick++;}

这种大家最开始学习单片机程序的时候,编写的程序就是满足这样的前后台程序架构的,你可以看到,后台就在默默的轮询执行任务,前台则是招待板上硬件的中断,打断我们的执行处理相关的业务代码,当然,中断内一般咱们不会去执行长期的阻塞任务防止单片机挂死,一般都是直接设置标志位。所以简单的说:

  • 前台(Foreground):中断服务程序 ISR
  • 后台(Background)main()中的while(1)轮询逻辑

这种前后台程序架构比较直接,我相信大部分嵌入式工程师,对于身兼数职(又是画板子又是写程序又是测试又是拉客户的)的同志,这种结构简单,极易上手,代码出问题了有时候一下子执行逻辑是如何触发这个错误的时序图就蹦出来了(也就是代码可控、可预测),最重要的是——有时候使用的单片机就没法跑啥东西的时候,其实只能这样编写了。

但是慢慢伴随业务的扩大,如何协调这些具体的业务代码本身就构成了一个令人头疼的难题了。举个例子,我们假设真的有突发很重要的任务需要执行(比如说用户触发了按钮需要在漫长的后台轮询任务中打断执行流),但是在没有RTOS的项目中这个事情就比较难搞了——毕竟这种轮询都是我让你 → 你让他 → 他再让回来,如果我们每个函数都“没有分寸感”(这里说的分寸感是指——你不得不让一些函数要有速度执行的下限,也就是不能太慢;或者是必须异步;或者是必须时时刻刻的判断其他任务是否触发的变量),系统就直接整体失效了(比如说用户按了半天按钮才轮循到检查Flag变量的部分,这个体验有时候会很致命)

这种根源就是执行的任务代码是不可以被打断的,或者说,在处理器看来,您给定的所有代码的“重要性”是一样的。这种重要性就是我们后面要谈到的——任务优先级了。

在过去的范式里,我们的代码必须仔细可控的标称函数的行为,不可以过多的越过一些条件(不可以太慢,不可以同步阻塞,随时都可以返回),但是如果我们的业务迭代有些迅速,那么在这样小心翼翼的写代码只会让自己埋没在代码的修改中(改了这个挂了那个)。对于这种复杂的业务场景(这就是笔者不赞同点个灯也要RTOS,除非是教学需求),上RTOS就是合适的。

RTOS 的 Task 编程范式

FreeRTOS引入的核心变化是从“我主动让出 CPU” → “由内核决定谁运行”,意味着我们的代码稍微有了一点点不确定性。但是换来的就是巨大的代码清晰和可维护性,以及最重要的,我们的任务终于有了主次而不是在前后台中成为扁平的一条长链。

在RTOS 中,每一个Task就是我们熟悉的独立执行流,是的,就像你单独为点灯写了一个Main函数,单独为驱动OLED写了一个Main函数一样,现在我们放到一个Task函数放心的while(1)而不用担心程序走不出去了。在这里,调度不是由被执行的代码决定而是由内核调度器决定

很快我们就要写这样的代码了:

voidTaskA(void*param){while(1){DoSomethingA();vTaskDelay(pdMS_TO_TICKS(100));}}

💡 这里的while(1)被内核托管的无限循环,而不是裸奔循环。所以放心大胆的使用


两种模型的本质对比

说了很多,看看这个表格吧:

维度前后台程序FreeRTOS Task
并发模型顺序轮询抢占式调度
延时方式软件计数 / 阻塞内核阻塞
时序管理人工维护内核维护
任务重要性隐式显式(优先级)
可扩展性
可读性依赖经验贴近业务

GPT的总结很好——裸机是“人脑调度”,RTOS 是“内核调度”。


快点端上来罢!我等不及了

正常到这里,笔者看到不少的文章和教程就要开始跟你念经——什么是TCB,什么是任务优先级,什么是调度,乱七八糟的东西就来了,但是没有必要。

FreeRTOS在任务创建的时候就写过很长一串注释,这里的注释里的代码,笔者拿过来了:

// 任务函数的标准原型voidvTaskCode(void*pvParameters);// 示例:一个 LED 闪烁任务voidvLedTask(void*pvParameters){// 任务的局部初始化代码// ...vLedInit();// 如果我们打算在任务里初始化// 任务的主体是一个无限循环for(;;){// 1. 执行任务的实际工作// 比如:切换 LED 状态Toggle_LED();// 2. 主动让出 CPU 或进入阻塞状态// 比如:延时 500msvTaskDelay(pdMS_TO_TICKS(500));}// 任务理论上不应该退出 for(;;) 循环。// 如果需要退出,应使用 vTaskDelete(NULL)。}

笔者在之前的教程中就谈到了如何在上位机上模拟RTOS:

#include"FreeRTOS.h"#include"task.h"#include<stdio.h>voidTask1(void*pv){for(;;){printf("Task1 running\n");vTaskDelay(pdMS_TO_TICKS(1000));}}voidTask2(void*args_pv){for(;;){printf("Task2 running\n");vTaskDelay(pdMS_TO_TICKS(3000));}}intmain(void){xTaskCreate(Task1,"t1",configMINIMAL_STACK_SIZE,NULL,1,NULL);xTaskCreate(Task2,"Task2",configMINIMAL_STACK_SIZE,NULL,1,NULL);vTaskStartScheduler();return0;}

不过也没事,如果你的单片机有移植printf,那太好了,直接CV就能用。

笔者之前的RTOS上位机模拟教程和配置教程:

  1. 在上位机上熟悉FreeRTOS API-CSDN博客
  2. 基于STM32F407ZGT6的硬件平台,(可选CubeMX) + PlatformIO软件开发的FreeRTOS部署指南_platformio freertos-CSDN博客
  3. (1 封私信) 在上位机上熟悉FreeRTOS API——环境配置 - 知乎
  4. (1 封私信) 基于STM32F407ZGT6的硬件平台,(可选CubeMX) + PlatformIO软件开发的FreeRTOS部署指南 - 知乎
http://www.cnnetsun.cn/news/100259.html

相关文章:

  • vue基于springboot的基于建筑物识别的无人驾驶车辆路径规划系统
  • 启天 M 系列 Smart Power On/Fast boot 置灰?2 步解锁修改权限!
  • 告别繁琐问卷设计!百考通AI智能助手,5分钟生成专业调研问卷
  • 百考通AI:你的智能学术助手,让毕业论文写作化繁为简
  • IntelliJ IDEA 2025.3 正式发布
  • MyBatis-Flex 来了!完爆MyBatis-Plus?
  • 神经紧张素受体SORT1
  • 高盐高铵根工业废水去除重金属
  • 某211高校讲师晒工资条,网友:公积金数额令人瞩目...
  • Nature Electronics 一种用于多模态皮肤信号监测的柔性触觉接口
  • 小鼠T细胞激活:如何系统解析其发育分化与免疫功能表征?
  • 基于springboot和vue的民航飞机票务管理系统设计与实现
  • 2025年12月-2026年4月,计算机领域涵盖的前言学术会议推荐!
  • 基于单片机的智能镜子系统设计(有完整资料)
  • 国产化替代SSD的标杆之路:天硕TOPSSD以自主可控存储解决方案重塑高端工业存储格局
  • EmotiVoice本地化部署优势:数据安全与响应效率兼得
  • 【Java毕设全套源码+文档】基于springboot的数据库课程在线教学系统设计与实现(丰富项目+远程调试+讲解+定制)
  • 【Java毕设全套源码+文档】基于springboot的实验室安全考试系统设计与实现(丰富项目+远程调试+讲解+定制)
  • 基于QT(C++)实现的翻金币游戏
  • 基于 Spring·Boot和 Vue 框架的校园快递代领系统设计与实现
  • NVIDIA设置疑难杂症诊所:万字终极实战指南
  • 边缘Agent的Docker监控实践(资源利用率提升90%的秘密)
  • 揭秘Docker Scout漏洞导出功能:如何快速获取镜像安全报告
  • 【云原生Agent资源调度实战】:Docker环境下高效分配CPU与内存的5大黄金法则
  • 增长有毒?流血三闯港股!希迪智驾带病叩钟:115亿市值撑得住“白条狂欢”吗?
  • 多模态Agent性能骤降?可能是Docker网络隔离没做好(附诊断清单)
  • 为什么你的Docker镜像总被攻破?:可能是扫描频率设置错了
  • 背胶条分类识别:基于计算机视觉的修复状态差异检测与质量评估系统
  • 【新】基于SSM的高校实验室管理系统【包括源码+文档+调试】
  • Python 爬虫实战:沪深 300 股票(下)—— 适当进阶!爬取往期批量数据