【STM32】FreeRTOS的移植(一)(详细流程)
第一部分:FreeRTOS移植
这篇文章详细的讲述了如何将 FreeRTOS 移植到 STM32F1xx(以 STM32F103 为例) 的过程。你可以在你的工程创建中,按照步骤整理出完整的移植流程(并且我提供了测试任务,编写了创建说明),方便你学习和 创建FreeRTOS的实例 参考。
1、FreeRTOS 移植步骤
1.1 准备基础工程:
选择一个稳定可用的 STM32 工程作为基础。
这里我推荐使用“跑马灯实验”作为模板,因为其结构简单、易于调试。
1.2 获取 FreeRTOS 源码:
(1)、FreeRTOS官网下载。
(2)、固件库工程模板。
1.3 示例工程路径选择:
FreeRTOS 提供了丰富的示例,推荐从
Demo
文件夹中查找对应 MCU 的例程
STM32F103 示例路径如图 1.3.2.2 所示:
FreeRTOS\FreeRTOSvX.X.X\FreeRTOS\Demo\CORTEX_STM32F103_Keil
1.4 工程结构搭建
从零开始创建一个FreeRTOS例程
1 、准备基础工程
要移植 FreeRTOS,肯定需要一个基础工程,基础工程越简单越好,这里我们用的基础例程中的跑马灯实验来作为基础工程。
2、FreeRTOS 系统源码
FreeRTOS 系统源码已经详细的讲解过如何获取了,这里我们会将 FreeRTOS 的系统源码放到资料中去,路径为:资料->FreeRTOS 资料->FreeRTOS 源码
添加 FreeRTOS 源码
📁 1. 创建 FreeRTOS 文件夹(如下图):
在你的基础工程中添加 FreeRTOS
文件夹,用于放置 RTOS 所有源文件。
📁 2. 添加源码文件:
然后,创建 FreeRTOS 文件夹以后就可以将 FreeRTOS 的源码添加到这个文件夹中:
将以下内容复制到 FreeRTOS
文件夹:
include/
portable/
croutine.c
event_groups.c
list.c
queue.c
tasks.c
timers.c
📁 3. 精简 portable 目录:
只保留与 STM32 + Keil 相关的三个文件夹:
Keil/
MemMang/
RVDS/
进入 portable
文件夹,我们只需要留下 keil
、MemMang
和 RVDS
这三个文件夹,其他的都可以删除掉:
🗂️ 4. 在 Keil 中新建分组:
打开基础工程,新建分组 FreeRTOS_CORE 和 FreeRTOS_PORTABLE,然后向这两个分组中添加文件:
FreeRTOS_CORE
:添加核心 C 文件
FreeRTOS_PORTABLE
:添加port.c
和heap_4.c
1.5 添加头文件路径
添加完 FreeRTOS 源码中的 C 文件以后还要添加 FreeRTOS 源码的头文件路径:
在 Keil 中添加以下路径到 Include Paths
:
.\FreeRTOS\include
.\FreeRTOS\portable\RVDS\ARM_CM3
1.6 配置中断函数
FreeRTOS 会使用以下三个中断函数:
void SVC_Handler(void)
void PendSV_Handler(void)
void SysTick_Handler(void)
⚠️ 注意:不要在
startup
文件或stm32f10x_it.c
中重复定义,否则会报错:
Error: L6200E: Symbol PendSV_Handler multiply defined
解决方法:注释掉默认的这三个 Handler 定义,只保留 FreeRTOS 中定义的。
配置好后,文件结构为:
使用FreeRTOS的 SysTick 调度器
第二部分:FreeRTOS 移植测试代码编写
1、FreeRTOS系统配置(宏配置(FreeRTOSConfig.h
))
如果要使用静态方法的话需要将宏:打开 FreeRTOSConfig.h
,启用静态任务创建功能:
#define configSUPPORT_STATIC_ALLOCATION 1
2、任务创建和删除实验(静态方法)
1、实验目的
学习 xTaskCreateStatic ()和 vTaskDelete()这两个函数的使用 ,即静态方法创建任务。2、设计实验
本实验设计三个任务: start_task、 task1_task 和 task2_task ,这三个任务的任务功能如下:
start_task:用来创建其他两个任务。
task1_task :当此任务运行 5 此以后就会调用函数 vTaskDelete()删除任务 task2_task,此任务也会控制 LED0 的闪烁,并且周期性的刷新 LCD 指定区域的背景颜色。
task2_task : 此任务普通的应用任务,此任务也会控制 LED1 的闪烁。
测试任务设计要求(实现 3 个任务 + 1 个浮点测试任务):
任务名 | 优先级 | 堆栈大小(x4) | 说明 |
---|---|---|---|
start_task | 3 | 128 | 创建其他任务 |
led0_task | 4 | 128 | 控制 LED0 闪烁 |
led1_task | 5 | 128 | 控制 LED1 闪烁 |
float_task | 6 | 128 | 测试 FPU 与调度 |
3、创建任务结构(静态)
StaticTask_t xTaskBuffer;
StackType_t xStack[128];xTaskCreateStatic(TaskFunction, "TaskName", 128, NULL, 3, xStack, &xTaskBuffer);
4、删除任务函数使用
vTaskDelete(NULL); // 删除当前任务
vTaskDelete(xHandle); // 删除指定任务
问题排查:
问题 原因 解决方案
编译报重复定义 Handler startup 文件中重复定义中断函数 注释掉 startup 中定义
堆栈溢出 任务堆栈太小 增加任务堆栈大小
LED 不闪 任务没执行 检查任务是否创建成功,调度器是否启动
测试:
1、FreeRTOS测试软件设计2.1、测试软件设计要求:(1)、创建一个start_task任务,Start任务用来创建其他任务。(2)、创建一个led0_task任务,用来控制LED0的亮灭。(3)、创建一个led1_task任务,用来控制LED1的亮灭。
因为内容篇幅有限,下一篇文章承接此文,继续完成 FreeRTOS 的代码部分(提供完整项目实例代码),编写完整的 FreeRTOS 测试软件设计 的核心部分 —— 任务创建与实现。 构建一个包含 3 个任务的基础多任务系统。
以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!