FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。由于RTOS需占用一定的系统资源(尤其是RAM资源),只有μC/OS-II、embOS、salvo、FreeRTOS等少数实时操作系统能在小RAM单片机上运行。相对μC/OS-II、embOS等商业操作系统,FreeRTOS操作系统是完全免费的操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行。 –百度百科
FreeRTOS由Real Time Engineers有限公司独家拥有、开发和维护。是一个长期维护的开源软件。有开源免费版,也有商业授权版。
在FreeRTOS中,每个执行线程被称为“任务”。FreeRTOS通过调度策略以及任务的优先级的共同配合完成多任务的调度与切换。
Pre-emptive or co-operative operation (具有抢占式调度 、 合作调度模式)
Very flexible task priority assignment (具有非常灵活的任务优先级分配方式)
Flexible, fast and light weight task notification mechanism (灵活,快速与轻量化的任务通知机制)
Queues (队列)
Binary semaphores (二进制信号量)
Counting semaphores (计数型信号量)
Mutexes (互斥锁)
Recursive Mutexes (递归互斥锁)
Software timers (软件定时器)
Event groups (事件组)
Tick hook functions (tick 勾子函数)
Idle hook functions (空闲勾子函数)
Stack overflow checking (栈溋出检测)
Trace recording (跟踪记录调试功能)
Task run-time statistics gathering (任务的运行时统计)
Optional commercial licensing and support (可选的商业许可和支持)
Full interrupt nesting model (for some architectures) (针对一些平台的全中断嵌套模型)
A tick-less capability for extreme low power applications (适用于极低功耗应用的无tick功能)
Software managed interrupt stack when appropriate (this can help save RAM) (软件管理中断堆栈)
从官网的链接中https://freertos.org/index.html中去下载FreeRTOS发行版是一个压缩包:如图
解压后的目录结构如下:
上图的红框部分是主要的库文件(上方的event_groups.c也是),include包含了所有的头文件的目录。portable是移植到不同平台的对应文件目录。
以上是标准的FreeRTOS目录文件,相当的精简。当需要移植到不同编译环境和适配不同MCU平台时,需要使用的portable这个目录里对应的文件。具体内容可以打开目录看一下。
由于本文的环境是ESP32,乐鑫已经针对ESP32平台做了FreeRTOS的移植和适配。因此,这里的不需要另外下载。在安装完ESP-IDF环境后,就已经自带了FreeRTOS了。在这里我们为了区分原生的FreeRTOS和ESP32的FreeRTOS,延用乐鑫的叫法,把原生的FreeRTOS叫做Vanilla FreeRTOS,ESP32里的叫做ESP-IDF FreeRTOS。
为了集中注意力理清FreeRTOS的逻辑,不再针对ESP32以外的平台的移植相关内容进行展开。
文件名 | 说明 |
---|---|
task.c | 任务相关的库文件,完成任务的操作的函数集 |
list.c | 链表操作相关的库文件,链表是FreeRTOS里重要的数据结构,相应的操作函数在这个库里 |
queue.c | 队列和信号量相关的库文件。实现队列与信号量的操作函数 |
timers.c | 软件定时器相关的库文件。 |
event_groups.c | 事件组相关的库文件。 |
使用 FreeRTOS API 的源文件必须包含“FreeRTOS.h”,后跟包含正在使用的 API 函数原型的头文件——“task.h”、“queue.h”、“semphr.h”、“timers.h”或“event_groups.h”。
官方原文里对FreeRTOSConfig.h文件的使用要求如下:
FreeRTOS由一个名为FreeRTOSConfig.h的头文件配置。FreeRTOSConfig.h用于定制特定应用程序中使用的FreeRTOS。例如,FreeRTOSConfig.h包含诸如configUSE_PREEMPTION之类的常量,其设置定义将使用协作调度算法还是抢占调度算法。因为FreeRTOSConfig.h包含特定于应用程序的定义,它应该位于正在构建的应用程序的一部分目录中,而不是包含FreeRTOS源代码的目录中。
在ESP32,基本无需配置这个文件(这个文件在/esp/esp-idf/components/freertos/include/esp_additions/freertos/FreeRTOSConfig.h),这些设置里有一部分由ESP-IDF中的menuconfig这个功能对所有涉及到的内容时行配置的,使用起来会更加的直观和便利。这就是ESP32适配完FreeRTOS的使用上的区别。
以下为官方原文
1、 FreeRTOS 配置了一个称为滴答(tick)中断的周期性中断。
2、自 FreeRTOS 应用程序启动以来发生的滴答中断次数称为滴答计数(tick count)。滴答计数用作时间的度量。
两个滴答中断之间的时间称为滴答周期。时间被指定为tick周期的倍数。TickType_t 是用于保存滴答计数值的数据类型,并用于指定时间。
TickType_t可以是无符号16位类型或无符号32位类型,具体取决于FreeRTOSConfig.h中configUSE_16_bit_TICKS的设置。如果configUSE_16BIT_TICKS设置为1,则TickType_t定义为uint16_t。如果configUSE_16_BIT_TICKS设置为0,则TickType_t定义为uint32_t。
使用16位类型可以大大提高8位和16位架构的效率,但严重限制了可以指定的最大块周期。没有理由在32位体系结构上使用16位类型。
解释:
由于FreeRTOS是可以面向不同的平台的RTOS,因此在时间的计量上,独立于平台通过一个自定义的tick中断来实现不同平台下的统计计时。这个中断的周期做为计时的基础来转换成时间。定义的这个重要的基础数据类型TickType_t本质就是一个32位(现在基本都是32位的MCU了)的无符号整数。时间的内部表达就是从开机到现在经历了多少个tick中断。也即TickType_t类型用于保存tick中断的次数。
这样系统的时间内部表示就在不同的平台有了一个统一的标准,就是tick中断次数。但是这样做毕竟不利于开发者控制时间,因此我们习惯的时间表达方式是秒,毫秒等。这个要和tick中断次数如何表达呢。这里系统提供了很多多转换的宏,如pdMS_To_TICKS(毫秒)(宏pdMS_TO_TICKS()能被用于转换毫秒到ticks)等,来实现我们习惯的时间与系统计时单位的转换。
以下为官方原文
这总是被定义为架构中最有效的数据类型。通常,这是32位体系结构上的32位类型,16位体系结构中的16位类型,以及8位体系结构的8位类型。
BaseType_t通常用于只能接受非常有限的值范围的返回类型,以及pdTRUE/pdFALSE类型的布尔值。
解释:
这个数据类型简单理解就是FreeRTOS里定义的用于标准化返回值的一个数据类型。为了规避不同编译系统可能给true或false带来的不同定义,所以FreeRTOS官方通过这个BaseType_t类型来统一返回类型为pdTRUE 或 pdFALSE。
变量名称
变量以其类型为前缀:“c”表示char,“s”表示int16_t(短),“l”表示int32_t(长),“x”表示BaseType_t和任何其他非标准类型(结构、任务句柄、队列句柄等)。
如果变量是无符号的,它也会以“u”作为前缀。如果变量是指针,它也会以“p”作为前缀。例如,uint8_t类型的变量将以“uc”为前缀,而指向char的指针类型的变量则以“pc”为前缀。
函数名称
函数以返回的类型和在其中定义的文件为前缀。例如:
vTaskPrioritySet()返回一个void,并在task.c中定义。
xQueueReceive()返回BaseType_t类型的变量,并在queue.c中定义。
pvTimerGetTimerID()返回指向void的指针,并在timer.c中定义。
文件范围(专用)函数前缀为“prv”。
关于FreeRTOS的介绍,内容比较多,也比较杂,相互之前的逻辑性也不是很强。初学FreeRTOS一时对这些内容的不易理解也正常。但这些内容是必须要了解和知道的。然后在接下来的学习中,自然而然就明白了。因为在接下来的各个知识块里都会有这些相关联的内容。因此在这里所有的知道只能点到为止。