【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤

目录

1.获取FreeRTOS源码

1.1 FreeRTOS官网下载步骤

1.2FreeRTOS源码内容

 1.3FreeRTOS内核文件

 1.3.1Demo文件夹

 1.3.2Source文件夹

2.FreeRTOS移植

2.1添加FreeRTOS源码

2.1.1复制FreeRTOS源码

 2.1.2将文件添加到工程

 2.1.3添加头文件路径

 2.2添加FreeRTOS.h

2.3修改SYSYTEM文件 

2.3.1sys.h

2.3.2usart.c 

 2.3.3delay.c

 2.4修改中断相关文件

2.5可选步骤

2.5.1修改工程名称

2.5.2移除USMART调试组件

2.5.3添加定时器驱动

 2.6添加应用程序

3.系统配置文件说明

4.总结


1.获取FreeRTOS源码

1.1 FreeRTOS官网下载步骤

        进入网址:FreeRTOS官网

         点击DownLoad FreeRTOS,上图页面中两个按钮可以二选一

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第1张图片

        选择下载FreeRTOS,点击图中的DownLoad
【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第2张图片

        即可出现下图的下载图,如果多次下载不成功,可能需要挂梯子,这里我是用挂梯子才下载成功的。

1.2FreeRTOS源码内容

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第3张图片

          最重要的是FreeRTOS的内核文件,移植相关都需要此文件夹。

FreeRTOS源码介绍
名称 描述
FreeRTOS FreeRTOS内核(我们移植FreeRTOS的必要文件
FreeRTOS.Plus FreeRTOS组件
tools 工具
GitHub-FreeRTOS-Home FreeRTOS的GitHub仓库链接
Quick_Start_Guide 快速入门指南官方文档链接
Upgrading-to-FreeRTOS-xxx 升级到指定FreeRTOS版本官方文档链接
History.txt FreeRTOS历史更新记录
其他 其他

 1.3FreeRTOS内核文件

        打开FreeRTOS的内核文件会出现以下内容:

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第4张图片

FreeRTOS内核文件
名称  描述
Demo FreeRTOS官方提供的演示例程
License FreeRTOS相关许可(未用到
Source FreeRTOS源码
Test 公用以及移植层测试代码(未用到

 1.3.1Demo文件夹

        Demo文件夹里面是FreeRTOS的演示例程,如下所示:

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第5张图片

         通过以上文件可以看出FreeRTOS支持多种芯片架构、支持多种不同型号芯片,对于入门学习 FreeRTOS 是十分有帮助的,在学习移植FreeRTOS 的过程中就可以参考这些演示工程。

 1.3.2Source文件夹

        Source文件夹中是FreeRTOS的源码,FreeRTOS是一种轻量级的、可被裁剪的OS。以下是Source文件夹中的内容:

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第6张图片

         除了用不到,可以不添加的文件,其他文件是FreeRTOS必须涉及的文件。

Soure文件夹
名称 描述
include 内包含了FreeRTOS的头文件
portable 内包含了FreeRTOS的移植文件
croutine.c 协程相关文件(不用可以不添加
event_groups.c 事件相关文件(不用可以不添加
list.c 列表相关文件
queue.c 队列相关文件
stream_buffer.c 流式缓冲区相关文件(不用可以不添加
tasks.c 任务相关文件
timers.c 软件定时器相关文件(不用可以不添加

portable文件夹

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

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第7张图片

名称

描述

Keil

指向RVDS文件夹,对应MDK开发

RVDS

不同内核芯片的移植文件(由于Keil文件夹中内容指向RVDS,所以需要此文件,连接硬件的桥梁所在文件,根据不同的内核芯片去选择不同的桥梁)

MemMang

内存管理文件

2.FreeRTOS移植

        目的:实现全STM32的FreeRTOS移植。

移植准备:

1.FreeRTOS源码

2.由于后续实验需要使用LED、LCD、定时器、内存管理等所以我们使用正点原子HAL库版本的内存管理的实验工程为基础工程进行FreeRTOS的移植。由于内存管理实验例程的BSP文件夹中可能不包含定时器的驱动文件,因此如果内存管理实验例程的BSP文件夹不包括TIMER文件夹的话,需要从定时器相关的BSP文件夹中拷贝一份TIMER到FreeRTOS移植基础工程中。使用普通的跑马灯实验例程作为基础工程也是没有问题的,这里使用内存管理实验是为了方便后续例程。

 移植步骤:

1.添加FreeRTOS源码:将FreeRTOS源码添加至基础工程、头文件路径等。(比如之前提到 三个主要联系文件:队列、列表、任务相关,以及连接桥梁、头文件等)

2.FreeRTOSConfig.h:添加FreeRTOSConfig.h配置文件(此文件主要是用来拆解FreeRTOS的功能,以及一些API函数的使能都是通过此文件实现)

3.修改SYSTEM文件:修改SYSYTEM文件中的sys.c、delay.c、usart.c(正点原子中这三个文件是基于裸机以及UCOS-III是实现的,FreeRTOS是不能直接使用的,需要进行修改

4.修改中断相关文件:修改Systick中断、SVC中断、PendSV中断(这些中断和任务切换相关)

5.添加应用程序:验证移植是否成功

2.1添加FreeRTOS源码

2.1.1复制FreeRTOS源码

        此项目程序依赖正点原子A盘中的HAL库版本例程的38-内存管理实验7-定时器中断实验此处使用的代码和2022年正点原子发行的视频中使用的程序版本不同,但是原理一致。

        将38-内存管理实验文件夹改为“FreeRTOS移植”,在文件夹中创建FreeRTOS文件夹,将FreeRTOS源码Source中的文件全部拷贝到FreeRTOS文件中,并删除.gitmodules文件,只保留.c文件。

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第8张图片

         连接桥梁portable文件夹,在开发STM32时只用到了上文中提到的三个文件夹,其余用不到的文件,可以自行决定是否删除,这里将其他未用到的文件删除掉了。

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第9张图片

 2.1.2将文件添加到工程

        打开工程,在项目中新建两个文件分组。

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第10张图片

         向两个分组中添加文件。FreeRTOS_CORE文件夹放FreeRTOS的内核C源码文件,FreeRTOS_PORT中存放内核的移植文件,内存管理文件heap_x.c和连接桥梁port.c文件。port.c文件需要根据处理器型号的不同选择不同文件下的port.c文件。

STM32不同型号芯片与port.c的对应关系

STM32芯片类型

port.c所在文件
STM32F1 ARM_CM3
STM32F4 ARM_CM4F
STM32F7 ARM_CM7/r0p1
STM32H7 ARM_CM7/r0p1

        添加后的工程目录如下图所示: 

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第11张图片

 2.1.3添加头文件路径

        头文件地 目录包含FreeRTOS源码的头文件include和连接桥梁port.c的头文件。

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第12张图片

 2.2添加FreeRTOS.h

        FreeRTOSConfig.h时FreeRTOS操作系统的配置文件,FreeRTOS是可裁剪的,通过将FreeRTOS.h文件中用不到的功能可以通过宏定义为0去掉。

1、FreeRTOSConfig.h获取途径一

        用户自行编写,根据自己的需求编写FreeRTOSConfig.对FreeRTOS操作系统进行裁剪。对新手来说,并不友好,新手并不知道FreeRTOS有哪些功能。官方网址:FreeRTOS配置网址   网址中对各个配置项进行了描述,是官方提供的FreeRTOSConfig.h的模板。

2、FreeRTOSConfig.h获取途径二

        FreeRTOS内核的Demo工程中获取。Demo文件夹包含了FreeRTOS官方提供的演示工程,在这些演示工程中就包括了每个演示工程对应的FreeRTOSConfig.h,注意有些演示工程使用的是老版本的FreeRTOS,因此FreeRTOSConfig.h并不能够很好的适用新版本的FreeRTOS。

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第13张图片

 3、FreeRTOSConfig.h获取途径三

        从正点原子配套例程“FreeRTOS移植实验”的FreeRTOS/include文件夹下找到FreeRTOSConfig.h文件。这里和2022年出品的正点原子FreeRTOS视频有区别。复制到移植工程的USER文件夹下,如下图所示:

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第14张图片

2.3修改SYSYTEM文件 

        SYSTEM文件夹中的文件是正点原子一开始针对编写,所以用于FreeRTOS,需要作相应的修改。SYSTEM文件中一共需要修改三个文件,分别是sys.h,usart.c,delay.c。

2.3.1sys.h

        将以下宏定义改为1,表示支持OS。

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

2.3.2usart.c 

        需要修改两个地方,首先是串口中的中断服务函数,原本在使用时,进入和退出中断需要添加OSIntEnter()和OSIntExit()两个函数,这是对于中断的相关处理机制,而FreeRTOS并没有这种机制,因此需要将这两行代码删除,修改后的串口中断服务函数如下所示

//串口1中断服务程序
void USART1_IRQHandler(void)                	
{ 
	u8 Res;

	if((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_RXNE)!=RESET))  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
        HAL_UART_Receive(&UART1_Handler,&Res,1,1000); 
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d
			{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到0X0D
			{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}   		 
	}
	HAL_UART_IRQHandler(&UART1_Handler);	
 											 
} 

        usart.c要修改的第二个地方时导入的头文件,因为在串口的中断服务函数中已经删除了的相关代码,并且FreeRTOS也没有使用相关代码,因此将usart.c中包含的关于OS的头文件删除,要删除的代码如下

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

 2.3.3delay.c

        delay.c文件需要改动的地方比较多,大致可以分为三个步骤:1)删除适用于但不适用与FreeRTOS的代码;2)添加FreeRTOS的相关代码;3)修改部分内容。

1) 删除适用于但不适用与FreeRTOS的代码

        一共需要删除1个全局变量、6个宏定义、3个函数,这些要删除的代码在使用时候会用到,但是在使用FreeRTOS的时候无需使用,要删除的代码如下所示,还需删除SysTick_Handler函数后的#endif

#if SYSTEM_SUPPORT_OS		
    static u16 fac_ms=0;				        //ms延时倍乘数,在os下,代表每个节拍的ms数
#endif

#if SYSTEM_SUPPORT_OS							//如果SYSTEM_SUPPORT_OS定义了,说明要支持OS了(不限于UCOS).
//当delay_us/delay_ms需要支持OS的时候需要三个与OS相关的宏定义和函数来支持
//首先是3个宏定义:
//delay_osrunning:用于表示OS当前是否正在运行,以决定是否可以使用相关函数
//delay_ostickspersec:用于表示OS设定的时钟节拍,delay_init将根据这个参数来初始哈systick
//delay_osintnesting:用于表示OS中断嵌套级别,因为中断里面不可以调度,delay_ms使用该参数来决定如何运行
//然后是3个函数:
//delay_osschedlock:用于锁定OS任务调度,禁止调度
//delay_osschedunlock:用于解锁OS任务调度,重新开启调度
//delay_ostimedly:用于OS延时,可以引起任务调度.

//本例程仅作UCOSII和UCOSIII的支持,其他OS,请自行参考着移植
//支持UCOSII
#ifdef 	OS_CRITICAL_METHOD						//OS_CRITICAL_METHOD定义了,说明要支持UCOSII				
#define delay_osrunning		OSRunning			//OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec	OS_TICKS_PER_SEC	//OS时钟节拍,即每秒调度次数
#define delay_osintnesting 	OSIntNesting		//中断嵌套级别,即中断嵌套次数
#endif

//支持UCOSIII
#ifdef 	CPU_CFG_CRITICAL_METHOD					//CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII	
#define delay_osrunning		OSRunning			//OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec	OSCfg_TickRate_Hz	//OS时钟节拍,即每秒调度次数
#define delay_osintnesting 	OSIntNestingCtr		//中断嵌套级别,即中断嵌套次数
#endif


//us级延时时,关闭任务调度(防止打断us级延迟)
void delay_osschedlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD   			//使用UCOSIII
	OS_ERR err; 
	OSSchedLock(&err);						//UCOSIII的方式,禁止调度,防止打断us延时
#else										//否则UCOSII
	OSSchedLock();							//UCOSII的方式,禁止调度,防止打断us延时
#endif
}

//us级延时时,恢复任务调度
void delay_osschedunlock(void)
{	
#ifdef CPU_CFG_CRITICAL_METHOD   			//使用UCOSIII
	OS_ERR err; 
	OSSchedUnlock(&err);					//UCOSIII的方式,恢复调度
#else										//否则UCOSII
	OSSchedUnlock();						//UCOSII的方式,恢复调度
#endif
}

//调用OS自带的延时函数延时
//ticks:延时的节拍数
void delay_ostimedly(u32 ticks)
{
#ifdef CPU_CFG_CRITICAL_METHOD
	OS_ERR err; 
	OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err); //UCOSIII延时采用周期模式
#else
	OSTimeDly(ticks);						    //UCOSII延时
#endif 
}
 

2)添加FreeRTOS相关代码

         只需要在delay.c文件中使用extern关键字导入一个FreeRTOS函数——xPortSysTickHandler()即可,这个函数是用于处理FreeRTOS系统时钟节拍的,本文将SysTick作为FreeRTOS操作系统的心跳,因此需要在SysTick的中断服务函数中调用这个函数,因此将代码添加到SysTick中断服务函数之前,修改后的代码如下

extern void xPortSysTickHandler(void);
//systick中断服务函数,使用OS时用到
void SysTick_Handler(void)
{	
    HAL_IncTick();
	if(delay_osrunning==1)					//OS开始跑了,才执行正常的调度处理
	{
		OSIntEnter();						//进入中断
		OSTimeTick();       				//调用ucos的时钟服务程序               
		OSIntExit();       	 				//触发任务切换软中断
	}
}

3)修改部分内容

        修改的内容包括两个,分别是包括头文件和4个函数。

        修改的4个函数分别是:SysTick_Handler()、delay_init()、delay_us()和delay_ms()。

3-1)SysTick_Handler()

        滴答定时器中断服务函数SysTick_Handler()中需要调用之前(2)中添加的代码。修改后的代码如下

//systick中断服务函数,使用OS时用到
void SysTick_Handler(void)
{	
    HAL_IncTick();
	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)	//OS开始跑了,才执行正常的调度处理
	{
		xPortSysTickHandler();
	}
}

 3-2)delay_init()

        delay_init()主要用于初始化SysTick。在后续调用vTaskStartScheduler()函数时,FreeRTOS会按照FreeRTOSConfig.h文件的配置对SysTick进行初始化,因此delay_init()函数对于SysTick的初始化主要使用在FreeRTOS开始任务调度之前。函数delay_init()要修改的部分主要是为SysTick的重装载值以及删除用不到的代码,修改后的代码如下所示(F1和F4/F7/H7系列修改后不同,此处为F4/F7/H7修改后的代码):

void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
	u32 reload;
#endif
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick频率为HCLK
	fac_us=SYSCLK;						//不论是否使用OS,fac_us都需要使用
#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
	reload=SYSCLK;					    //每秒钟的计数次数 单位为K
	/*使用configTick_RATE_HZ计算重装载值
	 *configTick_RATE_HZ在FreeRTOSConfig.h中定义
	 */
	reload*=1000000/configTICK_RATE_HZ;	//根据configTICK_RATE_HZ设定溢出时间
											//reload为24位寄存器,最大值:16777216,在180M下,约合0.745s左右	
	/*删除不用的g_fac_ms相关代码*/
	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断
	SysTick->LOAD=reload; 					//每1/OS_TICKS_PER_SEC秒中断一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
#else
#endif
}		

         在正点原子STM32系列开发板的标准例程源码中,STM32F1系列的函数delay_init()将SysTick的时钟频率设置为CPU时钟频率的1/8,而STM32F4/F7/H7系列的函数delay_init则将SysTick的时钟频率设置为与CPU相同的时钟频率,由于FreeRTOS在配置SysTick时,并不会配置SysTick的时钟源,因此这将导致正点原子STM32F1系列和正点原子STM32F4/F7/H7系列的FreeRTOSConfig.h文件有所差异,并且也只有这一点存在差异

3-3)delay_us()

        函数delay_us()用于微秒级的CPU忙延时,原本的函数delay_us()延时的前后加入了自定义函数delay_osschedlock()delay_osschedunlock()用于锁定和解锁的任务调度器,让延时更加准确。在FreeRTOS中可以不用加入这两个函数,但是这会让函数delay_us(0的微妙延时的精度有所下降,修改后的代码如下所示(同时需要删除delay_osschedlock()delay_osschedunlock()两个函数)

void delay_us(u32 nus)
{		
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;				//LOAD的值	    	 
	ticks=nus*fac_us; 						//需要的节拍数 
	/*删除适用于uC/OS用于锁定任务调度器的自定义函数*/
	told=SysTick->VAL;        				//刚进入时的计数器值
	while(1)
	{
		tnow=SysTick->VAL;	
		if(tnow!=told)
		{	    
			if(tnow=ticks)break;			//时间超过/等于要延迟的时间,则退出.
		}  
	};
	/*删除用于解锁任务调度器的自定义函数*/										    
}  

 3-4)delay_ms()

        函数delay_ms()用于毫秒级的CPU忙延时,原本的函数delay_ms()会判断是否在运行,如果正在运行则使的OS延时进行毫秒级延时,否则就调用delay_us()进行毫秒级的CPU忙延时。在FreeRTOS中,可以将函数delay_ms()定义为CPU忙延时,当需要OS延时时,调用FreeRTOS提供的OS延时函数vTaskDelay()delay_ms()函数修改后的代码如下

void delay_ms(u16 nms)
{	
	uint32_t i;
	for(i=0;i

3-5)包含头文件

        根据上述步骤的修改,delay.c文件中使用到了FreeRTOS的相关函数,因此需要在该文件中包含FreeRTOS的相关头文件,并且移除原本存在的相关头文件。先看一下改之前delay.c文件中包含的相关的头文件:

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

        修改后的内容如下

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

 2.4修改中断相关文件

        在FreeRTOS的移植过程中会用到三个重要重要中断,分别任FreeRTOS系统时基定时器中断(SysTick中断)、SVC中断、PendSV中断。对于不同型号的STM32,中断服务函数所在文件名字有所不同,具体如下:

STM32系列 中断服务函数所在文件
STM32F1 stm32f2xx_it.c
STM32F4 stm32f4xx_it.c
STM32F7 stm32f4xx_it.c
STM32H7 stm32h7xx_it.c

        SysTick的中断服务函数在delay.c中已经定义了,并且FreeRTOS也提供了SVC和PendSV的中断服务函数,因此需要将HAL库提供的这三个中断服务函数注释掉,这里采用宏开关的方式让HAL库中的这三个中断服务函数不加入注释,使用的宏在sys.h中定义,因此还得导入sys.h头文件。 添加头文件后的代码如下所示

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_it.h"
/*导入 sys.h 头文件*/
#include "sys.h"

        并且将sys.h的以下宏定义改为1:

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

        在SVC_Handler、PendSV_Handler、SysTick_Handler函数外加入宏开关。修改后的代码如下

/**
  * @brief  This function handles SVCall exception.
  * @param  None
  * @retval None
  */
#if(!SYSTEM_SUPPORT_OS)
void SVC_Handler(void)
{
}
#endif
/**
  * @brief  This function handles Debug Monitor exception.
  * @param  None
  * @retval None
  */
void DebugMon_Handler(void)
{
}

/**
  * @brief  This function handles PendSVC exception.
  * @param  None
  * @retval None
  */
#if(!SYSTEM_SUPPORT_OS)
void PendSV_Handler(void)
{
}
#endif
/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
#if(!SYSTEM_SUPPORT_OS)
void SysTick_Handler(void)
{
  HAL_IncTick();
}
#endif

         最后,还需修改FreeRTOSConfig.h文件,文件中有如下定义(由于前面并没有添加FreeRTOSConfig.h到项目文件夹中,所以需要编译才能打开):

#define configPRIO_BITS       		__NVIC_PRIO_BITS

        对于这个宏定义,在下文讲解到ARM Corten-M和FreeRTOS中断的时候会具体分析。可以看到,这个宏定义将configPRIO_BITS定义成__NVIC_PRIO_BITS,而__NVIC_PRIO_BITS在HAL库中有相关定义,对于不同的STM32型号,__NVIC_PRIO_BITS定义在不同的文件中,具体的对应关系如下表所示:

不同型号STM32与__NVIC_PRIO_BITS所在文件的对应关系
STM32型号 __NVIC_PRIO_BITS所在文件
STM32F1 stm32f103x3.h
STM32F4 stm32f407xx.h或stm32f429xx.h
STM32F7 stm32f750xx.h或stm32f767xx.h
STM32H7 stm32h750xx.h或stm32h743xx.h

         虽然不同类型的芯片对应的文件不同,但是__NVIC_PRIO_BITS都被定义成立相同的值,如下所示:

#define __NVIC_PRIO_BITS          4U       /*!< STM32F4XX uses 4 Bits for the Priority Levels */

        这个值是正确的,但是如果将__NVIC_PRIO_BITS定义成4U的话,在编译FreeRTOS工程的时候,Keil会报错,解决方法就是将4U改成4,代码修改后如下图所示(在源码中我并不需要修改,因为本身就是4,这里和2022正点原子FreeRTOS教程有所不同):

#define __NVIC_PRIO_BITS          4       /*!< STM32F4XX uses 4 Bits for the Priority Levels */

        此时编译文件将不再报错。 

2.5可选步骤

2.5.1修改工程名称

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第15张图片

2.5.2移除USMART调试组件

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第16张图片

         同时删除main函数中的关于USMAT的头文件,usmart.h。并且删除main函数中调用USMART的相关代码。

2.5.3添加定时器驱动

        将实验7-基本定时器中断实验中的TIMER文件夹复制到HARDWARE文件夹下。并且在工程中添加.c文件。

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第17张图片

 2.6添加应用程序

        移植好FreeRTOS后需要测试移植是否成功。将测试源码拷贝到工程文件USER下。测试程序下载链接:

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第18张图片

        在工程中添加freertos.c文件,并且在main函数中添加头文件freertos.h,修改后如下所示

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "sdram.h"

#include "malloc.h"
#include "freertos_demo.h"

        在freertos.c中创建了两个任务,task1和task2,每隔1s翻转LED0亮灭状态和每隔1s翻转LED1的亮灭状态,外设的初始化在led.h中。这里所使用的程序是老版本程序项目,并没有2022正点原子FreeRTOS中的LED0_TOGGLE()LED0_TOGGLE()两个函数,并且led.h文件并不相同。所以如果想达到任务要求,只需要将TOGGLE函数改成LED灯状态取反即可。修改后的程序如下所示:

void task1(void *pvParameters)
{    
    while(1)
    {
        LED0=~LED0;                                                     /* LED0闪烁 */
        vTaskDelay(1000);                                               /* 延时1000ticks */
    }
}
void task2(void *pvParameters)
{
    while(1)
    {
        LED1=~LED1;
        vTaskDelay(500);                           /* 延时500ticks */
    }
}

         在main()函数中调用freertos_demo()函数,可能会产生Error:L6406E错误,只需删除main函数中调用的其他函数即可,修改后main函数如下所示

int main(void)
{
    
    HAL_Init();                     //初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化USART
    LED_Init();                     //初始化LED 
	freertos_demo();
}

        在正点原子STM32F429阿波罗开发板上,会显示LED0亮1s灭1s,而LED1亮0.5s灭0.5s,移植程序验证成功。

3.系统配置文件说明

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

学习途径:

1.官方的在线文档有详细的说明:FreeRTOS官方说明文档地址

2.正点原子《FreeRTOS开发指南》第三章的内容——FreeRTOS系统配置

 相关宏可以大致分为三类:

“INCLUDE”:配置FreeRTOS中可选的API函数

“config”:完成FreeRTOS的功能配置和裁剪

其他配置项:PendSV中断服务函数宏定义、SVC终端服务函数宏定义(宏定义供port.c进行调用)

4.总结

【02】FreeRTOS获取10.4.6源码+移植到STM32F429步骤_第19张图片

你可能感兴趣的:(FreeRTOS,linux,运维,服务器,嵌入式,STM32)