参考教程:【正点原子】手把手教你学FreeRTOS实时系统_哔哩哔哩_bilibili
一、FreeRTOS文件介绍
1、v202411.00版本压缩包目录略解
将FreeRTOS v202411.00版本的压缩包解压,包中的文件结构如下图所示,其中FreeRTOS中存放FreeRTOS内核,FreeRTOS-Plus中存放FreeRTOS组件(一般不使用)。
FreeRTOS文件夹中又有几个文件夹,其中Source中装有FreeRTOS内核的源码,Demo中装有对各种单片机(及编译器)移植好的工程代码(或者说演示工程),License中的内容是一些许可信息,Test中存放公用以及移植层测试代码。
2、Source文件夹
(1)FreeRTOS→Source文件夹的当前目录中有若干源文件,当前目录中的include文件夹中又有若干头文件,这两部分的文件适用于各种编译器/处理器,在任何环境下都是通用的。
名称 | 描述 |
croutine.c | 协程相关文件 |
event_groups.c | 事件相关文件 |
list.c | 列表相关文件 |
queue.c | 队列相关文件 |
stream_buffer.c | 流式缓冲区相关文件 |
tasks.c | 任务相关文件 |
timers.c | 软件定时器相关文件 |
(2)FreeRTOS→Source→portable文件夹中则装有针对不同芯片及编译器的接口文件(软件与硬件的沟通桥梁),根据实际情况进行移植即可;除此之外,FreeRTOS→Source→portable→MemMang文件夹中还存放着内存管理相关的文件,如果要将FreeRTOS移植到stm32上,使用heap_4.c文件即可。
名称 | 描述 |
Keil | 指向RVDS文件夹 |
RVDS | 不同内核芯片的移植文件 |
MemMang | 内存管理文件 |
二、FreeRTOS移植具体步骤
1、移植步骤概览
(1)将FreeRTOS源码添加至基础工程,并添加头文件路径。
(2)添加FreeRTOSConfig.h配置文件,用于对FreeRTOS的功能进行配置和裁剪,以及API函数的使能等。
(3)修改stm32f10x.h文件。
(4)添加应用程序,验证移植是否成功。
2、示例
(1)拷贝一份STM32教程中使用OLED屏进行显示的工程文件夹,并更名为“FreeRTOS移植工程”。
(2)在工程文件夹中新建文件夹,命名为“FreeRTOS”,并将Source文件夹中的源文件以及Source→include文件夹中的头文件添加进来,Source→portable文件夹中的Keil、RVDS、MemMang文件夹中的内容根据需要添加进来(STM32F103C8T6的内核是ARM Cortex-M3,需添加ARM_CM3文件夹下的port.c文件和portmacro.h文件)。
(3)打开工程,新建两个文件分组,分别命名为“FreeRTOS_CORE”和“FreeRTOS_PORT”,用来存放FreeRTOS的内核C源码文件和移植文件(STM32F103C8T6的内核是ARM Cortex-M3,需添加ARM_CM3文件夹下的port.c文件和portmacro.h文件)。
(4)添加三个头文件路径。
(5)添加FreeRTOSConfig.h文件,用户可通过该文件对FreeRTOS进行裁剪,去掉不需要用到的FreeRTOS功能,以此节约MCU的空间资源;这个文件可以由用户自行编写,也可在Demo文件夹中拷贝演示工程的FreeRTOSConfig.h文件,这里直接拷贝CORTEX_STM32F103_Keil文件夹中的FreeRTOSConfig.h文件即可(该文件将任务调度器配置为抢占式,可通过宏定义进行修改)。
(6)在FreeRTOSConfig.h文件中添加三个中断函数的宏定义(注意添加的位置)。
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#define xPortSysTickHandler SysTick_Handler
(7)注释stm32f10x_it.c文件中的三个空函数。
//void SVC_Handler(void) {}
//void PendSV_Handler(void) {}
//void SysTick_Handler(void) {}
(8)在main.c文件中添加头文件FreeRTOS.h和task.h。
#include "FreeRTOS.h"
#include "task.h"
(9)点击编译,如无报错说明移植成功,后续例程基于此工程展开。
3、系统配置文件详解
(1)FreeRTOSConfig.h配置文件通过宏定义对FreeRTOS的功能进行配置和裁剪,以及API函数的使能等,相关宏可大致分为以下三类:
①“INCLUDE”参数:配置FreeRTOS中可选的API函数。
②“config”参数:完成FreeRTOS的功能配置和裁剪。
③其它配置项:PendSV宏定义、SVC宏定义。
(2)各个宏详解:
①基础配置项:
宏定义 | 解释 |
configUSE_PREEMPTION | 1:配置为抢占式调度器 |
0:配置为协程式调度器 | |
无默认选项,必须定义 | |
configUSE_PORT_OPTIMISED_TASK_SELECTION | 1:使用硬件计算下一个要运行的任务(不一定支持所有硬件,任务优先级有限制,但效率高) |
0:使用软件计算下一个要运行的任务(不限任务优先级,支持所有硬件) | |
默认选项为0 | |
configUSE_TICKLESS_IDLE | 1:使能tickless低功耗模式 |
0:失能tickless低功耗模式 | |
默认选项为0 | |
configCPU_CLOCK_HZ | CPU主频率 |
configSYSTICK_CLOCK_HZ | SysTick时钟频率(与内核时钟频率不同时才可定义) |
configTICK_RATE_HZ | 系统时钟节拍频率(滴答定时器的计数频率),单位为Hz,必须定义 |
configMAX_PRIORITIES | 最大优先级 =(configMAX_PRIORITIES -1),必须定义 |
configMINIMAL_STACK_SIZE | 空闲任务的栈空间大小,单位为字,必须定义 |
configMAX_TASK_NAME_LEN | 任务名最大字符数,默认为16 |
configUSE_16_BIT_TICKS | 1:定义系统时钟节拍计数器的数据类型为16位无符号整型 |
0:定义系统时钟节拍计数器的数据类型为32位无符号整型 | |
无默认选项,必须定义 | |
configIDLE_SHOULD_YIELD | 1:在抢占式调度下,同优先级的任务能抢占空闲任务 |
0:在抢占式调度下,同优先级的任务不能抢占空闲任务 | |
默认选项为1 | |
configUSE_TASK_NOTIFICATIONS | 1:使能任务间直接的消息传递,包括信号量、事件标志和消息邮箱 |
0:失能任务间直接的消息传递,包括信号量、事件标志和消息邮箱 | |
默认选项为1 | |
configTASK_NOTIFICATION_ARRAY_ENTRIES | 任务通知数组的大小,默认为1 |
configUSE_MUTEXES | 1:使能互斥信号量 |
0:失能互斥信号量 | |
默认选项为0 | |
configUSE_RECURSIVE_MUTEXES | 1:使能递归互斥信号量 |
0:失能递归互斥信号量 | |
默认选项为0 | |
configUSE_COUNTING_SEMAPHORES | 1:使能计数信号量 |
0:失能计数信号量 | |
默认选项为0 | |
configUSE_ALTERNATIVE_API | 已废弃,可忽视(置0即可) |
configQUEUE_REGISTRY_SIZE | 可以注册的信号量和消息队列的个数,默认为0 |
configUSE_QUEUE_SETS | 1:使能队列集 |
0:失能队列集 | |
默认选项为0 | |
configUSE_TIME_SLICING | 1:使能时间片调度 |
0:失能时间片调度 | |
默认选项为1 | |
configUSE_NEWLIB_REENTRANT | 1:任务创建时分配Newlib的重入结构体 |
0:任务创建时不分配Newlib的重入结构体 | |
默认选项为0 | |
configENABLE_BACKWARD_COMPATIBILITY | 1:使能兼容老版本 |
0:失能兼容老版本 | |
默认选项为1 | |
configNUM_THREAD_LOCAL_STORAGE_POINTERS | 线程本地存储指针的个数,默认为0 |
configSTACK_DEPTH_TYPE | 任务堆栈深度的数据类型,默认为uint_16 |
configMESSAGE_BUFFER_LENGTH_TYPE | 消息缓冲区中消息长度的数据类型,默认为size_t |
②内存分配相关定义:
宏定义 | 解释 |
configSUPPORT_STATIC_ALLOCATION | 1:支持静态申请内存 |
0:不支持静态申请内存 | |
默认选项为0 | |
configSUPPORT_DYNAMIC_ALLOCATION | 1:支持动态申请内存 |
0:不支持动态申请内存 | |
默认选项为1 | |
configTOTAL_HEAP_SIZE | FreeRTOS堆中可用的RAM总量,单位为字节 |
configAPPLICATION_ALLOCATED_HEAP | 1:用户手动分配FreeRTOS内存堆(ucHeap) |
0:自动分配FreeRTOS内存堆(ucHeap) | |
默认选项为0 | |
configSTACK_ALLOCATION_FROM_SEPARATE_HEAP | 1:用户自行实现任务创建时使用的内存申请与释放函数 |
0:自动实现任务创建时使用的内存申请与释放函数 | |
默认选项为0 |
③钩子函数相关定义:
宏定义 | 解释 |
configUSE_IDLE_HOOK | 1:使能空闲任务钩子函数 |
0:失能空闲任务钩子函数 | |
无默认选项,必须定义 | |
configUSE_TICK_HOOK | 1:使能系统时钟节拍中断钩子函数 |
0:失能系统时钟节拍中断钩子函数 | |
无默认选项,必须定义 | |
configCHECK_FOR_STACK_OVERFLOW | 1:使能栈溢出检测方法1 |
2:使能栈溢出检测方法2 | |
0:不使能栈溢出检测方法 | |
默认选项为0 | |
configUSE_MALLOC_FAILED_HOOK | 1:使能动态内存申请失败钩子函数 |
0:失能动态内存申请失败钩子函数 | |
默认选项为0 | |
configUSE_DAEMON_TASK_STARTUP_HOOK | 1:使能定时器服务任务首次执行前的钩子函数 |
0:失能定时器服务任务首次执行前的钩子函数 | |
默认选项为0 |
④运行时间和任务状态统计相关定义:
宏定义 | 解释 |
configGENERATE_RUN_TIME_STATS | 1:使能任务运行时间统计功能 |
0:失能任务运行时间统计功能 | |
默认选项为0 | |
configUSE_TRACE_FACILITY | 1:使能可视化跟踪调试 |
0:失能可视化跟踪调试 | |
默认选项为0 | |
configUSE_STATS_FORMATTING_FUNCTIONS | 1:编译vTaskList()和vTaskGetRunTimeStats()函数 |
0:不编译vTaskList()和vTaskGetRunTimeStats()函数 | |
默认选项为0 |
⑤协程相关定义:
宏定义 | 解释 |
configUSE_CO_ROUTINES | 1:启用协程 |
0:不启用协程 | |
默认选项为0 | |
configMAX_CO_ROUTINE_PRIORITIES | 协程的最大优先级, 最大优先级 =(configMAX_CO_ROUTINE_PRIORITIES -1),启用协程时必须定义 |
⑥软件定时器相关定义:
宏定义 | 解释 |
configUSE_TIMERS | 1:使能软件定时器 |
0:失能软件定时器 | |
默认选项为0 | |
configTIMER_TASK_PRIORITY | 软件定时器任务的优先级,使能软件定时器时必须定义 |
configTIMER_QUEUE_LENGTH | 软件定时器命令队列的长度,使能软件定时器时必须定义 |
configTIMER_TASK_STACK_DEPTH | 软件定时器任务的栈空间大小,使能软件定时器时必须定义 |
⑦可选函数(1为使能,0为失能):
宏定义 | 对应的函数功能 |
INCLUDE_vTaskPrioritySet | 设置任务优先级 |
INCLUDE_uxTaskPriorityGet | 获取任务优先级 |
INCLUDE_vTaskDelete | 删除任务 |
INCLUDE_vTaskSuspend | 挂起任务 |
INCLUDE_xResumeFromISR | 恢复在中断中挂起的任务 |
INCLUDE_vTaskDelayUntil | 任务绝对延时 |
INCLUDE_vTaskDelay | 任务延时 |
INCLUDE_xTaskGetSchedulerState | 获取任务调度器状态 |
INCLUDE_xTaskGetCurrentTaskHandle | 获取当前任务的任务句柄 |
INCLUDE_uxTaskGetStackHighWaterMark | 获取任务堆栈历史剩余最小值 |
INCLUDE_xTaskGetIdleTaskHandle | 获取空闲任务的任务句柄 |
INCLUDE_eTaskGetState | 获取任务状态 |
INCLUDE_xEventGroupSetBitFromISR | 在中断中设置事件标志位 |
INCLUDE_xTimerPendFunctionCall | 将函数的执行挂到定时器服务任务 |
INCLUDE_xTaskAbortDelay | 中断任务延时 |
INCLUDE_xTaskGetHandle | 通过任务名获取任务句柄 |
INCLUDE_xTaskResumeFromISR | 恢复在中断中挂起的任务 |