STM32手动移植FreeRTOS

📦 准备工作

  1. 获取FreeRTOS源码:

    • 访问 FreeRTOS官网 或其 GitHub仓库 下载最新版内核源码。

    • 你也可以使用Git克隆(注意要包含子模块):git clone https://github.com/FreeRTOS/FreeRTOS.git --recurse-submodules

  2. 准备STM32基础工程:

    • 使用 STM32CubeMX 生成一个针对你芯片型号的裸机工程(例如一个简单的LED闪烁工程),配置好时钟树、调试接口(如SYS)和你需要的外设(如GPIO、USART等)。

    • 确保这个基础工程在你的开发板上能够编译并通过(例如,LED能闪烁)。

📁 文件组织与添加

在你的STM32工程目录下(通常与CoreDrivers等文件夹同级),创建一个用于存放FreeRTOS源码的文件夹,例如Middlewares/FreeRTOS。然后按照下表的指引将必要的文件复制到相应位置:

所需文件源路径 (基于FreeRTOS源码根目录)目标路径 (你的工程目录)作用描述
核心源文件(.c)FreeRTOS/Source/*.c (如 tasks.cqueue.clist.c等)Middlewares/FreeRTOS/SourceFreeRTOS内核的核心功能实现
核心头文件(.h)FreeRTOS/Source/include/*.hMiddlewares/FreeRTOS/Source/includeFreeRTOS内核的头文件,提供API和数据类型定义
移植层文件FreeRTOS/Source/portable/[Compiler]/[Architecture]/*Middlewares/FreeRTOS/Source/portable与编译器及CPU架构相关的移植代码(关键选择,见下文说明
内存管理实现FreeRTOS/Source/portable/MemMang/heap_x.c (选一个)Middlewares/FreeRTOS/Source/portable/MemMangFreeRTOS的动态内存管理方案(五选一,通常推荐heap_4.c
配置文件FreeRTOS/Demo/[Demo项目]/FreeRTOSConfig.h通常放在工程Inc目录或Middlewares/FreeRTOSFreeRTOS内核的配置文件(需根据你的芯片和需求修改

🔧 关键选择说明:

  • 移植层文件 ([Compiler]和[Architecture]):

    • [Compiler]: 根据你使用的开发环境选择。

      • Keil MDK: 选择 RVDS 目录。

      • IAR: 选择 IAR 目录。

      • GCC (如STM32CubeIDE, CLion): 选择 GCC 目录。

    • [Architecture]: 根据你STM32芯片的Cortex内核型号选择。

      • Cortex-M0ARM_CM0

      • Cortex-M3ARM_CM3

      • Cortex-M4 (无FPU): ARM_CM4F

      • Cortex-M7 (有FPU): ARM_CM7

      • *例如,STM32F103是Cortex-M3,STM32F407是Cortex-M4。*

  • 内存管理实现 (heap_x.c):
    FreeRTOS提供了5种内存管理方案,通常选择 heap_4.c支持内存分配与释放,并能有效减少碎片)。对于极其简单或从不释放内存的应用,也可考虑 heap_1.c

📝 操作步骤:

  1. 在你的工程目录下(例如Middlewares/FreeRTOS)创建相应的子文件夹:SourceSource/includeSource/portable

  2. 根据上表和你的芯片、编译器情况,将FreeRTOS源码包中对应的文件复制到刚刚创建的相应文件夹中。

  3. 从FreeRTOS源码包的Demo文件夹里,找一个与你芯片型号相近的Demo工程,将其中的FreeRTOSConfig.h文件复制到你的工程目录下(通常放在Inc目录下便于包含)。

⚙️ 工程配置与修改

1. 添加文件到IDE工程

  • 打开你的Keil MDK(或其他IDE)工程。

  • 在IDE中创建新的分组(Group),例如 "FreeRTOS_CORE", "FreeRTOS_PORTABLE"。

  • 将刚才复制到Middlewares/FreeRTOS/Source下的.c文件(如tasks.cqueue.c等)添加到 "FreeRTOS_CORE" 分组。

  • 将你选择的内存管理文件(如heap_4.c)和移植层文件(如port.c)添加到 "FreeRTOS_PORTABLE" 分组。

  • 不要添加其他未选择的内存管理文件和移植层文件。

2. 添加头文件路径

在IDE的工程设置("Options for Target" -> "C/C++" -> "Include Paths")中,添加以下头文件路径35:

  • ../Middlewares/FreeRTOS/Source/include

  • ../Middlewares/FreeRTOS/Source/portable/[Compiler]/[Architecture] (例如 ../Middlewares/FreeRTOS/Source/portable/RVDS/ARM_CM3)

  • 确保也包含了存放FreeRTOSConfig.h文件的路径(如../Inc)。

3. 修改FreeRTOSConfig.h

FreeRTOSConfig.h是FreeRTOS的核心配置文件,你需要根据你的芯片和项目需求进行修改。以下是一些最关键的配置项34:

配置宏说明与典型设置
configCPU_CLOCK_HZ设置为你STM32芯片的主时钟频率(Hz),例如STM32F103为72000000,STM32F407为168000000。可直接使用 SystemCoreClock
configTICK_RATE_HZ系统节拍频率。通常设置为1000Hz,表示1ms一个时钟节拍。
configTOTAL_HEAP_SIZEFreeRTOS动态内存堆的总大小。根据你计划创建的任务、队列等数量估算。如果不够,任务创建会失败。例如可先设置为(10 * 1024)(10KB),后续再调整。
configMAX_PRIORITIES系统支持的最大任务优先级数。设置一个够用的值即可,如5-8,不是越大越好。
configKERNEL_INTERRUPT_PRIORITY``configMAX_SYSCALL_INTERRUPT_PRIORITY中断优先级配置非常重要!需要根据你芯片的NVIC优先级位数(如STM32F1/F4是4位,即0-15)和你的应用来设置。设置错误可能导致系统不稳定或无法运行。务必仔细查阅FreeRTOS手册和芯片数据手册
configUSE_PREEMPTION设置为1启用抢占式调度器,这是最常用的模式。
configUSE_TIMERS``configTIMER_TASK_PRIORITY``configTIMER_QUEUE_LENGTH``configTIMER_TASK_STACK_DEPTH如果你要使用软件定时器,需要将这些配置使能并设置相关参数。

其他常用配置:你还可以根据需求使能或禁用互斥量(configUSE_MUTEXES)、递归互斥量(configUSE_RECURSIVE_MUTEXES)、事件组(configUSE_EVENT_GROUPS)、栈溢出检查(configCHECK_FOR_STACK_OVERFLOW)等功能。

4. 处理中断服务程序(ISR)

FreeRTOS需要接管SVCPendSVSysTick这三个中断246。

  • 打开你的工程中stm32fxxx_it.c文件(例如stm32f1xx_it.cstm32f4xx_it.c)。

  • 找到并注释掉或删除以下三个函数的具体实现:

    • SVC_Handler(void)

    • PendSV_Handler(void)

    • SysTick_Handler(void)

  • 原因:这些中断的服务程序已经在你之前添加的移植层文件(如port.c)中实现了。如果不注释掉,会导致函数重复定义。

注意SysTick的特殊情况:如果你的HAL库仍然使用SysTick作为时基源(HAL_InitTick()),你可能需要修改SysTick_Handler而不是简单地删除它。一种常见的做法是28:

c

#include "FreeRTOS.h"
#include "task.h"void SysTick_Handler(void)
{HAL_IncTick(); // 维持HAL库的时基if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {xPortSysTickHandler(); // 调用FreeRTOS的SysTick Handler}
}

确保在FreeRTOSConfig.h中启用了INCLUDE_xTaskGetSchedulerState宏。

5. 修改HAL库的时基源(强烈推荐)

STM32的HAL库默认使用SysTick作为其时基源(用于HAL_Delay()HAL_GetTick()等)。而FreeRTOS也使用SysTick作为其任务调度的时钟节拍。虽然通过一些技巧可以让两者共享SysTick,但更推荐的做法是将HAL库的时基源切换到另一个硬件定时器(如TIM1, TIM6等),以避免潜在冲突9。

  • 你可以在STM32CubeMX中重新配置:在SYS选项下,将Timebase SourceSysTick改为其他的硬件定时器(如TIM1)。

  • 或者直接修改代码:在main.cHAL_Init()调用之后,重新初始化一个定时器作为HAL库的时基源。

🧪 编写测试代码

完成以上步骤后,就可以编写简单的FreeRTOS任务来测试移植是否成功了。

  1. 包含头文件:在main.c中包含FreeRTOS头文件。

    #include "FreeRTOS.h"
    #include "task.h"
    #include "queue.h" // 如果需要使用队列等功能
  2. 创建任务函数:定义至少一个简单的任务函数。

    void vTaskLED(void *pvParameters) {for (;;) {HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); // 假设LED连接在PC13vTaskDelay(500); // 延迟500个时钟节拍,即500ms (假设configTICK_RATE_HZ=1000)}
    }
  3. 创建任务并启动调度器:在main()函数的初始化代码之后(while (1)之前)创建任务并启动FreeRTOS调度器。

    int main(void) {HAL_Init();SystemClock_Config();// ... 其他外设初始化代码// 创建任务xTaskCreate(vTaskLED, "LED_Task", 128, NULL, 2, NULL);// 启动FreeRTOS调度器,永远不会返回vTaskStartScheduler();for (;;) {} // 调度器启动后,不会执行到这里
    }

🔬 编译、下载与调试

  1. 编译工程:解决所有编译错误。常见的错误包括头文件路径不正确、函数未定义(可能是移植层文件没添加或路径错误)、重复定义(中断服务函数没注释掉)等。

  2. 下载到开发板并运行。

  3. 观察现象:如果一切正常,LED应该会以你设置的周期闪烁。

  4. 使用调试器:如果程序运行不正常,使用调试器进行单步调试,检查系统是否能成功创建任务、是否成功启动调度器、是否进入正确的硬件中断等。

⚠️ 常见问题排查

  • 编译错误 undefined reference to ...: 检查FreeRTOS的.c文件是否都已添加到工程组中,头文件路径是否设置正确。

  • 编译错误 redefinition of ...: 检查stm32fxxx_it.c中的SVC、PendSV、SysTick中断处理函数是否已注释掉。

  • 程序在启动调度器后卡死或进入HardFault:

    • 检查FreeRTOSConfig.h中的configCPU_CLOCK_HZ是否设置正确。

    • 检查FreeRTOSConfig.h中的中断优先级配置(configKERNEL_INTERRUPT_PRIORITYconfigMAX_SYSCALL_INTERRUPT_PRIORITY)是否正确。这是非常常见的错误来源

    • 检查堆大小configTOTAL_HEAP_SIZE是否足够创建初始任务。

    • 使用调试器检查是否成功进入SVC_Handler(用于启动第一个任务)。

  • SysTick中断冲突: 确保HAL库的时基源已切换至非SysTick的定时器,或者按照前述方法修改了SysTick_Handler函数。

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

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

相关文章

C5仅支持20MHZ带宽,如果路由器5Gwifi处于40MHZ带宽信道时,会出现配网失败

是的,这会导致“怎么都连不上”。结论先说:如果路由器把 5 GHz 固定在 40 MHz(或以上)带宽,而你的 C5 只支持 5 GHz 的 20 MHz 带宽,那么 STA 连接一定会失败。固件里不可能“把 40 MHz AP 连成 20 MHz”&a…

坚鹏请教DEEPSEEK:请问中国领先的AI智能体服务商有哪些?知行学

坚鹏请教DEEPSEEK:请问中国领先的AI智能体服务商有哪些?深圳知行学教育科技公司名列榜首根据2025年8月底多家权威机构发布的榜单和报告,比如德本咨询(DBC)的“2025企业级AI Agent应用TOP50”榜单、IDC的《中国AI AGENT…

【开题答辩全过程】以 投票系统为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人,语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

C++异常处理指南:构建健壮程序的错误处理机制

在程序开发的世界里,“错误” 是绕不开的话题。你可能写过一个简单的计算器,却因为用户输入 “50” 而崩溃;也可能在操作数据库时,因为权限不足导致数据读取失败;甚至在申请内存时,因为系统资源耗尽而无法继…

comfUI背后的技术——VAE

第一次知道VAE可能还是许嵩。当然,这里的VAE指的是变分自编码器(Variational Autoencoder, VAE) Seq2Seq 在 Seq2Seq 框架提出之前,深度神经网络在图像分类等问题上取得了非常好的效果。在其擅长解决的问题中,输入和…

【序列晋升】21 Spring Cloud Gateway 云原生网关演进之路

Spring Cloud Gateway作为Spring生态系统中的核心组件,已成为微服务架构中的首选API网关解决方案。它基于响应式编程模型,提供高性能、可扩展的路由管理和跨领域功能,解决了传统微服务架构中的接口聚合、安全管控和流量控制等核心问题。与此同…

“HEU-AUTO”无线上网使用指南

本文针对笔记本电脑 笔者电脑型号为:2025联想拯救者Y9000p 5060步骤1:点击开始菜单,点击设置,如图步骤2:在Windows设置菜单中,点击“网络和Internet”选项,如下图:步骤3:…

微信小程序中蓝牙打印机中文编码处理:使用iconv-lite库

在微信小程序开发中,集成蓝牙打印机实现中文打印是常见需求,但中文文本常因编码不匹配(如UTF-8与GBK冲突)导致乱码问题。本文详细解释如何利用iconv-lite库高效处理中文编码转换,确保打印内容正确显示。文章结构清晰,逐步引导您解决问题,代码示例基于实际项目验证。 1. …

GraphRAG——v0.3.6版本使用详细教程、GraphRAG数据写入Neo4j图数据库、GraphRAG与Dify集成

GraphRAG——v0.3.6版本使用详细教程、GraphRAG数据写入Neo4j图数据库、GraphRAG与Dify集成理论部分安装知识图谱生成测试将数据导入到Neo4j图数据库可视化将GraphRAG与Dify集成理论部分 https://guoqingru.blog.csdn.net/article/details/150771388?spm1011.2415.3001.5331安…

MongoDB 聚合管道(Aggregation)高级用法:数据统计与分析

MongoDB 聚合管道(Aggregation)高级用法:数据统计与分析第一章:聚合管道核心概念与架构设计1.1 聚合管道的本质与价值1.2 管道阶段深度解析1.3 执行引擎与优化机制第二章:高级分组与多维统计分析2.1 复合分组与层次化分…

Twitter舆情裂变链:指纹云手机跨账号协同机制提升互动率200%

——基于动态设备指纹与智能行为仿真的裂变增长体系​​一、Twitter舆情运营的三大核心挑战​账号关联风险​同一设备/IP操作多账号触发平台风控,封号率高达65%,舆情响应链路断裂固定设备参数(如GPU型号/屏幕分辨率)导致账号权重暴…

【密集目标检测】停车场车辆(车位)识别数据集:12k+图像,yolo标注

停车场车辆(车位)识别数据集概述 数据集包含12415张从监控摄像头画面中截取的停车场图像,涵盖晴天、阴天和雨天场景,标注类别包含车位占用、空车位2类。 标注格式:yolo txt 标注工具:labelme/labelimg 分辨率:416*416 一、学术研究的奠基与迭代 停车场车辆(车位)…

苍穹外卖项目笔记day02

接下来的笔记都会以难点与一些不常见的方法为主,一些重复的crud并不会出现哦 ThreadLocal类 ThreadLocal 并不是一个Thread,而是Thread的局部变量,它用于创建线程局部变量。 核心思想:每个线程都有自己独立的变量副本。这意味着,即…

设计模式12-适配器模式

定义 Adapter Partern: 将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 场景 系统需要使用现有的类,而这些类的接口不符合系统的需要。 典型场景:集成第三方库、遗留系统代…

VGG改进(6):基于PyTorch的VGG16-SE网络实战

1. 引言:注意力机制在计算机视觉中的重要性近年来,深度学习在计算机视觉领域取得了巨大成功,从图像分类到目标检测,各种复杂任务都获得了前所未有的性能提升。然而,传统的卷积神经网络(CNN)在处…

[电商网站-动态渲染商品-尺寸、尺码、颜色图片等];库存缺货状态动态对应。

目录 描述: 数据结构 组件代码文件 描述: 自动处理SKU数据生成规格属性列表 支持用户选择不同规格组合 智能禁用无库存选项 自动匹配当前选择对应的SKU信息 通过视觉样式区分可选/不可选状态 该组件采用Vue实现,通过计算属性和响应式数据…

论《运动战》

运动战的本质是以机动换主动,以时间换空间,通过高度的流动性、主动的位移和灵活的战术选择,在动态中创造并捕捉战机,最终以较小的代价换取最大的胜利。它是一种非对称的、主动的作战哲学,其核心不在于一城一地的得失&a…

DVWA靶场通关笔记-CSRF(Impossible级别)

目录 一、查看源码 二、功能分析 三、CSRF防范分析 1、CSRF令牌验证机制 (1)核心原理 (2)防范机制 2、旧密码确认防御实现 (1)核心原理 (2)为什么旧密码确认能有效防范CSRF…

深层语义在自然语言处理中的理论框架与技术融合研究

摘要本文章系统阐述了深层语义在自然语言处理(NLP)领域的定义、特征及其与知识图谱和大型预训练语言模型的融合方法。基于截至2025年8月的最新研究成果,报告深入分析了深层语义的多维度特性、技术实现路径以及面临的挑战,为研究人…

深入解析HarmonyOS:UIAbility与Page的生命周期协同

深入解析HarmonyOS:UIAbility与Page的生命周期协同 在HarmonyOS应用开发中,理解UIAbility和Page的生命周期是构建高质量应用的关键。本文将深入探讨这两大核心概念的生命周期及其协同工作机制,帮助开发者更好地管理应用资源、优化用户体验。…