一.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指向一个死循环,那么任务返回之后就在死循环中执行,这样子的任务是不安全的,所以避免这种情况,任务一般都是死循环并且无返回值的。
并且每个任务循环主体中应该有阻塞任务的函数,否则就会饿死比它优先级更低的任务!!!