[STM32]从零开始的STM32 FreeRTOS移植教程

一、前言

        如果能看到这个教程的话,说明大家已经学习嵌入式有一段时间了。还记得嵌入式在大多数时候指的是什么吗?是的,我们所说的学习嵌入式大部分时候都是在学习嵌入式操作系统。从简单的一些任务状态机再到复杂一些的RTOS,再到最复杂的Linux,这些都属于嵌入式操作系统的一种,只是简单与复杂的区别。在之前,我们开发STM32时采用的都是裸机开发所以对实时系统并没有什么概念,接触RTOS会接触到一种新的编程方式。当然,因为RTOS已经引入了系统的概念了,所以代码看起来与调试起来也更加抽象。但,就现在而言,实时操作系统仍然是许多公司要求嵌入式工程师必会的技能之一。所以,如果你准备好了,就让我们一起来移植RTOS吧!

二、在开始之前

        因为已经涉及到嵌入式系统了,所以还请学习这篇教程的小伙伴有一定的STM32基础,我始终不推荐纯小白直接接触RTOS。在这篇教程中,我会教大家如何下载RTOS的代码固件包,如何将RTOS移植到对应的单片机中,以及如何解决一些常见的问题。当然,你也可以下载我下面给的资料,资料中会包含本次会用到的RTOS源码包和我已经移植好的工程:

RTOS移植资料:https://pan.baidu.com/s/1YbfUm1LUSomslaGWqJ-g4w?pwd=clxm 
提取码:clxm

三、芯片的选择        

        因为RTOS是一个嵌入式操作系统,RTOS强调的是代码的实时性,比起裸机开发,它并不能提高芯片的性能,相反,它是一个消耗芯片性能的软件。在运行了RTOS以后,我们芯片的资源就被占用了一部分,这也会让我们的可编程范围变小了。既然是这样,那为什么我们还需要嵌入式操作系统呢?当然是为了实时性呀,裸机在开发时,代码始终顺序执行,这也导致了我们有的步骤要等很久才会执行到,在某些特定的情况下就可能出现问题。如果使用实时操作系统,它会合理分配每一个任务的执行时间,保证我们每一个任务都执行一段时间,不会有任务长期阻塞程序。当然,我们这次的重点并不是RTOS的原理,如果想要了解RTOS详细原理与系统性的学习的话,还是建议大家去看一些视频教程。这里话又说回来,因为RTOS会消耗一部分的性能,所以有的芯片可能无法运行RTOS,这里我会使用STM32F407ZGT6进行RTOS的移植演示,我并不推荐大家使用STM32F103C6T6单片机,这款单片机在移植RTOS时可能会出现你无法解决的错误。在移植RTOS时尽量选择RAM与ROM都比较大的芯片。这样代码在编译时也不容易报错。

四、RTOS系统固件包的下载

        RTOS的虽说是一个操作系统,但是本质上还是代码构成的,在这里面我们仍然可以看到.c .h文件。所以,移植RTOS简单来说,就是将对应的C语言代码在STM32中运行起来。所以我们现在需要下载RTOS的固件包,这里我们直接在浏览器中搜索“FreeRTOS”:

我们可以看到,这里搜索出来的第一个网站就是FreeRTOS的官网了:

当然,如果你没有找到FreeRTOS的官网的话,也可以点击下方的链接前往:

FreeRTOS官网:FreeRTOS™ - FreeRTOS™

进入FreeRTOS的官网以后,就可以看到以下页面了:

如果你这里不是中文的,可以点击右上角这里切换语言:

接着,我们点击网页中的“下载”:

点击了下载以后,弹出的窗口中会让我们选择要下载的版本:

这里我推荐大家使用2022或者2020的版本,这些版本经过了几年的迭代已经非常稳定了。如果你是小白的话,建议下载和我一样的版本,以保证文件的统一。

我们选择好版本以后,直接点击“Download”:

随后浏览器就会弹出下载了:

我们将其下载到我们能找到的地方:

如果你这里无法打开RTOS的官网或者是无法下载RTOS的固件包,那么你就可以打开我给的资料中的RTOS固件包文件夹,这里有我已经下载好的固件包:

下面,我们再将下载的压缩包解压得到以下文件夹:

至此,我们RTOS系统的固件包就已经下载完成了。

五、RTOS的移植

        当我们准备好了RTOS系统的固件包以后,就可以开始移植了,这里我们移植RTOS系统是在原本的工程之上,所以,首先就要保证我们有一个对应芯片的对应工程模板。我这里使用的是STM32F407ZGT6芯片,所以准备的也是STM32F407ZGT6的工程,如图:

我们进入工程,这里需要我们的工程编译没有错误:

下面我们直接写一个LED的代码,证明我们的硬件没有问题,这个地方的点灯代码很简单,就不多说了,我的LED在PA12口上,并且为高电平点亮:

将程序编译下载到芯片后,就可以看到LED已经亮起了,证明我们的硬件方面没有问题:

下面,我们就要在这个原本的工程上移植RTOS。

首先需要在工程的主目录下新建一个RTOS的文件夹用来存放RTOS的相关文件:

我们进入这个RTOS的文件夹,然后新建三个文件夹,分别是“inc”,“src”,“port”:

这里的inc文件夹用来存放RTOS的头文件和配置文件,src用来存放RTOS的源文件,port用来存放RTOS的内存管理文件。

我们现在去RTOS固件包解压出来的文件夹中复制文件,我们进入解压后的文件夹就可以看到以下文件夹和文件:

这里我们再进入“FreeRTOSv202212.01”文件夹下的“FreeRTOS”文件夹,可以看到以下文件和文件夹:

然后我们再进入“FreeRTOS”文件夹下的“Source”文件夹,这里面的文件就是我们要用的了:

这里我们首先将“Source”文件夹下的所有.c的文件复制到刚才工程目录中创建的“RTOS\src”文件夹下:

这里需要注意的是,我们只需要复制.c,多余的文件如果被复制过去了删除就行了。

随后,我们再把“Source”文件夹下的“include”文件夹下的所有.h的文件复制到“RTOS\inc”文件夹下

这里同样的只要.h文件,不能复制别的文件。

随后我们进入“Source”文件夹下的“portable”文件夹,看到以下文件夹:

这里包含了RTOS的内存管理文件和不同编译器的相关文件。这里我们首先来复制内存管理文件,我们进入“portable”文件夹下的“MemMang”文件夹,将“heap_4.c”文件复制到工程目录下的“RTOS\port下”:

这里的内存管理文件我们一般都用4,如果你是小白的话请不要随意修改。

随后我们再打开“portable”文件夹下的“RVDS”文件夹,可以看到以下文件夹:

这里面对应了RVDS集成编译环境不同的ARM内核的编译规则文件。因为我这里使用的是STM32F407ZGT6单片机,所以这里首先肯定要选择M4内核,因为STM32F407ZG系列都不附带MPU所以我们这里直接选择“ARM_CM4F”文件夹,我们将“RVDS\ARM_CM4F”下的文件复制到工程目录下的“RTOS\port”下:

至此,我们RTOS的基本文件就已经复制完成了,这里我们还需要复制一下配置文件。配置文件被放在了“FreeRTOSv202212.01\FreeRTOS\Demo”目录下,进入这个目录,我们就能看到非常多的芯片型号,这些芯片官方都提供的相关的Demo,我们只需要在对应的芯片Demo中寻找配置文件即可:

因为这里我使用的是STM32F407ZGT6的芯片,所以我芯片所对应的配置文件就被存放在了“CORTEX_M4F_STM32F407ZG-SK”文件夹下。大家可以根据自己的芯片型号和对应的IDE寻找相关的Demo:

这里我们进入“CORTEX_M4F_STM32F407ZG-SK”文件夹,文件夹中的“FreeRTOSConfig.h”就是我们需要的配置文件了,我们将其复制到工程目录下的“RTOS\inc”下:

至此,我们RTOS运行所需的所有文件都已经复制完成了,我们直接打开工程:

接着,我们把刚才复制的文件添加的工程中,点击菜单栏中的箱子:

我们这里新建三个文件夹,分别是“RTOS\inc”,“RTOS\src”,“RTOS\port”:

接着将对应文件夹中的文件添加进来,这里一定要对应好,不要添加错了:

这里要注意的是,一定是把对应的所有文件添加进来以后再进行下一步。

我们再在魔术棒中将对应文件夹的路径添加进来,这里路径添加很基础,就不细讲了:

将文件添加进来以后,我们点击编译,这里的编译肯定会报错的,我们慢慢来解决:

这里的错误提示我们“configSYSTICK_CLOCK_HZ”这个变量没有定义。这里我们去到配置文件中,大概在40行左右,可以看到这样一条条件编译:

这里是为了判断是否是使用IAR编译器,我们这里使用的是keil,这条条件编译肯定不会过的。我们将这一条条件编译修改一下,改成下面这样:

#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)

这里修改了条件编译以后就可以兼容keil,IAR, GCC编译器了。

我们再次编译,出现三个重复定义的错误,因为这三个函数在STM32原本的库中已经被定义过了,但是在RTOS的库中又被定义了一次。既然我们要使用RTOS那当然也要用RTOS的处理函数,这里我们直接将原本的函数注释掉:

原本的函数被写在了“stm32f4xx_it.c”中,我们分别将其注释掉,通过报错我们可以得知,这里被重复定义的函数分别是“PendSV_Handler”,“SVC_Handler”,“SysTick_Handler”:

注释后如图:

这里将重复定义的函数注释掉以后,我们再次编译,我们可以看到这几个函数没有被定义:

这里又需要我们修改配置文件了,我们同样的打开配置文件我们将配置文件中的如下几项的值改为0:

#define configUSE_IDLE_HOOK				0
#define configUSE_TICK_HOOK				0
#define configCHECK_FOR_STACK_OVERFLOW	0
#define configUSE_MALLOC_FAILED_HOOK	0

修改完配置文件以后,我们再次编译:

可以看到,现在已经没有报错了,我们现在就算是移植完成了,我们可以写一点代码来试一下,首先回到“main.c”,这里我们先在main.c中引入RTOS相关的头文件:

#include "freertos.h"
#include "task.h"

然后我们创建一个任务函数:

void LED(void* age)
{
	while(1)
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_12);
		vTaskDelay(500);
		GPIO_SetBits(GPIOA,GPIO_Pin_12);
		vTaskDelay(500);
	}
}

这里就是我们的任务函数了,控制了LED的亮灭,注意,任务函数进入以后一定是在一个死循环中,任务函数不能返回,不然可能引发一些错误。在使用了RTOS以后,我们的所以延时都要使用RTOS中的相对延时。

在主函数中,我们写引脚的初始化和任务的创建:

int main(void)
{
	TaskHandle_t myTaskHandle_t;
	GPIO_InitTypeDef  GPIO_InitStructure;
	delay_init(168);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_SetBits(GPIOA,GPIO_Pin_12);
	
	xTaskCreate(LED,"LED",128,NULL,2,&myTaskHandle_t);
	vTaskStartScheduler();
    while(1)
	{
			
	}
}

这里主要解释一下“xTaskCreate”函数。xTaskCreate用于创建RTOS中的任务。这里的第一个参数为任务函数的名称,我们这里任务函数名为“LED”所以第一个参数就传入LED,第二个参数是任务的名字,要求传入字符串格式的,我们这里传入一个字符串即可。第三个参数是为任务分配的内存,我们这里的任务只是点灯而已,所以不用分配太大,直接128就已经很充足了。第四个参数是向任务中传入的参数,我们这里没有参数要传入,直接写NULL,第五个参数是任务的优先级,因为只有一个任务,也不存在谁优先的问题,随便写个优先级即可。最后要我们传入一个“TaskHandle_t ”类型的结构体指针,我们直接定义一个结构体,取它的地址传入即可。

随后,我们再使用vTaskStartScheduler函数启动任务调度器。当调度器启动以后,STM32就已经被系统接管了。

我们将代码编译下载到开发板中,可以看到LED正常闪烁:

至此,我们的RTOS已经算是移植成功了。当然RTOS的知识还很多,能够运用只是第一步。

六、结语

        本次我们讲解了如何下载RTOS的固件包,以及如何复制RTOS的相关文件,以及在遇到错误以后如何解决。内容比较多,还是希望大家多吸收一下。那么最后,感谢大家的观看!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《操作系统 - 清华大学》5 -4:虚拟技术

文章目录 0. 虚拟存储的定义1. 目标2.局部性原理3. 虚拟存储的思路与规则4. 虚拟存储的基本特征5. 虚拟页式存储管理5.1 页表表项5.2 示例 0. 虚拟存储的定义 1. 目标 虚拟内存管理技术,简称虚存技术。那为什么要虚存技术?在于前面覆盖和交换技术&#…

2024APMCM亚太杯数学建模C题【宠物行业】原创论文分享

大家好呀,从发布赛题一直到现在,总算完成了2024 年APMCM亚太地区大学生数学建模竞赛C题的成品论文。 给大家看一下目录吧: 目录 摘 要: 10 一、问题重述 14 二.问题分析 15 2.1问题一 15 2.2问题二 15 2.3问题三…

YOLOv8模型pytorch格式转为onnx格式

一、YOLOv8的Pytorch网络结构 model DetectionModel((model): Sequential((0): Conv((conv): Conv2d(3, 64, kernel_size(3, 3), stride(2, 2), padding(1, 1))(act): SiLU(inplaceTrue))(1): Conv((conv): Conv2d(64, 128, kernel_size(3, 3), stride(2, 2), padding(1, 1))(a…

零基础3分钟快速掌握 ——Linux【终端操作】及【常用指令】Ubuntu

1.为啥使用Linux做嵌入式开发 能广泛支持硬件 内核比较高效稳定 原码开放、软件丰富 能够完善网络通信与文件管理机制 优秀的开发工具 2.什么是Ubuntu 是一个以桌面应用为主的Linux的操作系统, 内核是Linux操作系统, 具有Ubuntu特色的可视…

VScode 连不上远程云服务器

今天下午写代码,打开 VScode 突然发现连不上云服务器了,一开始以为自己密码输错了,试了好多次,依然是这样的 经过查资料发现,应该是版本的自动升级导致的!解决方案如下: 1、删除 windows 端的 …

图像分割——区域增长

一 区域增长 图像灰度阈值分割技术都没有考虑到图像像素空间的连通性。区域增长法则正好相反,顾及像素的连接性. 方法:1)选择一个或一组种子; 2)选择特征及相似性判决准则; 3)从该种子开始向外生长&#x…

音视频相关的一些基本概念

音视频相关的一些基本概念 文章目录 音视频相关的一些基本概念RTTH264profile & levelI帧 vs IDRMP4 封装格式AAC封装格式TS封装格式Reference RTT TCP中的RTT指的是“往返时延”(Round-Trip Time),即从发送方发送数据开始,到…

春秋云境 CVE 复现

CVE-2022-4230 靶标介绍 WP Statistics WordPress 插件13.2.9之前的版本不会转义参数,这可能允许经过身份验证的用户执行 SQL 注入攻击。默认情况下,具有管理选项功能 (admin) 的用户可以使用受影响的功能,但是该插件有一个设置允许低权限用…

Linux—进程概念学习-03

目录 Linux—进程学习—31.进程优先级1.1Linux中的进程优先级1.2修改进程优先级—top 2.进程的其他概念3.进程切换4.环境变量4.0环境变量的理解4.1环境变量的基本概念4.2添加环境变量—export4.3Linux中环境变量的由来4.4常见环境变量4.5和环境变量相关的命令4.6通过系统调用获…

go语言逆向-基础basic

文章目录 go 编译命令 ldflags -w -s的作用和问题使用 file 命令查看文件类型 go 语言逆向参考go ID版本GOROOT和GOPATHGOROOTGOPATHGOROOT和GOPATH的关系示例 go build和 go modpclntab (Program Counter Line Table 程序计数器行数映射表)Moduledata程…

RAG架构类型

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

PostgreSQL详细安装教程

#安装PostgreSQL的yum仓库 sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm#安装PostgreSQL 15版本 sudo yum install -y postgresql15-server#初始化数据库(若要自定义数据库存储目录…

uniapp介入极光推送教程 超级详细

直接按照下面教程操作 一步一步来 很快就能 完成 下面的文章非常详细 ,我就不班门弄斧了 直接上原文链接 https://blog.csdn.net/weixin_52830464/article/details/143823231

公司金融期末考试题目

公司金融期末考试题 选择题 1.现金折扣和信用条件(教材P253) 题目类似: 下列不属于信用条件的是()。 现金折扣 数量折扣信用期限 折扣期限 给定的信用条件为"1/10,n/40",则其含义…

图论入门编程

卡码网刷题链接:98. 所有可达路径 一、题目简述 二、编程demo 方法①邻接矩阵 from collections import defaultdict #简历邻接矩阵 def build_graph(): n, m map(int,input().split()) graph [[0 for _ in range(n1)] for _ in range(n1)]for _ in range(m): …

visionpro实践项目(一)进阶

在visionpro实践项目(一)中,我们是使用标签工具,将测得的零件宽度信息显示在图片上,在这篇文章中,我们换一种方法,使用脚本工具来显示宽度信息。这就涉及到写代码了。 将Job中的标签工具删掉&am…

KPAC(ICCV 2021)代码单图片推理

文章目录 KPAC(ICCV 2021)代码单图片推理创建虚拟环境安装依赖包数据集路径设置运行测试单图片推理 KPAC(ICCV 2021)代码单图片推理 论文链接:Single Image Defocus Deblurring Using Kernel-Sharing Parallel Atrous Convolutions 该论文研究的问题是散焦去模糊&…

Flink cdc同步增量数据timestamp字段相差八小时(分析|解决)不是粘贴复制的!

问题 我使用flink cdc同步mysql到mysql遇到了timestamp字段缺少八小时的问题。很少无语,flink ,cdc,debezium时区都设置了,没有任何效果! 分析 问题出现在mysql binlog身上!!! 因为默认mysql会使用UTC来…

算法新篇章:AI如何在数学领域超越人类

人工智能咨询培训老师叶梓 转载标明出处 尽管大模型在很多领域表现出色,比如理解自然语言和生成文本,但它们在解决一些复杂的推理任务时,比如数学问题、编程挑战或者医疗诊断,还是显得有些力不从心。最近,一个来自中国…

MTK主板_安卓主板方案_MTK联发科主板定制开发

联发科(MTK)主板以其强大的性能和多样化的功能而受到广泛关注。该平台包括多个型号,例如MT6761、MT8766、MT6762、MT6765、MT8768和MT8788等,均配置了四核或八核64位处理器,主频可高达2.0GHz。采用先进的12nm工艺,搭载Android 11.…