基于STM32F4单片机的FreeRTOS移植思路及过程
一 、FreeRTOS 简介
官网:https://www.freertos.org/zh-cn-cmn-s
FreeRTOS 是一款开源的实时操作系统(RTOS),专为嵌入式系统设计。其核心特点包括轻量级、可移植性强、支持多任务调度,适用于资源受限的硬件环境。FreeRTOS 遵循 MIT 开源协议,允许商业应用无需支付授权费用。
核心功能:
多任务管理:支持基于优先级的抢占式调度,允许任务动态创建和删除。
内存管理: 提供多种内存分配方案(如 heap_1 至 heap_5),适应不同硬件资源需求。
同步与通信:包含队列、信号量、互斥锁等机制,支持任务间高效通信。
低功耗支持:提供 Tickless 模式,减少空闲任务时的 CPU 功耗。
二 、rtos移植
(1)、下载
1、官网,github下载
官网下载地址:https://www.freertos.org/zh-cn-cmn-s/Documentation/02-Kernel/01-About-the-FreeRTOS-kernel/03-Download-freeRTOS/01-DownloadFreeRTOS
进入之后下拉,可以找到不同的版本,若需要之前的版本,可以点击下图所示的位置,进行跳转
跳转之后进入到github页面,点击tags
进入到这个页面后可以看到不同的版本,如果没有我们需要的,可以点击最下面的 next按钮(本文需要的v10.2.1版本在后面第二页或者第三页的位置)
找到需要的版本后点击跳转到新页面,选择要下载的压缩方式,点击就会开始下载
下载完成后,进行解压(解压位置自行决定,使用完就可以删除了)
2、代码托管平台下载
代码托管网站:https://sourceforge.net/projects/freertos/files/FreeRTOS/
进入之后我们可以直接看到很多个版本
我们选择对应的版本点击后,点击对应的压缩包,稍等片刻就会下载。
(2)、文件移植
结束后我们就会得到如下的一个文件夹
进入到下图对应的文件目录下,包括三个部分:第一部分和第三部分包含的是FreeRTOS的通用的头文件和C文件,这两部分的文件是通用的(试用于各种编译器和处理器)。第二部分portable是与编译器相关的文件夹,在不同的编译器中需要使用不同的支持文件。
我们在自己的工程文件目录下新建一个FreeRTOS文件夹,在FreeRTOS文件夹下面新建如下图所示的几个文件夹。
将上述的include文件夹,和下面的文件复制到新建的文件夹下,其中include存放的是上述第一部分include文件,src存放的是上图第三部分所有的.c文件
我们点击上述的第二部分portable文件夹,进入之后可以看到我们熟悉的keil,但是这个文件夹是空的,让我们参考RVDS文件夹。
打开RVDS文件夹后可以看到不同内核的文件夹,我是以stm32f407为例子,所以选择的是m4内核(f407vet6带有浮点运算,所以选择红色框内的)。如果是其他系列的,点击对应的文件夹。(例如stm32f103,则选择M3内核的文件夹)
将其中的.c文件和.h文件复制到我们在工程中建的FreeRTOS文件夹下port文件夹中即可。
复制之后,回到portable文件夹下面,点击MemMang,可以看到有五种方式:
heap_1-- 最简单,不允许释放内存。
heap_2-- 允许释放内存,但不会合并相邻的空闲块。
heap_3-- 简单包装了标准 malloc() 和 free(),以保证线程安全。
heap_4-- 合并相邻的空闲块以避免碎片化。包含绝对地址放置选项,
heap_5-- 如同 heap_4,能够跨越多个不相邻内存区域的堆。
这里我们选择heap_4.c文件
复制后放入到我们工程中port文件夹下,此时port文件夹如下
接着我们回到下图对应的文件目录下,找到对应的stm32F407。(如果是其他系列单片机,在文件中找到对应的文件夹点进去即可,下面操作步骤一样)
点击之后,将下图红框的文件复制,粘贴到我们工程下建的FreeRTOS文件夹下
此时我们的文件已经齐全了
(3)、keil中配置
打开工程,在三色盒子中创建两个文件夹,FreeRTOS/src;FreeRTOS/port。其中src包含所有的.c文件
port包含如下图所示文件,完成
点击魔法棒,按下图所示包含.h文件
我们再编译一下,发现有以下错误
..\FreeRTOS\portable\RVDS\ARM_CM4F\port.c(788): error: #20: identifier "SystemCoreClock" is undefined
此时我们需要修改为如下图所示
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
改完后,有以下报错:这个报错是因为在port.c 和stm32f4xx_it.c文件中出现重复定义的函数SVC_Handler、SysTick_Handler、 PendSV_Handler。
..\OBJ\MALLOC.axf: Error: L6200E: Symbol SVC_Handler multiply defined (by port.o and stm32f4xx_it.o).
..\OBJ\MALLOC.axf: Error: L6200E: Symbol PendSV_Handler multiply defined (by port.o and stm32f4xx_it.o).
..\OBJ\MALLOC.axf: Error: L6200E: Symbol SysTick_Handler multiply defined (by port.o and stm32f4xx_it.o).
我们将stm32f4xx_it.c中这三个函数直接注释掉,再编译。(其他系列单片机,找到对应的中断.c文件即可,内容一样)
接下来出现如下错误。这是由于没有定义这些函数而导致的,这些未定义的函数,它们都是Hook 结尾的,这些函数有个共同的名称:钩子函数。将相应的宏定义改为0即可。
..\OBJ\MALLOC.axf: Error: L6218E: Undefined symbol vApplicationIdleHook (referred from tasks.o).
..\OBJ\MALLOC.axf: Error: L6218E: Undefined symbol vApplicationStackOverflowHook (referred from tasks.o).
..\OBJ\MALLOC.axf: Error: L6218E: Undefined symbol vApplicationTickHook (referred from tasks.o).
..\OBJ\MALLOC.axf: Error: L6218E: Undefined symbol vApplicationMallocFailedHook (referred from heap_4.o).
这里将下列宏定义为 0
confiUSE IDLE HOOK、
confgUSE TICK HOOK
configCHECK FOR STACK OVERFLOW
configUSE MALLOC FAILED HOOK
最后编译一下,应该就没有错误了(图片中我已经修改了部分参数,但不影响观看)
(4)、编写任务测试运行
移植过程,如果还有错误的话可以自行根据错误类型处理,也可以评论区进行讨论一下。博主看到会及时回复
后续有什么错误我会及时更新。
