STM32 FreeRTOS移植

news2025/1/15 0:53:42

目录

FreeRTOS源码结构介绍

获取源码

1、 官网下载

2、 Github下载

源码结构介绍

源码整体结构

FreeRTOS文件夹结构

Source文件夹结构如下

portable文件夹结构

RVDS文件夹

MemMang文件夹 

FreeRTOS在基于寄存器项目中移植步骤

目录添加源码文件

工程添加源码文件

系统配置文件修改

main.c中添加如下代码

FreeRTOS在基于HAL库项目中移植步骤

目录添加源码文件

工程添加源码文件

系统配置文件修改

修改stm32f1xx_it.c

引入头文件

系统配置文件说明

FreeRTOS数据类型

TickType_t

BaseType_t

UBaseType_t

StackType_t

FreeRTOS的命名规范

变量

函数


FreeRTOS源码结构介绍

获取源码

1、 官网下载

官网地址:FreeRTOS™ - FreeRTOS™

2、 Github下载

Github地址:https://github.com/FreeRTOS/FreeRTOS/releases

源码结构介绍

源码整体结构

名称

描述

FreeRTOS

FreeRTOS内核

FreeRTOS-Plus

FreeRTOS组件,一般我们会选择使用第三方的组件

tools

工具

GitHub-FreeRTOS-Home

FreeRTOS的GitHub仓库链接

Quick_Start_Guide

快速入门指南官方文档链接

Upgrading-to-FreeRTOS-xxx

升级到指定FreeRTOS版本官方文档链接

History.txt

FreeRTOS历史更新记录

其他

其他

FreeRTOS文件夹结构

名称

描述

Demo

FreeRTOS演示例程,支持多种芯片架构、多种型号芯片

License

FreeRTOS相关许可

Source

FreeRTOS源码,最重要的文件夹

Test

公用以及移植层测试代码

Source文件夹结构如下

名称

描述

include

内包含了FreeRTOS的头文件

portable

包含FreeRTOS移植文件:与编译器相关、keil编译环境

croutine.c

协程相关文件:进程下细分线程,线程下细分协程

event_groups.c

事件相关文件

list.c

列表相关文件

queue.c

队列相关文件

stream_buffer.c

流式缓冲区相关文件

tasks.c

任务相关文件

timers.c

软件定时器相关文件

include文件夹和.c文件是通用的头文件和 C 文件,这两部分的文件适用于各种编译器和处理器,是通用的。标红的是移植必需的,其他.c文件根据需要选取。

portable文件夹里根据编译器、内核等实际环境对应选取。

portable文件夹结构

FreeRTOS操作系统归根到底是一个软件层面的东西,需要跟硬件联系在一起,portable文件夹里面的东西就是连接桥梁。由于我们使用MDK开发,因此这里只重点介绍其中的部分移植文件。

名称

描述

Keil

指向RVDS文件夹

RVDS

不同内核芯片的移植文件

MemMang

内存管理相关文件

Keil文件夹里只有一个See-also-the-RVDS-directory.txt,意思是让我们看RVDS文件夹。

RVDS文件夹

RVDS 文件夹包含了各种处理器相关的文件夹,FreeRTOS 是一个软件,单片机是一个硬件,FreeRTOS 要想运行在一个单片机上面,它们就必须关联在一起。

关联还是得通过写代码来关联,这部分关联的文件叫接口文件,通常由汇编和 C 联合编写。这些接口文件都是跟硬件密切相关的,不同的硬件接口文件是不一样的,但都大同小异。编写这些接口文件的过程我们就叫移植,移植的过程通常由 FreeRTOS 和 mcu 原厂的人来负责,移植好的这些接口文件就放在 RVDS 这个文件夹的目录下。

FreeRTOS 为我们提供了 cortex-m0、m3、m4 和 m7 等内核的单片机的接口文件,根据mcu的内核选择对应的接口文件即可。其实准确来说,不能够叫移植,应该叫使用官方的移植, 因为这些跟硬件相关的接口文件,RTOS 官方都已经写好了,我们只是使用而已。

以 ARM_CM3 这个文件夹为例,里面只有“port.c”与“portmacro.h” 两个文件,

  • port.c文件:里面的内容是由 FreeRTOS 官方的技术人员为 Cortex-M3 内核的处理器写的接口文件,里面核心的上下文切换代码是由汇编语言编写而成,对技术员的要求比较高,我们只是使用的话只需拷贝过来用即可。
  • portmacro.h文件:port.c文件对应的头文件,主要是一些数据类型和宏定义。
MemMang文件夹 

MemMang 文件夹下存放的是跟内存管理相关的,总共有五个 heap 文件以及一个 readme 说明文件。

 这五个 heap 文件在移植的时候必须使用一个,因为 FreeRTOS 在创建内核对象的时候使用的是动态分配内存,而这些动态内存分配的函数则在这几个文件里面实现,不同的分配算法会导致不同的效率与结果,后面在内存管理中我们会讲解每个文件的区别,由于现在是初学,所以我们选用 heap4.c 即可。

FreeRTOS在基于寄存器项目中移植步骤

目录添加源码文件

在例程的根路径下,新建“FreeRTOS”文件夹,并且在里面新建“portable”和“source”两个空文件夹。

拷贝FreeRTOS源码的Source文件夹的7个.c文件到例程的source文件夹。

拷贝FreeRTOS源码portable文件夹下的Keil、RVDS、MemMang到例程的portable文件夹下。

其中例程的MemMang可只保留heap_4.c:

其中例程的RVDS可只保留ARM_CM3(对应我们的芯片内核)。

拷贝FreeRTOS源码include文件夹到例程的FreeRTOS文件夹下。

FreeRTOSConfig.h 文件是 FreeRTOS 的工程配置文件,因为 FreeRTOS 是可以裁剪的 实时操作内核,应用于不同的处理器平台,用户可以通过修改这个 FreeRTOS 内核的配置头文件来裁剪 FreeRTOS 的功能,所以我们把它拷贝一份放在 user 这个文件夹下面。

工程添加源码文件

工程新建Group“FreeRTOS/Source”和“FreeRTOS/Portable”。

系统配置文件修改

FreeRTOSConfig.h中添加如下3个配置:

#define xPortPendSVHandler  PendSV_Handler
#define vPortSVCHandler     SVC_Handler
#define INCLUDE_xTaskGetSchedulerState   1

第一行:中断服务程序的名称---可挂起的系统服务---可以等当前的中断服务程序结束然后执行

第二行:中断服务程序的名称---通过SWI指令的系统服务调用---可以使用硬件资源

第三行:开关选项(include...)获取调度器的状态

main.c中添加如下代码

FreeRTOS使用滴答定时器来实现的系统时基, 需要实现滴答定时器的中断,并在中断中添加下面的代码.

extern void xPortSysTickHandler(void);
void  SysTick_Handler(void)
{
    if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
    {
        xPortSysTickHandler();
    }
}

FreeRTOS在基于HAL库项目中移植步骤

目录添加源码文件

在例程的根路径下,新建“FreeRTOS”文件夹,并且在里面新建“portable”和“source”两个空文件夹。

拷贝FreeRTOS源码的Source文件夹的7个.c文件到例程的source文件夹。

拷贝FreeRTOS源码portable文件夹下的Keil、RVDS、MemMang到例程的portable文件夹下。

其中例程的MemMang可只保留heap_4.c:

其中例程的RVDS可只保留ARM_CM3(对应我们的芯片内核)。

拷贝FreeRTOS源码include文件夹到例程的FreeRTOS文件夹下。

FreeRTOSConfig.h 文件是 FreeRTOS 的工程配置文件,因为 FreeRTOS 是可以裁剪的 实时操作内核,应用于不同的处理器平台,用户可以通过修改这个 FreeRTOS 内核的配置 头文件来裁剪 FreeRTOS 的功能,所以我们把它拷贝一份放在 user 这个文件夹下面。

在源码“..\FreeRTOS\Demo”文件夹下面找到 “ CORTEX_STM32F103_Keil ” 这个文件夹下,找到 “FreeRTOSConfig.h”文件,然后拷贝到我们工程下的 “Core/Inc” 文件夹下即可,等下我们需要对这个文件进行修改。

工程添加源码文件

工程新建Group“FreeRTOS/Source”和“FreeRTOS/Portable”。

FreeRTOS/Source添加.c文件。

FreeRTOS/Portable添加port.c和heap_4.c文件。

添加配置头文件。

添加头文件。

FreeRTOS 的源码已经添加到开发环境的组文件夹下面,编译的时候需要为这些源文件指定头文件的路径,不然编译会报错。FreeRTOS 的源码里面只有 include 和RVDS\ARM_CM3这两个文件夹下面有头文件,只需要将这两个头文件的路径在开发环境里面指定即可。

同时我们还将 FreeRTOSConfig.h 这个头文件拷贝到了工程根目录下的 Core/Inc 文件夹下,这个路径本身就在开发环境里面。(放其他路径也可以, 就是一个.h文件)

系统配置文件修改

FreeRTOSConfig.h中添加如下3个配置:

#define xPortPendSVHandler  PendSV_Handler
#define vPortSVCHandler     SVC_Handler
#define INCLUDE_xTaskGetSchedulerState   1

修改stm32f1xx_it.c(hal库自动生成的文件)

引入头文件
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "FreeRTOS.h"
#include "task.h"
/* USER CODE END Includes */

注释掉2个函数

// void SVC_Handler(void)
// {
// }


// void PendSV_Handler(void)
// {
// }

添加SysTick时钟中断服务函数

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
extern void xPortSysTickHandler(void);
/* USER CODE END PV */


void SysTick_Handler(void)
{
    /* USER CODE BEGIN SysTick_IRQn 0 */

    /* USER CODE END SysTick_IRQn 0 */
    HAL_IncTick();
    /* USER CODE BEGIN SysTick_IRQn 1 */
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) 
    {
        xPortSysTickHandler();
    }
    /* USER CODE END SysTick_IRQn 1 */
}

注意:HAL本身和FreeRTOS都需要依赖SysTick,可能出现。

SysTick以最低的中断优先级运行,而FreeRTOS的临界区功能需要屏蔽中断,可能导致不可预知的问题。为了保险起见,可以考虑在SYS选择时钟源的时候换成其他的。

系统配置文件说明

FreeRTOSConfig.h 配置文件作用:对FreeRTOS的功能进行配置和裁剪,以及API函数的使能等。

官网中文说明:https://www.freertos.org/zh-cn-cmn-s/a00110.html

整体的配置项可以分为三类:

  • INCLUDE开头:一般是“INCLUDE_函数名”,函数的使能,1表示可用,0表示禁用。
  • config开头:FreeRTOS的一些功能配置,比如基本配置、内存配置、钩子配置、中断配置等。
  • 其他配置:PendSV宏定义、SVC宏定义。

FreeRTOS数据类型

针对每个移植定义四种类型。即:

TickType_t

如果 configUSE_16_BIT_TICKS 设置为非零 (true) ,则将 TickType_t 定义为无符号的 16 位类型。如果 configUSE_16_BIT_TICKS 设置为零(假),则将 TickType_t 定义为无符号的 32 位类型。

这个类型的变量, 通常用来表示系统节拍计数器的值。FreeRTOS系统中,每隔一段时间会进行一次滴答定时器中断处理,这个时间间隔就是系统的节拍周期。TickType_t类型的变量记录了系统过去的节拍次数。

BaseType_t

架构中最有效、最自然的类型。例如,在 32 位架构上,BaseType_t 会被定义为 32 位类型。在 16 位架构上,BaseType_t 会被定义为 16 位类型。是有符号的。

UBaseType_t

是无符号的BaseType_t

StackType_t

意指架构用于存储堆栈项目的 类型。通常是 16 位架构上的 16 位类型和 32 位架构上的 32 位类型,但也有例外情况。供 FreeRTOS 内部使用

FreeRTOS的命名规范

了解FreeRTOS的编码规范,有助于我们理解和学习FreeRTOS的使用.

变量

  1. 变量名称使用驼峰式大小写,具有明确的描述性,并使用完整的单词(没有缩写,但普遍接受的缩写除外)。
  2. uint32_t 类型变量以 ul 为前缀,其中“u”表示“unsigned” ,“l”表示“long”。
  3. uint16_t 类型变量以 us 为前缀,其中“u”表示“unsigned” , “s”表示“short”。
  4. uint8_t 类型变量以 uc 为前缀,其中“u”表示“unsigned” , “c”表示“char ”。
  5. 非 stdint 类型的变量以 x 为前缀。例如,BaseType_t 和 TickType_t,二者分别是可移植层定义的定义类型,主要架构的自然类型或最有效类型,以及用于保存 RTOS ticks 计数的类型。
  6. 非 stdint 类型的未签名变量存在附加前缀 u。例如,UBaseType_t(无符号的BaseType_t)类型变量以 ux 为前缀。
  7. size_t 类型变量也带有 x 前缀。
  8. 枚举变量以 e 为前缀
  9. 指针以附加 p 为前缀,例如,指向 uint16_t 的指针将以 pus 为前缀。
  10. 根据 MISRA 指南,无符号 char 类型仅可包含 ASCII 字符,并以 c 为前缀。
  11. 根据 MISRA 指南,char * 类型变量仅可包含指向 ASCII 字符串的指针,并以 pc 为前缀。

函数

  1. 函数名称使用驼峰式大小写,具有明确的描述性,并使用完整的单词(无缩写,但普遍接受的缩写除外)。
  2. 文件作用域静态(私有)函数以 prv 为前缀。
  3. 根据变量定义的相关规定,API 函数以其返回类型为前缀,并为 void 添加前缀 v。
  4. API 函数名称以定义 API 函数文件的名称开头。

比如一个函数 vTaskDelay , 从函数名可以得到如下信息:v表示这个函数的返回值是void, Task表示这个函数定义在Task.c文件中, Delay表示函数的功能

  1. 宏具有明确的描述性,并使用完整的单词(无缩写,但普遍接受的缩写除外)。
  2. 宏以定义宏的文件为前缀。前缀为小写。例如,在 FreeRTOSConfig.h 中定义 configUSE_PREEMPTION。
  3. 除前缀外,所有宏均使用大写字母书写,并使用下划线来分隔单词。

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

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

相关文章

可以进行重复测量的方差分析的AI agent

可以进行重复测量的方差分析的AI agent 前几天做了机器学习的AI agent,把一个糖尿病机器学习模型采用API的形式接入到LLM模型中,结合LLM的智能性和机器学习模型的准确性,利用两者的有点,有可以避免两者的缺点,是一条合…

OpenCV实现Kuwahara滤波

Kuwahara滤波是一种非线性的平滑滤波技术,其基本原理在于通过计算图像模板中邻域内的均值和方差,选择图像灰度值较为均匀的区域的均值来替代模板中心像素的灰度值。以下是Kuwahara滤波的详细原理说明: 一、基本思想 Kuwahara滤波的基本思想…

[文献精汇]使用 LSTM Networks 的均值回归交易策略

Backtrader 策略实例 [Backtrader]实例:均线策略[Backtrader] 实例:MACD策略[Backtrader] 实例:KDJ 策略[Backtrader] 实例:RSI 与 EMA 结合[Backtrader] 实例:SMA自定义数据源[Backtrader] 实例:海龟策略[Backtrader] 实例:网格交易[Backtrader] 实例: 配对交[Backtrader] 机…

IDEA Maven构建时报错:无效的目标发行版17

报错分析 报错原因:Maven 构建时,Java 版本配置不匹配 我安装的JDK版本是1.8,但由于种种原因,Maven构建时指定了 Java 17 作为目标发行版,从而导致错误 解决方案 首先,java -version,查看环…

计算机网络 (39)TCP的运输连接管理

前言 TCP(传输控制协议)是一种面向连接的、可靠的传输协议,它在计算机网络中扮演着至关重要的角色。TCP的运输连接管理涉及连接建立、数据传送和连接释放三个阶段。 一、TCP的连接建立 TCP的连接建立采用三次握手机制,其过程如下&…

Navicat Premium 16.0.90 for Mac 安装与free使用

步骤 0.下载 通过网盘分享的文件:Navicat Premium 16.0.90 链接: https://pan.baidu.com/s/12O22rXa9MiBPKKTGMELNIg 提取码: yyds 1.打开下好的 dmg 文件 (这个界面不要关闭) 2.将Navicat Premium 拖动至 Applications 这时出现 点击取消。 3.点开…

小创新模型!6种2024算法优化BiTCN-SVM单变量输入单步预测,MATLAB机器学习预测全家桶再更新...

截止到本期MATLAB机器学习预测全家桶,一共发了26篇关于机器学习预测代码的文章。算上这一篇,一共27篇!参考文章如下: 1.五花八门的机器学习预测?一篇搞定不行吗? 2.机器学习预测全家桶,多步预测…

3_CSS3 渐变 --[CSS3 进阶之路]

CSS3 引入了渐变(gradients),它允许在两个或多个指定的颜色之间显示平滑的过渡。CSS3 支持两种类型的渐变: 线性渐变(Linear Gradients):颜色沿着一条线性路径变化,可以是水平、垂直…

25/1/13 嵌入式笔记 继续学习Esp32

PWM(Pulse Width Modulation,脉宽调制) 是一种通过快速切换高低电平来模拟中间电压值的技术。它广泛应用于控制 LED 亮度、电机速度、音频生成等场景。 analogWrite函数:用于在微控制器(如 Arduino)上生成模拟信号。 …

【端云一体化】云函数的使用

前言 为丰富HarmonyOS对云端开发的支持、实现端云联动,DevEco Studio以Cloud Foundation Kit(云开发服务)为底座、在传统的“端开发”基础上新增“云开发”能力,开发者在创建工程时选择合适的云开发工程模板,即可在De…

行业案例:高德服务单元化方案和架构实践

目录 为什么要做单元化 高德单元化的特点 高德单元化实践 服务单元化架构 就近接入实现方案 路由表设计 路由计算 服务端数据驱动的单元化场景 总结 系列阅读 为什么要做单元化 单机房资源瓶颈 随着业务体量和服务用户群体的增长,单机房或同城双机房无法支持服…

基于单片机的语音控制玩具汽车的设计

语音控制小汽车选用了两个单片机、一个语音识别芯片、两个无线收发模块、一个电机驱动模块、两个电机、一个音频解码模块。语音控制端选用了一个语音识别芯片,实现了将声音信号转换成数字信号,再将数据传输给单片机的功能。小车端选用了单片机来控制电机…

解锁“搭子小程序”开发新机遇,助力企业数字化转型

搭子作为一种新型的社交方式,逐渐进入到了年轻人的生活中,在日常旅游、学习、逛街等,年轻人都可以找到志同道合的“搭子”,提高生活的幸福指数。 随着搭子市场的发展,通过互联网寻找搭子已经成为了年轻人的必备方式。…

Spring Boot 2 学习全攻略

Spring Boot 2 学习资料 Spring Boot 2 学习资料 Spring Boot 2 学习资料 在当今快速发展的 Java 后端开发领域,Spring Boot 2 已然成为一股不可忽视的强大力量。它简化了 Spring 应用的初始搭建以及开发过程,让开发者能够更加专注于业务逻辑的实现&am…

31_搭建Redis分片集群

Redis的主从复制模式和哨兵模式可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:海量数据存储问题、高并发写的问题。由于数据量过大,单个master复制集难以承担,因此需要对多个复制集进行集群,形成水平扩展每个复制集只负责存储整个数据集的一部分,这就是Red…

IMX6U Qt 开发环境

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一、交叉编译 1. 安装通用 ARM 交叉编译工具链 2. 安装 Poky 交叉编译工具链 二、编译出厂源码 1. U-boot 2. 内核和模块 3. 编译出厂 Qt GUI 综合 Demo 前言…

数据结构与算法之链表: LeetCode 92. 反转链表 II (Ts版)

反转链表 II https://leetcode.cn/problems/reverse-linked-list-ii/description/ 描述 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 示例 1 输入&…

【Uniapp-Vue3】@import导入css样式及scss变量用法与static目录

一、import导入css样式 在项目文件中创建一个common文件夹&#xff0c;下面创建一个css文件夹&#xff0c;里面放上style.css文件&#xff0c;编写的是公共样式&#xff0c;我们现在要在App.vue中引入该样式。 在App.vue中引入该样式&#xff0c;这样就会使样式全局生效&#…

MySQL中的四种表联结

目录 1、联结、关系表 &#xff08;1&#xff09;关系表 &#xff08;2&#xff09;为什么使用联结 2、如何创建联结 &#xff08;1&#xff09;笛卡尔积&#xff08;叉联结&#xff09;--用逗号分隔 &#xff08;2&#xff09;where子句的重要性 &#xff08;3&#xff…

DVWA靶场CSRF漏洞通关教程及源码审计

目录标题 CSRFlow源码审计 medium源码审计 high源码审计 impossible源码审计 CSRF low 先修改密码 看到地址栏 复制在另一个网页打开 成功登录 源码审计 没有任何过滤措施&#xff0c;很危险&#xff0c;并且采用了不安全的md5加密 <?phpif( isset( $_GET[ Change ] )…