3.1 FreeRTOS详细移植步骤(自己的实操)

@[TOC](3.1 FreeRTOS详细移植步骤(自己的实操))

自己使用阿波罗F767的内存管理实验和定时器实验,进行复刻。
FreeRTOS源码版本是FreeRTOS 202212.01。官网和Github都有下载。
按照STM32F767FreeRTOS开发手册V1.1进行移植复刻。
注:这个开发手册不是开发指南。跟视频里用的教程(开发手册)有出入。

新建FreeRTOS的工程方法可以分为:
1、CubeMX生成带FreeRTOS的HAL库工程。(CSDN有一篇文章介绍,简单)
2、已有HAL库的基础工程,将FreeRTOS移植进该工程。(步骤复杂)
3、已有标准固件库的基础工程,将FreeRTOS移植进该工程。(步骤复杂)

本文记录“已有HAL库的基础工程,将FreeRTOS移植进该工程”的方法。

计划完成FreeRTOS基础工程移植后
再完成“任务创建与恢复”实验,看看代码的含义。
完成后续视频中的实验。
由于没有开发板,实验只编程,没有报错即可,不看实验现象。
(虽然是一种不好的学习方法)

1 准备

1 阿波罗F767的内存管理实验
  作为基础工程
2 阿波罗F767的定时器实验
  用到里面的设备驱动代码
3 FreeRTOS源码
  官网或github下载。2.24.5.24,下载的是V202212.01版本。
在这里插入图片描述

4(可选) 正点原子的“FreeRTOS移植实验”,这个是移植完成的工程,可当作参考。
没找到HAL的FreeRTOS工程。只有固件库的FreeRTOS工程,可按照教程修改,使之支持HAL
库。

2 移植

2.1 STM32F7xx_DFP

keil5编辑STM32F系列的工程时,需要添加STM32F7xx_DFP的pack,CSDN上已记录添加步骤。

2.2 建立基础工程

使用内存管理实验作为基础工程。
将内存管理实验复制一份,并命名为“FreeRTOS_Demo”。
在这里插入图片描述

修改名字(非必须),并编译。
会发现0error0warning。
在这里插入图片描述

2.3 FreeRTOS源码文件处理

2.3.1 源码文件解压

2.3.2 源码文件简化

源码解压后的文件夹是FreeRTOSv202212.01,找到其中的Source文件夹是各源码文件,有一些文件用不到,所以就删了。
在这里插入图片描述

有以上绿色下划线的五个文件,FreeRTOS就可以用起来了。
不用其他功能,对应的.c文件,可不添加。
这里就全部保留了。

再将portable文件夹中的文件进行删除。
只留下下面三个文件夹(用其他编辑器或MCU,根据实际情况选择留下的文件夹)
在这里插入图片描述

2.4 添加FreeRTOS源码文件

将FreeRTOS源码文件添加至工程。过程简单,不再展示图片。
第一步:在基础工程中新建一个名为 FreeRTOS 的文件夹。

第二步:将Source文件夹下的所有源码文件,复制进第一步新建的文件夹中。

第三步:在keil中新建两个“分组”,分别是 FreeRTOS_COREFreeRTOS_PORTABLE

新建分组,不等于新建文件夹。
在这里插入图片描述

第四步:在keil中为 FreeRTOS_CORE添加c文件
在这里插入图片描述

添加完成后
在这里插入图片描述

第五步:在keil中为FreeRTOS_PORTABLE添加c文件
这个分组中添加两个文件,port.cheap_4.c
port.c与所用的芯片有关,这个选用了STM32F767,所以要选择RVDS文件夹下的ARM_CM7中的port.c文件。
heap_4.c是内存管理算法,选择MemMang文件夹下的heap_4.c文件。
添加完成后如下图。
在这里插入图片描述

第六步:添加头文件路径
在上两步中添加了c文件,还要添加FreeRTOS的头文件路径,要不keil找不到头文件会报错。
在这里插入图片描述

完成以上六步后,点击编译,会报错,提示没有“FreeRTOSConfig.h”配置文件。
所以进行2.5小节。

2.5 添加FreeRTOS配置文件

FreeRTOSConfig.h是一个配置文件,在这个文件中,通过宏定义完成对系统功能的配置和裁剪。共有三个方法。推荐第三种。
方法一:自己创建并编写。

方法二:从官方demo中移植。
在官方demo中找到针对F7的KEIL工程。
在这里插入图片描述

上面的文件夹中,即可找到FreeRTOSConfig.h配置文件。

Cortex就是ARM公司一个系列处理器的名称。
比如英特尔旗下处理器有酷睿,奔腾,赛扬。
ARM在最初的处理器型号都用数字命名,最后一个是ARM11系列,在应用ARMv7架构后,推出了Cortex这一系列,老式的则命名为Classic系列。

其中:“A”系列面向尖端的基于虚拟内存的操作系统和用户应用;“R”系列针对实时系统;“M”系列对微控制器。

方法三:从“FreeRTOS移植实验”中获取(推荐)
从正点原子的“FreeRTOS移植实验”中获取带注释的配置文件,更方便学习。
在扩展例程中找到该实验。

找到后将文件复制,粘贴到移植工程中FreeRTOS文件夹下的Include中(放在USER下也行,灵活点),这样就不需要再添加“头文件路径”了。
在这里插入图片描述

此时再编译工程,仍会报错。
按照下面的步骤继续进行修改,逐渐的消除错误信息,完成移植。

2.6 修改system文件

修改其中的sys.h,delay.c,uart.c三个文件。
这三个文件大部分是针对UCOS的,所以要进行修改。
使之支持FreeRTOS。

2.6.1 修改sys.h文件

打开sys.h文件
使用了FreeRTOS,所以将SYSTEM_SUPPORT_OS修改为1。

//0,不支持os
//1,支持os
#define SYSTEM_SUPPORT_OS		1		//定义系统文件夹是否支持OS

2.6.2 修改uart.c文件

有两部分需要进行修改
第一部分:添加FreeRTOSConfig.h头文件
默认添加的是UCOS的“includes.h”头文件,将其删除,添加为“FreeRTOSConfig.h”的头文件。

//如果使用os,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
//#include "includes.h"					//UCOS 使用	 
#include "FreeRTOSConfig.h"  //FreeRTOS使用
#endif

第二部分:修改USART1的中断服务函数
uart.c文件默认支持UCOS的,UCOS进出中断时需要添加OSIntEnter()和 OSIntExit(),使用 FreeRTOS 的话就不需要了,所以将这两行代码删除掉。
看了下,本工程的uart.c文件中,该代码用了条件编译。如下。

#if SYSTEM_SUPPORT_OS	 	//使用OSOSIntEnter();    
#endif

所以直接删除也行,宏前面加个叹号也行。
这里直接删除。

重新学习一下宏定义,看看#if和#ifdef的区别是什么?

删除后的代码为

//串口1中断服务程序  FreeRTOS
void USART1_IRQHandler(void)                	
{ u32 timeout=0;u32 maxDelay=0x1FFFF;HAL_UART_IRQHandler(&UART1_Handler);	//调用HAL库中断处理公用函数timeout=0;while (HAL_UART_GetState(&UART1_Handler)!=HAL_UART_STATE_READY)//等待就绪{timeout++;超时处理if(timeout>maxDelay) break;		}timeout=0;while(HAL_UART_Receive_IT(&UART1_Handler,(u8 *)aRxBuffer, RXBUFFERSIZE)!=HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1{timeout++; //超时处理if(timeout>maxDelay) break;	}} 

注意,在我这里用的这个例程中,USART1的中断服务函数是针对UCOS的,即使删除了OSIntEnter()和 OSIntExit()也可能不对。
但在下方有一个被注释的USART1中断服务函数,这个是针对FreeRTOS的。就是上面删除后的代码。(这段代码也是跟指南中的代码一致的)
所以一定要跟上面的代码对应。
还可以将上面的代码复制,对“USART1的中断服务函数”进行替换。

2.6.3 修改delay.c文件

同理,delay.c文件中的程序是支持UCOS的,经过对比,发现不适合将程序修改后适配FreeRTOS,所以将delay.c文件的代码全部删除,然后将固件库的“FreeRTOS移植实验”delay.c文件代码复制过来。复制过来之后,再稍作修改,使之支持HAL库。

因为delay.c文件涉及到 FreeRTOS 的系统时钟,所以修改比较大。
delay.c文件中有5个函数,将所以的代码复制,经过修改后,支持HAL的FreeRTOS中的delay.c代码如下。
以后使用时,直接将下面的代码复制到delay.c中即可。

注意,倒数第二个函数void delay_ms(u32 nms),形参改变了,需要在.h中重新声明一下。

#include "delay.h"
#include "sys.h"
// 	 
//如果使用OS,则包括下面的头文件即可
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"					//FreeRTOS使用		  
#include "task.h"
#endif
//  
//使用SysTick的普通计数模式对延迟进行管理(支持OS)
//包括delay_us,delay_ms
//********************************************************************************static u8  fac_us=0;							//us延时倍乘数			   
static u16 fac_ms=0;							//ms延时倍乘数,在os下,代表每个节拍的ms数extern void xPortSysTickHandler(void);//systick中断服务函数,使用OS时用到
void SysTick_Handler(void)
{	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行{xPortSysTickHandler();	}HAL_IncTick();
}//初始化延迟函数
//当使用FreeRTOS时,此函数会初始化FreeRTOS的时钟节拍。
//SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
//这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
//SYSCLK:系统时钟频率
void delay_init(u8 SYSCLK)
{u32 reload;//SysTick 频率为 HCLKHAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);fac_us=SYSCLK;							//不论是否使用OS,fac_us都需要使用reload=SYSCLK;							//每秒钟的计数次数 单位为M	   reload*=1000000/configTICK_RATE_HZ;		//根据configTICK_RATE_HZ设定溢出时间//reload为24位寄存器,最大值:16777216,在168M下,约合0.0998s左右	fac_ms=1000/configTICK_RATE_HZ;			//代表OS可以延时的最少单位	   SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断SysTick->LOAD=reload; 					//每1/configTICK_RATE_HZ断一次	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK     
}								    //延时nus
//nus:要延时的us数.	
//nus:0~204522252(最大值即2^32/fac_us@fac_us=168)	    								   
void delay_us(u32 nus)
{		u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD;				//LOAD的值	    	 ticks=nus*fac_us; 						//需要的节拍数 told=SysTick->VAL;        				//刚进入时的计数器值while(1){tnow=SysTick->VAL;	if(tnow!=told){	    if(tnow<told)tcnt+=told-tnow;	//这里注意一下SYSTICK是一个递减的计数器就可以了.else tcnt+=reload-tnow+told;	    told=tnow;if(tcnt>=ticks)break;			//时间超过/等于要延迟的时间,则退出.}  };										    
}  
//延时nms 会引起任务调度
//nms:要延时的ms数
//nms:0~65535
void delay_ms(u32 nms)
{	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行{		if(nms>=fac_ms)						//延时的时间大于OS的最少时间周期 { vTaskDelay(nms/fac_ms);	 		//FreeRTOS延时}nms%=fac_ms;						//OS已经无法提供这么小的延时了,采用普通方式延时    }delay_us((u32)(nms*1000));				//普通方式延时
}//延时nms,不会引起任务调度
//nms:要延时的ms数
void delay_xms(u32 nms)
{u32 i;for(i=0;i<nms;i++) delay_us(1000);
}

修改完成后,点击编译。

2.7 修改中断相关文件

编译后会报错
在这里插入图片描述

这三个函数,在port.c和stm32f7xx_it.c中被多次定义了。
所以选在将stm32f7xx_it.c中的这三个函数注释掉。
用条件编译注释掉,如下

#if (!SYSTEM_SUPPORT_OS)
void SVC_Handler(void)
{
}
#endif

注意,SYSTEM_SUPPORT_OS这个宏在sys.h中,所以要在stm32f7xx_it.c包含这个头文件。

完成后再点击编译。

2.8 小节

编译后没有错误。
但是还需要编写应用程序进行验证。
移植步骤大体就是这样。
看开发手册中,不同芯片还会有其他错误,等实际遇到时再去改吧。

2.9 验证移植是否成功

需要编写应用程序。

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

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

相关文章

关于Qt部署CMake导致“Failed to set working directory to”的问题

2024年7月23日补充&#xff1a;该目录过深的情况只在Win10上有发现&#xff0c;Win11则没有问题&#xff0c;且Win11可以在DevHome中设置LongPath。 --------------------------------------------------------------------------------------------------------------- 使用qt…

Spark_Oracle_II_Spark高效处理Oracle时间数据:通过JDBC桥接大数据与数据库的分析之旅

接前文背景&#xff0c; 当需要从关系型数据库&#xff08;如Oracle&#xff09;中读取数据时&#xff0c;Spark提供了JDBC连接功能&#xff0c;允许我们轻松地将数据从Oracle等数据库导入到Spark DataFrame中。然而&#xff0c;在处理时间字段时&#xff0c;可能会遇到一些挑战…

分布式Apollo配置中心搭建实战

文章目录 环境要求第一步、软件下载第二步、创建数据库参考文档 最近新项目启动&#xff0c;采用Apollo作为分布式的配置中心&#xff0c;在本地搭建huanj 实现原理图如下所示。 环境要求 Java版本要求&#xff1a;JDK1.8 MySql版本要求&#xff1a;5.6.5 Apollo版本要求&…

第八讲:Sysmac Studio控制器设置

控制器设置 一、控制器设定-操作设置 1、启动模式(运行模式/编程模式) 控制器上电后,希望程序运行还是不运行。如果说希望程序运行,那么就选择运行模式。如果说希望上电后程序不运行就选择编程模式。 通常情况下选运行模式可能会比较多一些。 2、SD内存卡设置 当控制…

Pytorch TensorBoard的使用

from torch.utils.tensorboard import SummaryWriter writer SummaryWriter("logs")for i in range(100):writer.add_scalar("yx",i,i) writer.close() 第一个参数 y2x: 这是图表的标题或标签。它会显示在TensorBoard界面中,帮助你识别这条曲线。 第二个参…

(35)远程识别(又称无人机识别)(二)

文章目录 前言 4 ArduRemoteID 5 终端用户数据的设置和使用 6 测试 7 为OEMs添加远程ID到ArduPilot系统的视频教程 前言 在一些国家&#xff0c;远程 ID 正在成为一项法律要求。以下是与 ArduPilot 兼容的设备列表。这里(here)有一个关于远程 ID 的很好解释和常见问题列表…

【数据结构】排序算法——Lesson2

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

uni-app pinia搭建

1.新建store文件 新建index.js&#xff0c;代码&#xff1a; // import { // createPinia // } from pinia //const store createPinia() import * as Pinia from pinia const pinia Pinia.createPinia() export * from "./modules/user" export * from ".…

vscode 寻找全部分支的提交

vscode 寻找全部分支的提交 Git Graph

Python 机器学习求解 PDE 学习项目——PINN 求解二维 Poisson 方程

本文使用 TensorFlow 1.15 环境搭建深度神经网络&#xff08;PINN&#xff09;求解二维 Poisson 方程: 模型问题 − Δ u f in Ω , u g on Γ : ∂ Ω . \begin{align} -\Delta u & f \quad & \text{in } \Omega,\\ u & g \quad & \text{on } \Gamma:\p…

Proxmox8基于PC物理机/服务器安装,初始化,挂载磁盘,安装虚拟机

目录 安装文件 开始安装Proxmox 选择启动菜单&#xff0c;F11 后进入启动菜单选择 按需选择是否关闭RAID 选择对应的U盘 进入安装界面 进入安装启动过程 选择系统盘 设置相关信息 设置IP和开启root远程登录 设置dns 设置网卡ip 设置 ssh 远程登录 开机合并local-l…

Telegram曝零日漏洞,可伪装成视频攻击安卓用户

ESET Research在一个地下论坛上发现了一个针对Android Telegram的零日漏洞广告。 ESET将该漏洞命名为“EvilVideo”&#xff0c;并将其报告给Telegram&#xff0c;Telegram于7月11日更新了该应用程序。 EvilVideo允许攻击者发送恶意的有效载荷&#xff0c;这些载荷以视频文件…

计算机网络-配置双机三层互联(静态路由方式)

目录 交换机工作原理路由器工作原理路由信息表组成部分路由器发决策 ARP工作原理配置双机三层互联&#xff08;静态路由方式&#xff09; 交换机工作原理 MAC自学习过程 初始状态&#xff1a; 刚启动的交换机的MAC地址表是空的。 学习过程&#xff1a; 当交换机收到一个数据帧…

论文阅读——Integrated Diffusive Antenna Array of Low Backscattering

文章目录 摘要一、背景介绍二、天线结构A. 缝隙天线B. 低频扩散单元C. 高频扩散单元D. 集成设计 三、验证总结 论文来源&#xff1a;https://ieeexplore.ieee.org/document/10309141 摘要 文章提出了一种低雷达散射截面&#xff08;RCS&#xff09;的扩散天线阵列。 作为示例…

STM32嵌入式人工智能边缘计算应用教程

目录 引言环境准备边缘计算系统基础代码实现&#xff1a;实现嵌入式人工智能边缘计算系统 4.1 数据采集模块 4.2 数据处理与推理模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;边缘计算与优化问题解决方案与优化收尾与总结 1. 引言 嵌入式人工智…

前后端分离项目部署,vue--nagix发布部署,.net--API发布部署。

目录 Nginx免安装部署文件包准备一、vue前端部署1、修改http.js2、npm run build 编译项目3、解压Nginx免安装,修改nginx.conf二、.net后端发布部署1、编辑appsetting.json,配置跨域请求2、配置WebApi,点击发布3、配置文件发布到那个文件夹4、配置发布相关选项5、点击保存,…

Python-numpy基础--------2

1.full()创建函数 目录 1.full()创建函数 2.创建单位矩阵 3.linspace创建 4.logspace 创建 5.二维数组的索引和切片&#xff1a; 1.索引直接获取 在NumPy中&#xff0c;full() 函数用于创建一个给定形状、类型的新数组&#xff0c;并用指定的值填充这个数组。这个函数非…

【vue前端项目实战案例】Vue3仿今日头条App

本文将开发一款仿“今日头条”的新闻App。该案例是基于 Vue3.0 Vue Router webpack TypeScript 等技术栈实现的一款新闻资讯类App&#xff0c;适合有一定Vue框架使用经验的开发者进行学习。 项目源码在文章末尾 1 项目概述 该项目是一款“今日头条”的新闻资讯App&#xf…

go语言day14 bufio包 ioutil包

Golang-100-Days/Day16-20(Go语言基础进阶)/day16_file操作.md at master rubyhan1314/Golang-100-Days GitHub 一、bufio包 读写文件 1&#xff09; bufio包下的Reader类实现了Read()方法和Write()方法 2&#xff09;和io包相比&#xff0c;虽然都是在读写文件&#xff0c;…

【Android】性能实践—编码优化与布局优化学习笔记

【Android】性能实践—编码优化与布局优化学习笔记 编码优化 使用场景 如果需要拼接字符串&#xff0c;优先使用StringBuffer和StringBuilder进行凭借&#xff0c;他们的性能优于直接用加号进行拼接&#xff0c;因为使用加号连接符会创建多余的对象一般情况下使用基本数据类…