当前位置:首页 > 学习资源 > 讲师博文 > FreeRTOS的介绍及移植

FreeRTOS的介绍及移植 时间:2023-09-11      来源:华清远见

一.FreeRTOS简单概述

1.1 FreeRTOS目录结构

以Keil工具下STM32F103芯片为例,它的FreeRTOS的目录如下: 

主要涉及2个目录:

Demo 

Demo目录下是工程文件,以"芯片和编译器"组合成一个名字 

比如:CORTEX_STM32F103_Keil 

Source 

根目录下是核心文件,这些文件是通用的 

portable目录下是移植时需要实现的文件 

目录名为:[compiler]/[architecture] 

比如:RVDS/ARM_CM3,这表示cortexM3架构在RVDS工具上的移植文件

1.2 核心文件

FreeRTOS的最核心文件只有2个: 

FreeRTOS/Source/tasks.c 

FreeRTOS/Source/list.c 

其他文件的作用也一起列表如下:

1.3 移植时涉及的文件

移植FreeRTOS时涉及的文件放在 FreeRTOS/Source/portable/[compiler]/[architecture] 目录下,比如:RVDS/ARM_CM3,这表示cortexM3架构在RVDS或Keil工具上的移植文件。 

里面有2个文件: 

port.c 

portmacro.h

1.4头文件相关

列表如下:

1.5内存管理

文件在 FreeRTOS/Source/portable/MemMang 下,它也是放在 portable 目录下,表示你可以提供自己的函数。 

源码中默认提供了5个文件,对应内存管理的5种方法。 

参考文章:FreeRTOS说明书吐血整理【适合新手+入门】 

1.6 Demo

Demo目录下是预先配置好的、没有编译错误的工程。目的是让你可以基于它进行修改,以适配你的单板。 

这些Demo还可以继续精简: 

Demo/Common 中的文件可以完全删除 

main函数中只需要保留2个函数: 

prvSetupHardware() 

vTaskStartScheduler() 

如下图所示:

1.7数据类型和编程规范

1.7.1数据类型

每个移植的版本都含有自己的 portmacro.h 头文件,里面定义了2个数据类型: 

TickType_t: 

FreeRTOS配置了一个周期性的时钟中断:Tick Interrupt 

每发生一次中断,中断次数累加,这被称为tick count 

tick count这个变量的类型就是TickType_t 

TickType_t可以是16位的,也可以是32位的 

FreeRTOSConfifig.h中定义confifigUSE_16_BIT_TICKS时,TickType_t就是uint16_t 

否则TickType_t就是uint32_t 

对于32位架构,建议把TickType_t配置为uint32_t 

BaseType_t: 

这是该架构最高效的数据类型 

32位架构中,它就是uint32_t 

16位架构中,它就是uint16_t 

8位架构中,它就是uint8_t 

BaseType_t通常用作简单的返回值的类型,还有逻辑值,比如 pdTRUE/pdFALSE 

1.7.2变量名

变量名有前缀:

1.7.3函数名

函数名的前缀有2部分:返回值类型、在哪个文件定义。

1.7.4宏的名

宏的名字是大小,可以添加小写的前缀。前缀是用来表示:宏在哪个文件中定义。

1.8安装keil

移植过程

2.1提取源码

首先在我们的STM32裸机工程模板根目录下新建一个文件夹,命名为“FreeRTOS”,并且在FreeRTOS文件夹下新建两个空文件夹,分别命名为“src”与“port”,src文件夹用于保存FreeRTOS中的核心源文件,也就是我们常说的‘.c文件’,port文件夹用于保存内存管理以及处理器架构相关代码,这些代码FreeRTOS官方已经提供给我们的,直接使用即可,在前面已经说了,FreeRTOS是软件,我们的开发版是硬件,软硬件必须有桥梁来连接,这些与处理器架构相关的代码,可以称之为RTOS硬件接口层,它们位于FreeRTOS/Source/Portable文件夹下。

2.1.1

打开FreeRTOS V9.0.0源码,在“FreeRTOSv9.0.0\FreeRTOS\Source”目录下找到所有的‘.c文件’,将它们拷贝到我们新建的src文件夹中

2.1.2

打开FreeRTOS V9.0.0源码,在“FreeRTOSv9.0.0\FreeRTOS\Source\portable”目录下找到“MemMang”文件夹与“RVDS”文件夹,将它们拷贝到我们新建的port文件夹中

2.1.3

打开FreeRTOS V9.0.0源码,在“FreeRTOSv9.0.0\ FreeRTOS\Source”目录下找到“include”文件夹,它是我们需要用到FreeRTOS的一些头文件,将它直接拷贝到我们新建的FreeRTOS文件夹中,完成这一步之后就可以看到我们新建的FreeRTOS文件夹已经有3个文件夹,这3个文件夹就包含FreeRTOS的核心文件,至此,FreeRTOS的源码就提取完成。

 

2.2添加到工程

2.2.1添加FreeRTOSConfig.h文件

 FreeRTOSConfig.h文件是FreeRTOS的工程配置文件,因为FreeRTOS是可以裁剪的实时操作内核,应用于不同的处理器平台,用户可以通过修改这个FreeRTOS内核的配置头文件来裁剪FreeRTOS的功能,所以我们把它拷贝一份放在user这个文件夹下面。
 打开FreeRTOSv9.0.0源码,在“FreeRTOSv9.0.0\FreeRTOS\Demo”文件夹下面找到“CORTEX_STM32F103_Keil”这个文件夹,双击打开,在其根目录下找到这个“FreeRTOSConfig.h”文件,然后拷贝到我们工程的user文件夹下即可,等下我们需要对这个文件进行修改。

2.2.2创建工程分组

接下来我们在mdk里面新建FreeRTOS/src和FreeRTOS/port两个组文件夹,其中FreeRTOS/src用于存放src文件夹的内容,FreeRTOS/port用于存放port\MemMang文件夹 与port\RVDS\ARM_CM3文件夹的内容。
然后我们将工程文件中FreeRTOS的内容添加到工程中去,按照已经新建的分组添加我们的FreeRTOS工程源码。
在FreeRTOS/port分组中添加MemMang文件夹中的文件只需选择其中一个即可,我们选择“heap_4.c”,这是FreeRTOS的一个内存管理源码文件。
添加完成后:

2.1.3

打开FreeRTOS V9.0.0源码,在“FreeRTOSv9.0.0\ FreeRTOS\Source”目录下找到“include”文件夹,它是我们需要用到FreeRTOS的一些头文件,将它直接拷贝到我们新建的FreeRTOS文件夹中,完成这一步之后就可以看到我们新建的FreeRTOS文件夹已经有3个文件夹,这3个文件夹就包含FreeRTOS的核心文件,至此,FreeRTOS的源码就提取完成。

2.2.4修改FreeRTOSConfig.h

FreeRTOSConfig.h是直接从demo文件夹下面拷贝过来的,该头文件对裁剪整个FreeRTOS所需的功能的宏均做了定义,有些宏定义被使能,有些宏定义被失能,一开始我们只需要配置最简单的功能即可。要想随心所欲的配置FreeRTOS的功能,我们必须对这些宏定义的功能有所掌握,下面我们先简单的介绍下这些宏定义的含义,然后再对这些宏定义进行修改。

2.2.5修改stm32f10x_it.c

SysTick中断服务函数是一个非常重要的函数,FreeRTOS所有跟时间相关的事情都在里面处理,SysTick就是FreeRTOS的一个心跳时钟,驱动着FreeRTOS的运行,就像人的心跳一样,假如没有心跳,我们就相当于“死了”,同样的,FreeRTOS没有了心跳,那么它就会卡死在某个地方,不能进行任务调度,不能运行任何的东西,因此我们需要实现一个FreeRTOS的心跳时钟,FreeRTOS帮我们实现了SysTick的启动的配置:在port.c文件中已经实现vPortSetupTimerInterrupt()函数,并且FreeRTOS通用的SysTick中断服务函数也实现了:在port.c文件中已经实现xPortSysTickHandler()函数,所以移植的时候只需要我们在stm32f10x_it.c文件中实现我们对应(STM32)平台上的SysTick_Handler()函数即可。FreeRTOS为开发者考虑得特别多,PendSV_Handler()与SVC_Handler()这两个很重要的函数都帮我们实现了,在在port.c文件中已经实现xPortPendSVHandler()与vPortSVCHandler()函数,防止我们自己实现不了,那么在stm32f10x_it.c中就需要我们注释掉PendSV_Handler()与SVC_Handler()这两个函数了。

2.2.6创建任务

这里,我们创建一个单任务,任务使用的栈和任务控制块是在创建任务的时候FreeRTOS动态分配的。
任务必须是一个死循环,否则任务将通过LR返回,如果LR指向了非法的内存就会产生HardFault_Handler,而FreeRTOS指向一个死循环,那么任务返回之后就在死循环中执行,这样子的任务是不安全的,所以避免这种情况,任务一般都是死循环并且无返回值的。
并且每个任务循环主体中应该有阻塞任务的函数,否则就会饿死比它优先级更低的任务!!!

 

上一篇:Java为什么只有值传递

下一篇:UART、RS232、RS485、IIC、SPI5大常用协 议原理、应用场景及异同对比

戳我查看嵌入式每月就业风云榜

点我了解华清远见高校学霸学习秘籍

猜你关心企业是如何评价华清学员的

干货分享
相关新闻
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2024 北京华清远见科技发展有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部