编辑推荐: |
本文主要介绍了FreeRTOS入门相关内容。 希望对你的学习有帮助。
本文来自于GitCode 开源社区,由火龙果软件Linda编辑、推荐。 |
|
各位看官好,欢迎大家进入新的专栏学习,从今天开始,正式进入FreeRTOS的学习,这是专门应用于嵌入式领域的一款实时操作系统,相比裸机,它有很大的优势,实际开发中应用广泛,为此,我们应该首先掌握最基本的内容,理解实时操作系统的实时性是通过哪些机制实现的?相比裸机开发,它的优势在哪里?这样更加有利于我们运用好FreeRTOS来解决生活中问题。
一、RTOS入门
1.0 裸机与RTOS的举例对比
为了初步感知裸机与实时操作系统的区别与优势,我们这里简单的举个例子,通过例子来理解二者。
正如上面图片所示,有一个人正在打游戏,这时候有人给他发消息,两件事的优先级相同,对于裸机系统而言,它必须等打完游戏才能去回复消息,每个任务是按照程序编写的顺序执行的。
裸机处理方式:打游戏和回复信息,需要打完游戏才可回复信息,或者回复完信息才可打游戏
而对于RTOS它又是怎么处理的呢?它会将每件事独立构成一个任务(这个任务函数是无返回值并且是死循环),然后以系统滴答定时器的时钟作为一个时间片即1ms,
每隔1ms去做另一个任务,在这两个任务之间切换,微观上看,我们的两个任务是按照顺序依次执行的,但是,由于1ms时间非常短,宏观上看,我们人眼根本分辨不出来,因此这两个任务其实就是并发运行的(一个时间片只有一个任务在执行),这样就不存在等待。
RTOS处理方式:打游戏和回复信息,不需要等某一件事做完,可每间隔1ms(一个时间片时钟节拍),然后交替做这两件事,因为速度很快,从宏观的意义上来看,类似同步执行!
同样的场景,假设此时小明肚子疼了,要去医院,即这时出现了更高优先级的任务,此时裸机与RTOS又会怎么做呢?
回忆Stm32裸机开发,我们其实是利用中断处理的,设立一个标志位,中断条件触发,标志位改变,判断标志位,然后去执行中断处理服务函数,在这里也是这样,肚子疼就相当于一个中断,一旦发生,就要立马去医院,但是它存在一个问题:首先,中断只能处理简单的短时间的任务,不能在中断里停留较长的时间,其次,如上图所示,去医院必须要等打游戏和回复信息,两件事完成,才会去判断,而这两件事又是需要一定的时间的,缺乏一种实时性的处理能力!
如上图RTOS的处理方式,它将去医院看病这件事设置成更高的优先级,前面两件事优先级相同,当去医院这件事发生后,首先就去执行它,前面两件事不进行处理,并且,实现试想生活中,去医院途中要打车,坐车,...各种事消耗时间,在程序里面就是延时,在裸机开发中,延时的时候CPU什么也不做,处于一种空转的状态,而在RTOS中,它并不是这样,延时的时候,CPU会去做低优先级的任务,即前面两件事,等这段时间过去后,到了医院门口,回来接着去看病,这样的优势在于它充分的利用了CPU的资源,不让CPU停下来,一直在不同的任务之间进行切换。
1.1 裸机与RTOS介绍
1.1.1 裸机
1.1.1.1概念
裸机:直接对硬件资源的编程,所有功能函数放在主循环中,同⼀时间只能单⼀任务运行。裸机又称为前后台系统,前台系统指的中断服务函数,后台系统指的大循环,即应用程序。
1.1.1.2特点
可以看出来:裸机系统是轮流执行的,因此必须等一个任务完成才能完成下一件任务,这带来的后果就是:实时性差,当处于延时的时候,CPU处于一种空转的状态,这样会浪费CPU的资源
,此外,所有实现的功能都放在死循环里面,如果任务非常多,将导致结构非常臃肿!
1.1.1.3 图示
1.1.2 RTOS
1.1.2.1 RTOS的概念
RTOS 全称是 Real Time Operating System,中文名就是实时操作系统,强调的是:实时性。
1.1.2.2 RTOS的特点
RTOS实现功能划分为多个任务,并且在延时的时候,不会空等待,会让出CPU的使用权给其他任务,即任务调度,这是操作系统内部自己实现的调度算法,高优先级任务抢占低优先级任务,同一优先级任务按照时间片轮转的方式执行,为了保证高优先级任务执行完后,低优先级不用再重新开始执行,每个任务都有自己的栈空间,用于保存局部变量以及任务的上下文信息。
1.1.2.3 图示
可以看出:每个任务都是一个死循环,这是为了保证能够高优先级执行完后,能够继续执行低的优先级任务,如果低优先级任务执行到一半,被高优先级任务打断,低优先级任务不是死循环,那就执行不了低优先级的任务了。
注意两点:
1、任务可以是同等优先级的;
2、中断可以打断任意任务;
思考:如果高优先级的任务一直在运行,会怎么样?
如果高任务的优先级里面没有延时函数,那么,它就不会让出CPU的使用权,并且高优先级任务是死循环的,它将会一直执行下去,使得低优先级任务无法运行!!!
1.2 FreeRTOS简介
RTOS是指一类系统,如 FreeRTOS,uC/OS,RTX,RT-Thread 等,都是 RTOS
类操作系统。FreeRTOS 是一个免费的嵌入式实时操作系统,其开源、轻量级、可移植的特点使其成为许多嵌入式开发者的首选。在近几年的使用排名上位居前列。
FreeRTOS的特点:
学习资料:
FreeRTOS官网:https://www.freertos.org/和FreeRTOS教程指南以及课程源码。
二、FreeRTOS基础知识(非常重要)
2.1 任务调度简介
2.1.1 概念
一个处理器核心在某一时刻只能运行一个任务,如果在各个任务之间迅速切换,这样看起来就像多个任务在同时运行。操作系统中任务调度器的责任就是使用相关的调度算法来决定当前时刻要执行哪个任务。
2.1.2 实现方式
FreeRTOS 一共支持三种任务调度方式:
2.1.3 抢占式调度
总结:
高优先级任务,优先执行;
高优先级任务不停止,低优先级任务无法执行,除非高优先级的任务进入阻塞态或者被挂起,这时便会让出CPU的使用权给就绪态中最高的优先级任务使用,运行它;
被抢占的任务将会进入就绪态;
2.1.4 时间片调度
同等优先级任务轮流地享有相同的 CPU 时间(可设置,指的是SysTick中断周期), 叫时间片,在FreeRTOS中,一个时间片就等于SysTick
中断周期,即相同优先级任务轮转运行的时间为一个时间片,时间片的持续时间可以由中断周期进行设置改变。我们代码通常用的的是1ms.
总结:
同等优先级任务,轮流执行;时间片流转;
一个时间片大小,取决于滴答定时器中断周期;
注意没有用完的时间片不会再使用,下次任务Task3得到执行,还是按照一个时间片的时钟节拍运行;
2.2 任务状态
2.2.1 任务状态基本知识
FreeRTOS中任务共存在4种状态:
2.2.2 四种任务状态的转换图
四种任务状态之间的转换图如下:
总结:
仅就绪态可转变成运行态;
其他状态的任务想运行,必须先转变成就绪态;
当运行态的任务被挂起或者阻塞时,就会找就绪态中优先级最高的任务去执行;同理,就绪态中的任务出现比运行态任务优先级还高,那么,这个就绪态任务就会抢占运行态任务;
2.2.3 任务状态列表
FreeRTOS中无非就四种状态,运行态,就绪态、阻塞态、挂起态,这四种状态中,除了运行态,其他三种任务状态的任务都有其对应的任务状态列表
,列表类似于链表,非常重要!后面章节会专门介绍。处于不同状态的任务就会被挂载到不同的列表下面。前面学习,我们知道,只有就绪态可以直接成为运行态,其他的状态都不可以,因此,只有将任务挂载到就绪列表中,才能变为运行态!阻塞态和挂起态只有先挂载到就绪列表才能成为运行态。我们任务调度器总是在所有处于就绪列表的任务中,选择具有最高优先级的任务来执行。并且,新创建的任务会直接挂载到就绪列表中的!
以就绪列表为例。如果在32位的硬件中,会保存一个32位的变量,代表0-31的优先级。当某个位,置一时,代表所对应的优先级就绪列表有任务存在。如果有多个任务优先级相同,会连接在同一个就绪列表上:
2.2.4 举例理解列表随着任务状态的变化
假设,创建三个任务分别是:task1、task2、task3,优先级分别是:1、2、3
一开始,任务调度器会去就绪列表中找优先级最高的任务执行,也就是任务3,此时任务3会成为运行态,标志位为0,如果任务3由于延时,它会发生阻塞,这时它会被挂载到阻塞列表下,任务调度器会再次去就绪列表中最高的优先级去执行,也就是任务2,此时任务2会成为运行态,它的标志位也为0,如果任务2被挂起,那么此时,任务2就会被挂载到挂起列表下面,任务调度器会再次去就绪列表中最高的优先级去执行,也就是任务1,此时任务1会成为运行态,它的标志位也为0,运行一段时间,发现任务3,阻塞解除(延时时间到了或者信号量接收到了),任务3会重新回到就绪列表,任务调度器会再次去就绪列表中找优先级最高的任务执行,也就是任务3,此时任务3会成为运行态。
任务调度器总是在所有处于就绪列表的任务中,选择具有最高优先级的任务来执行,如果task1、task2、task3,优先级相同均为1,则会进行时间片的流转调度方式。
三、FreeRTOS移植
3.1 获取FreeRTOS源码
官网地址:https://www.freertos.org/可选择当前最新的202212.01版本下载
3.2 源码结构介绍
3.2.1 源码整体结构
3.2.2 FreeRTOS文件夹结构
3.2.3 Source文件夹结构如下
include 文件夹和.c 文件是通用的头文件和 C 文件,这两部分的文件适用于各种编译器 和处理器,是通用的。标红的是移植必需的,其他.c
文件根据需要选取。
3.2.4 portable文件夹结构
FreeRTOS操作系统归根到底是一个软件层面的东西,那FreeRTOS是如何跟硬件联系在一起的呢?portable文件夹里面的东西就是连接桥梁.portable
文件夹里根据编译器、内核等实际环境对应选取。由于我们使用 MDK 开发,因此这里只重点介绍其中的部分移植文件。
Keil文件夹里只有一个 See-also-the-RVDS-directory.txt,意思是让我们看RVDS
文件夹。
3.2.4.1 RVDS 文件夹
RVDS 文件夹包含了各种处理器相关的文件夹,FreeRTOS 是一个软件,单片机是一个硬件,FreeRTOS
要想运行在一个单片机上面,它们就必须关联在一起。 关联还是得通过写代码来关联,这部分关联的文件叫接口文件,通常由汇编和
C语言联合编写。这些接口文件都是跟硬件密切相关的,不同的硬件接口文件是不一样的,但都大同小 异。编写这些接口文件的过程我们就叫移植,移植的过程通常由
FreeRTOS 和 mcu 原厂的 人来负责,移植好的这些接口文件就放在 RVDS 这个文件夹的目录下。
FreeRTOS 为我们提供了 cortex-m0、m3、m4 和 m7 等内核的单片机的接口文件,根
据 mcu 的内核选择对应的接口文件即可。其实准确来说,不能够叫移植,应该叫使用官方 的移植, 因为这些跟硬件相关的接口文件,RTOS
官方都已经写好了,我们只是使用而已。以 ARM_CM3 这个文件夹为例,里面只有“port.c”与“portmacro.h”
两个文件:
port.c 文件:里面的内容是由 FreeRTOS 官方的技术人员为 Cortex-M3 内核的处理器写的接口文件,里面核心的上下文切换代码是由汇编语言编写而成,对技术员的要求比
较高,我们只是使用的话只需拷贝过来用即可。
portmacro.h 文件:port.c 文件对应的头文件,主要是一些数据类型和宏定义。
3.2.4.2 MemMang 文件夹
MemMang 文件夹下存放的是跟内存管理相关的,总共有五个 heap 文件以及一个 readme
说明文件。
这五个 heap 文件在移植的时候必须使用一个,因为 FreeRTOS 在创建内核对象的时候使用的是动态分配内存,而这些动态内存分配的函数则在这几个文件里面实现,不同的分配算法会导致不同的效率与结果,后面在内存管理中我们会讲解每个文件的区别,由于现在是初学,所以我们选用
heap4.c 即可。
3.3 FreeRTOS手把手移植(掌握)
1)在本地⼯程⽂件夹中新建两个文件:
2)将Source(源码)下的.c⽂件 和 include⽂件中的.h⽂件(头文件)复制到 Free
RTOS_CORE中
3)将FreeRTOSv202212.00\FreeRTOS\Source\portable\RVDS\ARM_CM4F下⾯的⽂件复制到Free
RTOS_PORT 中 将FreeRTOSv202212.00\FreeRTOS\Source\portable\MemMang中的heap_4c也复制进来。
4)添加FreeRTOSConfig.h⽂件:FreeRTOSConfig.h
是 FreeRTOS 的配置⽂件,通过此⽂件来实现对内核的裁剪。 获取配置⽂件:(1)自己编写(难度有点⼤)(2)从官方给的DEMO⽂件中获取
在我们的⼯程中添加⼀个⽂件夹⽤来存放系统配置文件(FreeRTOSConfig.h)
编译我们的工程
3.3 最终修改成功的config⽂件
3.4 系统配置文件说明
FreeRTOSConfig.h 配置文件作用:对FreeRTOS的功能进行配置和裁剪,以及API函数的使能等
相关宏大致可分为三类:
四、移植测试
至此,FreeRTOS入门结束,相对于裸机开发虽然更加方便了,但也对于程序的控制带来一定的难度,初次学习,循序渐进,一步步掌握即可!
|