STM32之FreeRTOS移植(重点)

news2025/7/19 21:02:56

  1. RTOS的基本概念

实时操作系统(Real Time Operating System)的简称就叫做RTOS,是指具有实时性、能支持实时控制系统工作的操作系统,RTOS的首要任务就是调度所有可以利用的资源来完成实时控制任务的工作,其次才是提高工作效率。

绝大多数比较简单的产品(中小型产品)是直接在单片机上“裸奔”的,也就是产品不需要搭载RTOS的,但是产品的各个功能想要正常工作都需要主程序来进行调度。

其实RTOS就是一段嵌入在程序中的代码,在系统上电复位后首先被执行,可以理解为用户的主程序,只不过用户把产品的其他功能(子程序)都建立在RTOS之上,在RTOS中可以调用API函数为每个子程序都创建一个任务(也可以叫做线程),用户只需要调用RTOS内核中的相关的API函数接口就可以控制子程序,而且可以为每个任务设置不同的优先级,通过RTOS的调度器进行调度,这样就可以合理的使用CPU。

这里就涉及到产品的设计思路(裸机开发 or RTOS)以及程序的运行方式,可以分为三种:

  • 轮询式

轮询系统指的是程序运行时,先初始化各种硬件,初始化硬件之后程序进入一个死循环中,按照事件的顺序进行执行,该系统的结构非常简单,只适用于按照顺序执行事件并且没有外部事件来打断的情况,轮询系统就非常可靠,但是一旦有外部事件或者外部需要检测的信号来打断,则会造成外部事件的缺失。

int main()

{

//硬件的初始化

while(1)

{

//事件1 LED

//事件2 BEEP

//....... KEY

}

}
  • 前后台

前后台系统就是在轮询系统的基础上增加了中断,进行外部事件检测的时候就在中断中实现,所以中断也被称为前台,而其他事件还是在主程序的死循环中按照顺序执行,一旦中断发生,则会暂停执行后台的while(1),然后去执行前台的中断服务函数,如果事件简短,直接在中断中实现,如果事件复杂,则返回主程序的死循环实现,该方案可以提高程序的实时响应能力。

int main()

{

//硬件的初始化

//注册中断,设置中断的触发条件

while(1)

{

//事件1

//事件2

.....

}

}

//中断服务函数

void XXX_IRQ (void)

{

//执行中断的事件

//执行完成返回main函数

}
  • 多任务

多任务系统指的是在前后台系统的基础上执行外部事件,只不过外部事件是放在任务中执行,不在中断服务函数中执行,一旦某个外部事件满足触发条件,就在中断服务函数中设置事件标志,然后在跳转到任务中执行事件,任务分优先级的,优先级高的任务就先执行,所以程序就会被分割为一个个的任务(不能退出),每个任务都有一个独立的函数来执行的功能。更大程序提高程序的实时性。

void task1(void *arg)

{

while(1)

{

//LED

}

}

void task2(void *arg)

{

while(1)

{

//BEEP

}

}

int main()

{

//硬件的初始化

//注册中断,设置中断的触发条件

//注册任务,根据任务调度器进行调度

}
  1. RTOS的种类

RTOS是实时操作系统的统称,不意味着是某一种确定的操作系统,而是指某一类操作系统,比如最常用的uC/OSII、uC/OSIIIFreeRTOS、RTX、RT-Thread、Huawei LiteOS........每种RTOS各有特色,所以大家可以根据实际需要选择对应的RTOS进行学习。

  • uC/OS

uC/OS是Micrium公司推出的RTOS实时操作系统,分为两个版本: uC/OSII 和 uC/OSIII,该RTOS的特点是开源的、可裁剪的、具有可剥夺型内核,uC/OSII可以支持创建最多255个任务,而uC/OSIII对任务数量没有限制。

uC/OS的发布时间是较早的,所以中文资料是最多的,并且代码例程比较丰富,但是想要在商业中进行使用,需要取得正版授权(花钱),所以大家可以把UCOS作为RTOS的入门。关于uC/OS的资料和源码都可以去官网下载 官网地址:www.micrium.com

  • FreeRTOS

FreeRTOS也是RTOS的一种,在2003年发布,是免费的,虽然起步比UCOS晚,但是由于可以在商业中免费使用,所以目前的市场占有率是最高的,并且很多的半导体公司都和FreeRTOS有很紧密的合作关系,这些半导体公司的评估板绝大多数都是采用FreeRTOS进行程序设计。比如半导体公司发布的SDK(开发工具包)一般也采用FreeRTOS,另外,像蓝牙、WIFI等带协议栈的芯片或者模块也是采用FreeRTOS。

相比于UCOS而言,FreeRTOS的文件数量更少,占用内存空间更少,所以在移植到不同硬件平台的时候更加轻松,FreeRTOS对于任务数量也是没有限制的,而是对于任务的优先级也没有限制

FreeRTOS支持抢占式、时间片调度等算法,而且FreeRTOS是完全免费的,这也是FreeRTOS的核心竞争力。

FreeRTOS可以用在商业领域,不具有版权问题,如果在产品中使用FreeRTOS时没有修改原码,则产品不需要开源,如果使用FreeRTOS的过程修改了原码,则需要把修改的那部分代码进行开源,遵循MIT开源协议。

大家可以去FreeRTOS的官网下载源码以及其他的资料,比如FreeRTOS提供了若干本书籍,比如关于RTOS的API函数的参考手册以及新手教程。 官网地址:www.freertos.org

  • RT-Thread

长期作业:自行观看RT-Thread的相关视频和教程,要求大家可以自行完成Rt-thread的移植。

  1. RTOS的源码下载

想要真正掌握RTOS,则必须要去阅读RTOS的源码,才能理解RTOS是如何对任务进行调度

可以去FreeRTOS的官网下载源码。

  1. 点击选项链接跳转GitHub托管网站,下载FreeRTOS以前的发行源码包, 比如 V9.0.0

  1. 点击GitHub的标签tags,显示所有的FreeRTOS的源码发行版,搜索到V9.0.0版本即可

注意:如果浏览器在登录GitHub网站时等待时间过长,或者无法登录界面,则可以使用其他的代码托管网站进行源码下载,比如Sourceforge代码托管网站 ,搜索FreeRTOS即可。

  1. RTOS源码结构

解压好的源码包内部有一个叫做FreeRTOS的文件夹,该文件夹内部包含FreeRTOS的源码以及许可和通用的头文件,并且还提供丰富的案例供用户在不同的硬件平台使用。

Demo中提供了很多个半导体公司的评估板的代码例程,用户可以参考甚至直接使用。而License文件夹中包含了FreeRTOS的许可文件,大家可以在商业软件中进行参考,在Source文件夹中包含通用的头文件以及针对不同硬件平台的移植文件供用户使用。

五、FreeRTOS的移植

如果想要在项目中利用RTOS对任务进行调度,则需要把RTOS的源码移植到自己的项目中,移植的步骤如下:

  1. 去FreeRTOS的官网下载源码包,源码包的版本可以是V9.0.0或更新的版本 (比较稳定)

  1. 把源码包解压到本地,分析源码包中哪些文件需要移植,可以浏览源码包的readme.txt

  1. 把FreeRTOS源码包中需要移植的文件拷贝到自己工程中对应的文件夹,操作如下所示:

  1. 打开自己的工程,把拷贝过来文件添加到KEIL5工程中,编辑文件夹的结构,如下所示

  1. 配置KEIL5工程的头文件的路径,确保编译器可以找到关于FreeRTOS的头文件,如下:

  1. 编译工程,如果编译之后报错,根据错误原因解决错误,直到编译通过为止,如下所示

  • 提示:__ICCARM__宏定义是和开发工具相关的,该宏定义是IAR软件需要使用的,而目前采用的开发工具是KEIL,KEIL软件需要使用其他的宏定义。

再次编译,发现有函数出现重复定义的情况,port.c和stm32f4xx_it.c中出现,所以可以选择分别进行分析,可以把stm32f4xx_it.c中的函数名称删除即可。

再次编译,发现有5个函数未定义,命名规则是有规律的,都是HooK结尾,Hook是钩子函数,其实属于回调函数的一种,目前由于不知道是否需要使用,可以选择不去定制。

由于FreeRTOS是高度可定制的,定制的功能是由FreeRTOSConfig.h决定,所以需要配置该头文件,裁剪掉这几个功能即可。

再次编译,发现没有出现任何错误和任何警告,则说明FreeRTOS实时操作系统移植成功!!

五、FreeRTOS的任务管理

  • 任务的概念

FreeRTOS是一个支持多任务的实时操作系统,如之前裸机开发时采用的轮询系统而言,主程序是一个死循环,CPU按照死循环中的流程执行代码,而在多任务系统中,用户可以把整个系统分割为多个独立的且不能返回(死循环)的函数,这些函数就被称为任务。

应用程序中的任务都是由FreeRTOS的调度器进行调度,同时每个任务具有独立的栈空间,栈空间其实就是单片机中RAM的一段空间,通常可以提前定义一个全局数组,或者在创建任务的时候对任务的栈空间进行动态的分配,可以参考FreeRTOS的官方资料。

  • 任务的状态

对于FreeRTOS中的任务而言,FreeRTOS的调度器会根据任务的状态决定运行哪个任务,任务的状态一共有四种:运行态、就绪态、挂起态、阻塞态。 可以参考FreeRTOS的官网资料。

  • 任务优先级

FreeRTOS可以为每一个创建的任务分配一个优先级,当然也可以让多个任务共用一个优先级,这里就涉及到调度器的调度算法,有抢占式、时间片一共2种算法。

  • 任务的创建

刚才提到过任务都是独立的,并且每个任务都需要占用一部分RAM空间,单片机中的RAM是有限的,所以FreeRTOS就提供了两种方案为每个任务分配栈空间:静态分配 + 动态分配,而且FreeRTOS提供了不同的函数接口给用户去申请任务的空间。两种分配方案的区别如下:

一般情况下采用动态分配的方案,所以需要调用API函数,名字叫做xTaskCreate(),如下图

  • 启动调度器

  • 任务的删除

FreeRTOS中的任务是可以删除的,如果用户创建的任务只打算运行一次就可以删掉,调用函数接口 vTaskDelete() ,调用该函数就可以把动态创建或者静态创建的任务从任务表中删掉。

  • 任务的挂起

在某些情况下,某些任务可能只运行一段时间,然后让任务暂停运行,过一段时间继续运行,如果采用反复删除和反复创建的方案,就会导致任务之前的数据丢失,FreeRTOS提供一个函数可以把任务挂起,该函数为vTaskSuspend() 。

一旦任务被挂起,则不管任务的优先级是否为最高,都不会获得CPU资源,也就是说处于挂起态的任务永远不能进入运行态,除非该任务被恢复,如果想要恢复一个任务,则需要调用vTaskResume()。

  • 任务的恢复

FreeRTOS提供了一个恢复函数,可以让处于挂起态的任务恢复,注意只有被挂起的任务才可以被恢复。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2387434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

R语言科研编程-标准偏差柱状图

生成随机数据 在R中&#xff0c;可以使用rnorm()生成正态分布的随机数据&#xff0c;并模拟分组数据。以下代码生成3组&#xff08;A、B、C&#xff09;随机数据&#xff0c;每组包含10个样本&#xff1a; set.seed(123) # 确保可重复性 group_A <- rnorm(10, mean50, sd…

OpenGL Chan视频学习-11 Uniforms in OpenGL

bilibili视频链接&#xff1a; 【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p5&vd_source44b77bde056381262ee55e448b9b1973 函数网站&#xff1a; docs.gl 说明&#xff1a; 1.之后就不再单独整理网站具体函数了&#xff0c;网站直接翻译…

GitLab 从 17.10 到 18.0.1 的升级指南

本文分享从 GitLab 中文本 17.10.0 升级到 18.0.1 的完整过程。 升级前提 查看当前安装实例的版本。有多种方式可以查看&#xff1a; 方式一&#xff1a; /help页面 可以直接在 /help页面查看当前实例的版本。以极狐GitLab SaaS 为例&#xff0c;在浏览器中输入 https://ji…

产业集群间的专利合作关系

需要准备的文件&#xff1a; 全国的专利表目标集群间的企业名单 根据专利的共同申请人&#xff0c;判断这两家企业之间存在专利合作关系。 利用1_filter_patent.py&#xff0c;从全国的3000多万条专利信息中&#xff0c;筛选出与目标集群企业相关的专利。 只要专利的申请人包…

KT6368A通过蓝牙芯片获取手机时间详细说明,对应串口指令举例

一、功能简介 KT6368A双模蓝牙芯片支持连接手机&#xff0c;获取手机的日期、时间信息&#xff0c;可以同步RTC时钟 1、无需安装任何app&#xff0c;直接使用系统蓝牙即可实现 2、同时它不影响音频蓝牙&#xff0c;还支持一些简单的AT指令进行操作 3、实现的方式&#xff1…

计算机网络实验课(二)——抓取网络数据包,并实现根据条件过滤抓取的以太网帧,分析帧结构

文章目录 一、添加控件二、代码分析2.1 代码2.2 控件初始化2.3 打开和关闭设备2.4 开始和结束捕获2.5 设置捕获条件2.6 捕获数据包 三、运行程序四、结果分析 提要&#xff1a;如果你通过vs打开.sln文件&#xff0c;然后代码界面或者前端界面都没找到&#xff0c;视图里面也没找…

78. Subsets和90. Subsets II

目录 78.子集 方法一、迭代法实现子集枚举 方法二、递归法实现子集枚举 方法三、根据子集元素个数分情况收集 方法四、直接回溯法 90.子集二 方法一、迭代法实现子集枚举 方法二、递归法实现子集枚举 方法三、根据子集元素个数分情况收集 方法四、直接回溯法 78.子集…

ElasticSearch整合SpringBoot

ElasticSearch 整合SpringBoot ES官方提供了各种不同语言的客户端。用来操作ES。这些客户端的本质就是组装DSL语句&#xff0c;通过HTTP请求发送给ES。 设计索引库 跟据数据库的表结构进行ES索引库的创建时。如果字段需要进行倒排索引的时候请为它指定分词器。如果该字段不是…

2025上半年软考高级系统架构设计师经验分享

笔者背景 笔者在成都工作近7年&#xff0c; 一直担任研发大头兵&#xff0c;平日工作主要涵盖应用开发&#xff08;Java&#xff09;与数仓开发&#xff0c;对主流数据库、框架等均有涉猎&#xff0c;但谈不上精通。 最近有一些职业上的想法&#xff0c;了解到软考有那么一丁点…

uni-app学习笔记十二-vue3中创建组件

通过组件&#xff0c;可以很方便地实现页面复用&#xff0c;减少重复页面的创建&#xff0c;减少重复代码。一个页面可以引入多个组件。下面介绍在HBuilder X中创建组件的方法&#xff1a; 一.组件的创建 1.选中项目&#xff0c;右键-->新建目录(文件夹)&#xff0c;并将文…

一键启动多个 Chrome 实例并自动清理的 Bash 脚本分享!

目录 一、&#x1f4e6; 脚本功能概览 二、&#x1f4dc; 脚本代码一览 三、&#x1f50d; 脚本功能说明 &#xff08;一&#xff09;✅ 支持批量启动多个 Chrome 实例 &#xff08;二&#xff09;✅ 每个实例使用独立用户数据目录 &#xff08;三&#xff09;✅ 启动后自…

4 月 62100 款 App 被谷歌下架!环比增长 28%

大家好&#xff0c;我是牢鹅&#xff01;上周刚刚结束的 2025 年 Google I/O 开发者大会&#xff0c; Google Play 带来了一系列的更新&#xff0c;主要围绕提升优质 App 的"发现"、"互动"和"收入"三大核心内容。 这或许正是谷歌生态的一个侧影…

mediapipe标注视频姿态关键点(基础版加进阶版)

前言 手语视频流的识别有两种大的分类&#xff0c;一种是直接将视频输入进网络&#xff0c;一种是识别了关键点之后再进入网络。所以这篇文章我就要来讲讲如何用mediapipe对手语视频进行关键点标注。 代码 需要直接使用代码的&#xff0c;我就放这里了。环境自己配置一下吧&…

PCtoLCD2002如何制作6*8字符

如何不把“等比缩放”前的打勾取消&#xff0c;则无法修改为对应英文字符为6*8。 取消之后就可以更改了&#xff01;

SmartPlayer与VLC播放RTMP:深度对比分析延迟、稳定性与功能

随着音视频直播技术的发展&#xff0c;RTMP&#xff08;实时消息传输协议&#xff09;成为了广泛应用于实时直播、在线教育、视频会议等领域的重要协议。为了确保优质的观看体验&#xff0c;RTMP播放器的选择至关重要。大牛直播SDK的SmartPlayer和VLC都是在行业中广受欢迎的播放…

Qt QPaintEvent绘图事件painter使用指南

绘制需在paintEvent函数中实现 用图片形象理解 如果加了刷子再用笔就相当于用笔画过的区域用刷子走 防雷达&#xff1a; 源文件 #include "widget.h" #include "ui_widget.h" #include <QDebug> #include <QPainter> Widget::Widget(QWidget…

伪创新-《软件方法》全流程引领AI-第1章 04

《软件方法》全流程引领AI-第1章 ABCD工作流-01 对PlantUML们的评价-《软件方法》全流程引领AI-第1章 02 AI辅助的建模步骤-《软件方法》全流程引领AI-第1章 03 第1章 ABCD工作流 1.5 警惕和揭秘伪创新 初中数学里要学习全等三角形、相似三角形、SSS、SAS……&#xff0c;到…

【iOS】 锁

iOS 锁 文章目录 iOS 锁前言线程安全锁互斥锁pthread_mutexsynchronized (互斥递归锁)synchronized问题:小结 NSLockNSRecursiveLockNSConditionNSConditionLock 自旋锁OSSpinLock(已弃用)atomicatomic修饰的属性绝对安全吗?os_unfair_lock 读写锁互斥锁和自旋锁的对比 小结使…

uni-app学习笔记十五-vue3页面生命周期(一)

页面生命周期概览 vue3页面生命周期如下图所示&#xff1a; onLoad 此时页面还未显示&#xff0c;没有开始进入的转场动画&#xff0c;页面dom还不存在。 所以这里不能直接操作dom&#xff08;可以修改data&#xff0c;因为vue框架会等待dom准备后再更新界面&#xff09;&am…

《软件工程》第 14 章 - 持续集成

在软件工程的开发流程中&#xff0c;持续集成是保障代码质量与开发效率的关键环节。本章将围绕持续集成的各个方面展开详细讲解&#xff0c;结合 Java 代码示例与可视化图表&#xff0c;帮助读者深入理解并实践相关知识。 14.1 持续集成概述 14.1.1 持续集成的相关概念 持续集…