FreeRTOS学习笔记(一)—— 裸机和RTOS,Freertos移植(MDK),stm32cubeIDE使用Freertos
文章目录
- `FreeRTOS学习笔记(一)—— 裸机和RTOS,Freertos移植(MDK),stm32cubeIDE使用Freertos`
- `FreeRTOS学习笔记系列`
- `开胃小菜(前缀后缀)`
- 前缀x和v
- 后缀FromISR
- `1、裸机与RTOS`
- `裸机与RTOS的区别`
- `前后台系统(裸机)`
- `实时操作系统(RTOS)`
- `2、FreeRTOS简介`
- `3、Freertos调度方式`
- `抢占式——优先级不同的任务`
- `时间片轮转——优先级相同的任务`
- `协程式——不更新`
- `PS:Freertos的四个任务状态`
- `4、Freertos移植(MDK)`
- `源码文件夹介绍`
- `动手移植`
- `Source文件夹`
- `portable文件夹`
- `Keil文件夹`
- `RVDS文件夹`
- `MemMang文件夹`
- `添加 FreeRTOSConfig.h 文件`
- `FreeRTOSConfig.h获取途径`
- `移植好了别忘了加路径啊!!!!!!!!`
- `5、stm32cubeide创建Freertos工程`
- `如果对你有帮助,就点赞收藏吧!(。・ω・。)ノ♡`
FreeRTOS学习笔记系列
【FreeRTOS(MDK、STM32CUBEIDE)学习笔记,超详细!!!(合集)】
【FreeRTOS学习笔记(一)—— 裸机和RTOS,Freertos移植(MDK),stm32cubeIDE使用Freertos】
【FreeRTOS学习笔记(二)—— 任务,挂起,临界区,中断,任务调度和切换】
【FreeRTOS学习笔记(三)—— 消息队列,信号量,事件标志组,任务通知】
【FreeRTOS学习笔记(四)—— 延时函数,列表,软件定时器,低功耗模式,内存管理】
开胃小菜(前缀后缀)
前缀x和v
FreeRTOS 的一些函数前缀x,而有一些前缀v,到底是什么意思呢
就比如任务的创建和删除
API函数 | 描述 |
---|---|
xTaskCreate() | 动态方式创建任务 |
xTaskCreateStatic() | 静态方式创建任务 |
vTaskDelete() | 删除任务 |
x代表函数返回值为一个BaseType_t类型,用于辨别是否创建成功
v的含义是void,即没有返回值
后缀FromISR
带 “FromISR” 后缀是在 中断函数 中专用的API函数
在中断服务函数里边需调用FreeRTOS的API函数,必须使用带“FromISR”后缀的函数
1、裸机与RTOS
裸机与RTOS的区别
用两个事情作比喻:打游戏和跟对象聊天
裸机:游戏和对象只能选一个,打游戏怎么能分心呢
RTOS:小孩子才做选择,我两个都要,边打游戏边聊天
前后台系统(裸机)
裸机又称为前后台系统,前台系统指的中断服务函数,后台系统指的while()大循环,即应用程序
1、实时性差:(应用程序)轮流执行
2、delay空等待:CPU不执行其他代码
3、结构臃肿:实现功能都放在一个无限循环里面
实时操作系统(RTOS)
RTOS全称为:Real Time OS,就是实时操作系统,强调的是:实时性
1、分而治之:实现功能划分为多个任务
2、延时函数:任务调度,delay的时候去干别的事,不空等
3、抢占式:高优先级任务抢占低优先级任务
4、任务堆栈:每个任务都有自己的栈空间
2、FreeRTOS简介
更加详细的介绍可以看往期文章【嵌入式实时操作系统(RT-Thread、FreeRTOS、UCOSIII)】
FreeRTOS 是一个免费的嵌入式实时操作系统
- 免费开源:FreeRTOS完全免费且开源,无潜在商业风险,无须担心
- 高度可裁剪:其核心代码精炼至约9000行,集中分布在3个.c文件中,方便定制和优化
- 使用简便:FreeRTOS的用户界面友好,易于理解和操作。
- 优先级无限制:任务优先级分配自由,多个任务共享同一优先级
- 无限任务数量:理论上,FreeRTOS支持创建无限数量的实时任务,没有软件限制(但受硬件限制)
- 多样化的任务调度:支持抢占式、协程式和时间片轮转等多种任务调度方式
3、Freertos调度方式
抢占式——优先级不同的任务
抢占式调度主要是针对优先级不同的任务
每个任务都有一个优先级,优先级高的任务可以抢占优先级低的任务。
时间片轮转——优先级相同的任务
时间片调度主要针对优先级相同的任务
同等优先级任务轮流地享有相同的 CPU 时间, 叫时间片
当多个任务的优先级相同时,任务调度器会在每一次系统时钟节拍到的时候切换任务。
在FreeRTOS中,一个时间片(Freertos不可设置)就等于 SysTick 中断周期(可设置)
一个时间片大小,取决为滴答定时器中断周期
SysTick 中断周期是可以设置的,可以间接更改时间片
如果Task运行过程中(还不到一个时间片)阻塞了(系统延时或等待信号量等),直接切换到下个Task
注意没有用完的时间片不会再使用
协程式——不更新
协程式调度当前执行任务将会一直运行,同时高优先级的任务不会抢占低优先级任务
FreeRTOS部分版本还支持,但是官方已经表示不再更新协程式调度
PS:Freertos的四个任务状态
在STM32中,同一时间仅一个任务处于运行态
仅就绪态可转变成运行态,其他状态的任务想运行,必须先转变成就绪态
就绪态、阻塞态、挂起态的任务都有其对应的任务状态列表
就绪列表pxReadyTasksLists[x]
阻塞列表pxDelayedTaskList[x]
挂起列表xSuspendedTaskList[x]
x:表示优先级
4、Freertos移植(MDK)
官网直接下载就行:https://www.freertos.org/
源码文件夹介绍
解压压缩包,可以看到一堆文件,文件如下表所示
文件/文件夹 | 描述 |
---|---|
FreeRTOS | FreeRTOS内核 |
FreeRTOS-Plus | FreeRTOS组件 |
tools | 工具 |
GitHub-FreeRTOS-Home | FreeRTOS的GitHub仓库链接 |
Quick_Start_Guide | 快速入门指南官方文档链接 |
Upgrading-to-FreeRTOS-xxx | 升级到指定FreeRTOS版本官方文档链接 |
History.txt | FreeRTOS历史更新记录 |
FreeRTOS-Plus包含了TCP,UDP,MQTT等一些组件,但是这些组件一般用三方
最核心的文件夹内就是FreeRTOS——FreeRTOS内核
文件/文件夹 | 描述 |
---|---|
Demo | FreeRTOS演示例程 |
License | FreeRTOS相关许可 |
Source | FreeRTOS源码 |
Test | 公用以及移植层测试代码 |
其中最重要的是Source——FreeRTOS源码
文件/文件夹 | 描述 |
---|---|
include | 内包含了FreeRTOS的头文件 |
portable | 内包含了FreeRTOS的移植文件 |
croutine.c | 协程相关文件 |
event_groups.c | 事件相关文件 |
list.c | 列表相关文件 |
queue.c | 队列相关文件 |
stream_buffer.c | 流式缓冲区相关文件 |
tasks.c | 任务相关文件 |
timers.c | 软件定时器相关文件 |
其中必要的有include,portable,list.c,queue.c,tasks.c
FreeRTOS操作系统归根到底是软件层面的
portable文件夹里面的东西就是连接桥梁
portable文件夹里面文件很多
用MDK编辑器的重要文件如下
名称 | 描述 |
---|---|
Keil | 指向RVDS文件夹 |
RVDS | 不同内核芯片的移植文件 |
MemMang | 内存管理文件 |
动手移植
这些文件从哪来?
当然还有其他的文档整理方式
Source文件夹
Source文件夹——FreeRTOS源码就是要移植的文件
前面所说的9个文件/文件夹,文件就不多说,文件夹再仔细看
文件/文件夹 | 描述 |
---|---|
include | 内包含了FreeRTOS的头文件 |
portable | 内包含了FreeRTOS的移植文件 |
croutine.c | 协程相关文件 |
event_groups.c | 事件相关文件 |
list.c | 列表相关文件 |
queue.c | 队列相关文件 |
stream_buffer.c | 流式缓冲区相关文件 |
tasks.c | 任务相关文件 |
timers.c | 软件定时器相关文件 |
portable文件夹
接着,就是我们的链接桥梁 portable——内包含了FreeRTOS的移植文件
前文也讲到了用MDK编辑器的重要文件如下
名称 | 描述 |
---|---|
Keil | 指向RVDS文件夹 |
RVDS | 不同内核芯片的移植文件 |
MemMang | 内存管理文件 |
Keil文件夹
里面就只有一个 “See-also-the-RVDS-directory.txt”,所以也没什么用
RVDS文件夹
不同内核芯片的移植文件(链接桥梁)
STM32系列 | Port文件所在文件夹 |
---|---|
STM32F1(ARMCC) | RVDS/ARM_CM3 |
STM32F4/STM32G4(ARMCC) | RVDS/ARM_CM4F |
STM32F7(ARMCC) | RVDS/ARM_CM7/r0p1 |
STM32H7(ARMCC) | RVDS/ARM_CM7/r0p1 |
STM32H5(ARMClang) | GCC/ARM_CM33_NTZ |
里面都是这两个文件
MemMang文件夹
内存管理算法
一般使用的是 “heap_4.c”
这就是我们常见的这些文件从哪里来
添加 FreeRTOSConfig.h 文件
FreeRTOSConfig.h 配置文件作用:对FreeRTOS的功能进行配置和裁剪,以及API函数的使能等
FreeRTOSConfig.h 是 FreeRTOS 操作系统的配置文件
FreeRTOS 操作系统是可裁剪的,用户可以根据需求对 FreeRTOS 进行裁剪
裁剪掉不需要用到的 FreeRTOS 功能,节约 MCU中内存资源。
INCLUDE前缀:使能FreeRTOS中所需的API函数
config前缀:FreeRTOS的功能配置和裁剪
FreeRTOSConfig.h获取途径
途径1:官方历程里拿来用,在文件FreeRTOS——Demo里(可能不靠谱)
途径2:找个靠谱公司的嵌入式历程移植,比如说正点原子
途径3:自己写,官网内核 > 开发者文档 > FreeRTOSConfig.h > 定制 里面介绍了各个功能
看过 “FreeRTOSConfig.h” 就会知道,其实也并没有多难理解
文章下面有解释每个宏的意义
移植好了别忘了加路径啊!!!!!!!!
5、stm32cubeide创建Freertos工程
RCC模式和配置(根据实际情况)
系统模式与配置
烧录/调试选择所需的烧录/调试方式
时钟则采用一个定时器作为时钟信号,如果使用Systick,会报如下警告
FREERTOS模式和配置
Freertos接口(CMSIS)
没有特殊需求的选择接口2
PS:CMSIS(Cortex Microcontroller Software Interface Standard)
CMSIS_V1和CMSIS_V2版本主要影响的是底层硬件抽象层的标准接口。
分别被称为CMSIS_CORE和CMSIS 5。
-
CMSIS V1 (CMSIS_CORE)
这是早期的版本,为Cortex-M处理器提供了一个标准的软件接口
包括了内核外设访问层(CPAL)、调试和DWT(Data Watchpoint and Trace)等功能。
它是FreeRTOS和其他RTOS的基础,确保了不同厂商的Cortex-M微控制器能够使用统一的API来访问硬件资源。 -
CMSIS V2 (CMSIS 5)
这是CMSIS的较新版本,引入了一些新的特性和改进
针对特定系列的STM32增加了额外组件,提供更多的功能和更好的性能。比如DFPs
CMSIS 5还改进了调试和跟踪机制,增强了与开发工具的兼容性。
参数配置(Config parameters)
下面是 参数配置(Config parameters) 各项的意义
配置 | 参数 | 意义 | 默认选项 |
---|---|---|---|
API | FreeRTOS API | AP接口 | CMSIS V2 |
Versions | FreeRTOS version | FreeRTOS版本 | 10.0.1 |
(版本) | CMSIS-RTOS version | CMSIS-RTOS版本 | 2 |
Kernel settings | USE_PREEMPTION | 使能抢占式调度器(Disable: 协程式调度器) | Enabled |
(内核设置) | CPU CLOCK HZ | CPU主频 | SystemCoreClock |
TICK RATE_HZ | 系统时钟节拍频率 | 1000 | |
MAX PRIORITIES | 定义最大优先级数 | 56 | |
MINIMAL STACK SIZE | 定义空闲任务的栈空间大小 | 128 Words | |
MAX TASK NAME LEN | 定义任务名最大字符数 | 16 | |
USE_16_BIT_TICKS | 定义系统时钟节拍计数器的数据类型为16位无符号数 | Disabled | |
IDLE SHOULD YIELD | 使能在抢占式调度下,同优先级的任务能抢占空闲任务 | Enabled | |
USE MUTEXES | 使能互斥信号量 | Enabled | |
USE RECURSIVE MUTEXES | 使能递归互斥信号量 | Enabled | |
USE COUNTING SEMAPHORES | 使能计数信号量 | Enabled | |
QUEUE REGISTRY SIZE | 定义可以注册的消息量和消息队列的个数 | 8 | |
USE APPLICATION TASK TAG | 使能启用应用程序任务堆栈监视 | Disabled | |
ENABLE BACKWARD COMPATIBILITY | 使能兼容老版本 | Enabled | |
USE PORT OPTIMISED TASK SELECTION | 使用硬件计算下一个要运行的任务 | Disabled | |
USE TICKLESS IDLE | 使能idleless低功耗模式 | Disabled | |
USE TASK NOTIFICATIONS | 使能任务间直接的消息传递包括信号量、事件标志组和消息邮箱 | Enabled | |
RECORD STACK HIGH ADDRESS | 记录任务堆栈的高地址 | Disabled | |
Memory management settings | Memory Allocation | 内存分配方式(默认动态/静态) | Dynamic / Static |
(内存管理设置) | TOTAL HEAP SIZE | FreeRTOS堆中可用的RAM总量 | 3072 Bytes |
Memory Management scheme | 内存管理方案(第4章算法) | heap_4 | |
Hook function related definitions | USE IDLE HOOK | 使能空闲任务钩子函数 | Disabled |
(钩子函数相关定义) | USE TICK HOOK | 使能系统时钟节拍中断钩子函数 | Disabled |
USE MALLOC FAILED_HOOK | 使能动态内存申请失败钩子函数 | Disabled | |
USE DAEMON TASK STARTUP_HOOK | 使能定时器服务任务首次执行前的钩子函数 | Disabled | |
CHECK FOR STACK OVERFLOW | 使能栈溢出检测方法 | Disabled | |
Run time and task stats gathering related definitions | GENERATE RUN TIME STATS | 使能任务运行时间统计功能 | Disabled |
(收集相关定义的运行时和任务统计信息) | USE TRACE FACILITY | 使能可视化跟踪调试 | Enabled |
USE STATS FORMATTING FUNCTIONS | 使能编译统计格式化函数 | Disabled | |
Co-routine related definitions | USE CO ROUTINES | 启用协程 | Disabled |
(协例程相关定义) | MAX CO ROUTINE PRIORITIES | 定义协程的最大优先级 | 2 |
Software timer definitions | USE TIMERS | 使能软件定时器 | Enabled |
(软件定时器定义) | TIMER TASK PRIORITY | 定义软件定时器任务的优先级 | 2 |
TIMER QUEUE LENGTH | 定义软件定时器命令队列的长度 | 10 | |
TIMER TASK STACK DEPTH | 定义软件定时器任务的栈空间大小 | 10 | |
Interrupt nesting behaviour configuration | LIBRARY LOWER INTERRUPT PRIORITY | 中断最低优先级 | 15 |
(中断嵌套行为配置) | LIBRARY MAX SYSCALL INTERRUPT PRIORITY | FreeRTOS可管理的最高中断优先级 | 5 |
任务创建(Tasks) 和 消息队列(Queues)
任务 和 消息队列的创建,在同一个页面
队列又称消息队列,是一种常用于任务间通信的数据结构
队列可以在任务与任务间、 中断和任务间传递信息
实现了任务接收来自其他任务或中断的不固定长度的消息,任务能够从队列里面读取消息
当队列中的消息是空时,读取消息的任务将被阻塞,用户还可以指定阻塞的任务时间 xTicksToWait
在这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效。
代码生成选项
Default:就是生成正常的函数
As a external:作为一个外部函数
As weak:生成弱函数,函数可以被重写
互斥锁(Mutexes) 和 递归互斥锁(Recursive Mutexes)
递归互斥锁,也称为可重入互斥锁,是一种特殊的互斥锁,允许多次尝试以递归的方式锁定同一资源
普通的互斥锁在同一时间只能被一个线程锁定,且必须在同一线程中解锁相同次数才能实际释放锁
相比之下,递归互斥锁可以被同一个线程多次锁定,只要该线程解锁相同的次数就可以释放锁
这种类型的锁通常用于递归函数中,或者在多个线程可能以未知的顺序锁定和解锁资源的情况下
定时器(Timer) 和 信号量(Semaphore)
定时器是一种硬件或软件机制,可以生成周期性的中断,用于在特定的时间间隔后触发事件
定时器可以设置为一次性触发模式,也可以设置为周期性重复触发模式。
在多任务操作系统中,定时器还用于确定任务的最大执行时间,从而实现任务的实时调度。
信号量是一个重要的同步工具,用于控制多个进程对共享资源的访问,以防止数据的损坏。
信号量维护一个计数器,该计数器在进程申请资源时递减,在进程释放资源时递增。
当计数器的值大于零时,意味着有可用资源,进程可以直接使用;
当计数器的值为零时,进程必须等待,直到有其他进程释放资源。
事件标志组(Events)
高级设置(Advanced settings)
要是不使能的话,就会报如下警告
其他设置(others)
FreeRTOS Heap Usage——FreeRTOS堆使用情况——改不了,看得懂的,可以看这些数据
Include parameters——包括参数——看不懂的不要乱改
生成位置/效果
参数配置(Config parameters)的一系列定义和使能都在 freertos.h文件
创建的任务,消息队列,互斥锁,定时器,信号量,事件标志组等都在 freertos.c文件
这些线程同步方法的具体用法,官网 FreeRTOS 内核开发者文档 有介绍
┈┈┈┈▕▔╲┈┈┈┈┈┈┈ ┈┈┈┈▕▔╲┈┈┈┈┈┈┈ ┈┈┈┈▕▔╲┈┈┈┈┈┈┈┈
┈┈┈┈┈▏▕┈┈┈┈┈┈┈ ┈┈┈┈┈▏▕┈┈┈┈┈┈┈ ┈┈┈┈┈▏▕┈┈┈┈┈┈┈ ┈
┈┈┈┈┈▏ ▕▂▂▂▂▂┈┈┈┈┈┈┈▏ ▕▂▂▂▂▂┈┈┈┈┈┈┈▏ ▕▂▂▂▂▂┈┈┈
▂▂▂▂╱┈┈▕▂▂▂▂▏┈ ▂▂▂▂╱┈┈▕▂▂▂▂▏┈ ▂▂▂▂╱┈┈▕▂▂▂▂▏┈┈
▉▉▉┈┈┈┈▕▂▂▂▂▏ ┈ ▉▉▉┈┈┈┈▕▂▂▂▂▏ ┈ ▉▉▉┈┈┈┈▕▂▂▂▂▏ ┈
▉▉▉┈┈┈┈▕▂▂▂▂▏ ┈ ▉▉▉┈┈┈┈▕▂▂▂▂▏ ┈ ▉▉▉┈┈┈┈▕▂▂▂▂▏ ┈
▔▔▔▔╲▂▂▕▂▂▂▂▏┈ ▔▔▔▔╲▂▂▕▂▂▂▂▏┈ ▔▔▔▔╲▂▂▕▂▂▂▂▏┈┈