FreeRTOS —— 1.FreeRTOS发行版

1.1 本章介绍与适用范围

FreeRTOS以单个zip文件存档的形式分发,其中包含所有正式的FreeRTOS端口以及大量的预配置演示应用程序。

范围

本章旨在通过以下方式帮助用户熟悉FreeRTOS的文件和目录:

  • 提供FreeRTOS目录结构的顶层视图。
  • 描述任何特定的FreeRTOS项目实际上需要哪些文件。
  • 介绍演示应用程序。
  • 提供有关如何创建新项目的信息。

这里的描述仅与FreeRTOS官方发行版有关。 本书随附的示例使用的组织稍有不同。

1.2 了解FreeRTOS发行版

定义:FreeRTOS Port

FreeRTOS可以使用大约二十种不同的编译器来构建,并且可以在三十多种不同的处理器体系结构上运行。 每种受支持的编译器和处理器组合都被视为一个单独的FreeRTOS端口。

构建FreeRTOS

FreeRTOS可以看作是一个库,该库为裸机应用程序提供多任务处理功能。

FreeRTOS作为一组C源文件提供。 一些源文件是所有端口通用的,而其他源文件则是特定于端口的。 将源文件构建为项目的一部分,以使FreeRTOS API可用于您的应用程序。 为了使您轻松进行此操作,每个正式的FreeRTOS端口都随附有一个演示应用程序。 演示应用程序已预先配置为构建正确的源文件,并包括正确的头文件。

演示应用程序应“开箱即用”地构建,尽管某些演示比其他示例要老,并且有时自发布该演示以来对构建工具进行的更改可能会引起问题。 1.3节介绍了演示应用程序。

FreeRTOSConfig.h

FreeRTOS由名为FreeRTOSConfig.h的头文件配置。

FreeRTOSConfig.h用于定制FreeRTOS以在特定应用程序中使用。 例如,FreeRTOSConfig.h包含诸如configUSE_PREEMPTION之类的常量,该常量的设置定义将使用协作调度算法还是抢先式调度算法1。 由于FreeRTOSConfig.h包含应用程序特定的定义,因此它应位于正在构建的应用程序一部分的目录中,而不应位于包含FreeRTOS源代码的目录中。

每个FreeRTOS端口都提供了一个演示应用程序,每个演示应用程序都包含一个FreeRTOSConfig.h文件。 因此,永远不必从头开始创建FreeRTOSConfig.h文件。 相反,建议从使用的FreeRTOS端口提供的演示应用程序使用的FreeRTOSConfig.h开始,然后进行修改。

官方FreeRTOS发行版

FreeRTOS分布在单个zip文件中。 该zip文件包含所有FreeRTOS端口的源代码,以及所有FreeRTOS演示应用程序的项目文件。 它还包含精选的FreeRTOS +生态系统组件和精选的FreeRTOS +生态系统演示应用程序。

不要因FreeRTOS发行版中的文件数量而感到失望! 在任何一个应用程序中只需要很少的文件。

FreeRTOS发行中的顶级目录

FreeRTOS发行版的第一级和第二级目录如图1所示。
在这里插入图片描述
图1. FreeRTOS发行版中的顶级目录

所有端口通用的FreeRTOS源文件

核心FreeRTOS源代码仅包含在所有FreeRTOS端口共有的两个C文件中。 它们分别称为task.clist.c,它们直接位于FreeRTOS / Source目录中,如图2所示。除了这两个文件之外,以下源文件也位于同一目录中:

  • queue.c
    queue.c同时提供队列和信号量服务,如本书稍后所述。 几乎总是需要queue.c。
  • timers.c
    timers.c提供了软件计时器功能,如本书稍后所述。 仅当实际要使用软件计时器时,才需要将其包括在构建中。
  • event_groups.c
    event_groups.c提供事件组功能,如本书稍后所述。 如果实际上要使用事件组,则只需将其包括在构建中。
  • croutine.c
    croutine.c实现了FreeRTOS协同例程功能。 仅当实际要使用协同例程时,才需要将其包括在构建中。 协同例程旨在用于非常小的微控制器,现在很少使用,因此不能保持与其他FreeRTOS功能相同的水平。 本书中没有描述协同例程。

在这里插入图片描述
图2. FreeRTOS目录树中的核心FreeRTOS源文件

人们已经认识到文件名可能会导致名称空间冲突,因为许多项目已经包含了具有相同名称的文件。 但是,人们认为现在更改文件名是有问题的,因为这样做会破坏与使用FreeRTOS的成千上万个项目,自动化工具和IDE插件的兼容性。

特定于端口的FreeRTOS源文件

FreeRTOS端口专用的源文件包含在FreeRTOS / Source / portable目录中。 可移植目录首先通过编译器,然后通过处理器体系结构排列为层次结构。 层次结构如图3所示。

如果您正在使用编译器“ compiler”在具有体系结构“体系结构”的处理器上运行FreeRTOS,则除了核心FreeRTOS源文件之外,还必须构建FreeRTOS / Source / portable / [compiler] / [architecture]中的文件。 目录。

如第二章“堆内存管理”中所述,FreeRTOS还认为堆内存分配是可移植层的一部分。 使用FreeRTOS版本低于V9.0.0的项目必须包含堆内存管理器。 从FreeRTOS V9.0.0起,仅当FreeRTOSConfig.h中的configSUPPORT_DYNAMIC_ALLOCATION设置为1或未定义configSUPPORT_DYNAMIC_ALLOCATION时,才需要堆内存管理器。

FreeRTOS提供了五个示例堆分配方案。 这五个方案分别命名为heap_1至heap_5,并由源文件heap_1.c至heap_5.c实现。
分别。 示例堆分配方案包含在FreeRTOS / Source / portable / MemMang目录中。 如果您已经配置了FreeRTOS以使用
动态内存分配,则有必要在项目中构建这五个源文件之一,除非您的应用程序提供了替代实现。
在这里插入图片描述
图3.在FreeRTOS目录树中移植特定于源文件

包含路径

FreeRTOS要求在编译器的包含路径中包含三个目录。 这些都是:

1.核心FreeRTOS头文件的路径,该路径始终为FreeRTOS / Source / include。
2.特定于所使用的FreeRTOS端口的源文件的路径。 如上所述,这是FreeRTOS / Source / portable / [compiler] / [architecture]。
3. FreeRTOSConfig.h头文件的路径。

头文件

使用FreeRTOS API的源文件必须包含“ FreeRTOS.h”,后跟包含所用API函数原型的头文件-“ task.h”,“ queue.h”,“ semphr.h” ,“ timers.h”或“ event_groups.h”。

1.3 演示应用

每个FreeRTOS端口都至少带有一个演示应用程序,该应用程序应在构建时不产生任何错误或警告,尽管某些演示程序比其他示例程序要早,并且有时自发布该演示程序以来对构建工具进行的更改可能会引起问题。

给Linux用户的注释:FreeRTOS是在Windows主机上开发和测试的。 有时,在Linux主机上构建演示项目时,会导致构建错误。 生成错误几乎总是与引用文件名时使用字母的情况或文件路径中使用斜杠字符的方向有关。 请使用FreeRTOS联系表格(http://www.FreeRTOS.org/contact)提醒我们任何此类错误。

该演示应用程序具有以下目的:

  • 提供一个正在运行且已预先配置的项目的示例,其中包括正确的文件和正确的编译器选项集。
  • 以最少的设置或先验知识即可进行“开箱即用”的实验。
  • 作为如何使用FreeRTOS API的演示。
  • 作为创建实际应用程序的基础。

每个演示项目都位于FreeRTOS / Demo目录下的唯一子目录中。 子目录的名称表示演示项目所涉及的端口。

FreeRTOS.org网站上的网页还描述了每个演示应用程序。 该网页包含有关以下内容的信息:

  • 如何在FreeRTOS目录结构中找到演示的项目文件。
  • 项目配置为使用哪种硬件。
  • 如何设置用于运行演示的硬件。
  • 如何构建演示。
  • 演示的预期行为。

所有演示项目都创建了常见演示任务的子集,其实现包含在FreeRTOS / Demo / Common / Minimal目录中。 常见的演示任务纯粹是为了演示FreeRTOS API的使用方式-嘿,它没有实现任何特定的有用功能。

最近的演示项目也可以构建初学者的“闪灯”项目。 闪灯的项目是非常基本的。 通常,他们将仅创建两个任务和一个队列。

每个演示项目都包含一个名为main.c的文件。 它包含main()函数,从中创建所有演示应用程序任务。 有关该演示的特定信息,请参见各个main.c文件中的注释。

FreeRTOS / Demo目录层次结构如图4所示。
在这里插入图片描述

图4.演示目录层次结构

1.4 创建一个FreeRTOS项目

改编其中一个演示项目

每个FreeRTOS端口都至少带有一个预配置的演示应用程序,该应用程序应无错误或警告地构建。 建议通过改编这些现有项目之一来创建新项目; 这将使项目包含正确的文件,正确的中断处理程序以及正确的编译器选项集。

要从现有演示项目中启动新应用程序,请执行以下操作:

  1. 打开提供的演示项目,并确保它可以按预期构建和执行。
  2. 删除定义演示任务的源文件。 可以从项目中删除位于Demo / Common目录中的任何文件。
  3. 删除main()中除prvSetupHardware()和vTaskStartScheduler()之外的所有函数调用,如清单1所示。
  4. 检查项目直到构建。

按照这些步骤将创建一个项目,其中包括正确的FreeRTOS源文件,但未定义任何功能。

在这里插入图片描述

清单1.一个新的main()函数的模板

从头开始创建新项目

如前所述,建议从现有的演示项目中创建新项目。 如果不希望这样做,则可以使用以下过程创建一个新项目:

  1. 使用您选择的工具链,创建一个尚未包含任何FreeRTOS源文件的新项目。
  2. 确保可以构建新项目,将其下载到目标硬件并执行。
  3. 仅当您确定已经有一个正常的项目时,才将表1中详细说明的FreeRTOS源文件添加到该项目中。
  4. 将为正在使用的端口提供的演示项目所使用的FreeRTOSConfig.h头文件复制到项目目录中。
  5. 将以下目录添加到项目将搜索以查找头文件的路径:
  • FreeRTOS/Source/include
  • FreeRTOS/Source/portable/[compiler]/[architecture] (where [compiler] and [architecture] are correct for your chosen port)
  • The directory containing the FreeRTOSConfig.h header file
  1. 从相关的演示项目中复制编译器设置。
  2. 安装任何可能需要的FreeRTOS中断处理程序。 使用描述正在使用的端口的网页以及为正在使用的端口提供的演示项目作为参考。
    在这里插入图片描述
    使用FreeRTOS版本低于V9.0.0的项目必须构建heap_n.c文件之一。 从FreeRTOS V9.0.0起,仅当FreeRTOSConfig.h中的configSUPPORT_DYNAMIC_ALLOCATION设置为1或未定义configSUPPORT_DYNAMIC_ALLOCATION时,才需要heap_n.c文件。 有关更多信息,请参见第2章,堆内存管理。

1.5 数据类型和编码样式指南

数据类型

FreeRTOS的每个端口都有一个唯一的portmacro.h头文件,其中包含(除其他外)两个端口特定数据类型的定义:TickType_t和BaseType_t。 这些数据类型在表2中进行了描述。

表2. FreeRTOS使用的端口特定的数据类型

使用宏或typedef实际类型
TickType_tFreeRTOS配置了一个周期性的中断,称为滴答中断。自FreeRTOS应用程序启动以来发生的滴答中断次数称为滴答计数。 滴答计数用作时间量度。两个滴答中断之间的时间称为滴答周期。 时间指定为滴答周期的倍数。TickType_t是用于保存刻度计数值和指定时间的数据类型。TickType_t可以是无符号的16位类型,也可以是无符号的32位类型,这取决于FreeRTOSConfig.h中的configUSE_16_BIT_TICKS的设置。 如果configUSE_16_BIT_TICKS设置为1,则TickType_t被定义为uint16_t。 如果configUSE_16_BIT_TICKS设置为0,则TickType_t被定义为uint32_t。使用16位类型可以大大提高8位和16位体系结构的效率,但严重限制了可以指定的最大块周期。 没有理由在32位体系结构上使用16位类型。
BaseType_t始终将其定义为体系结构中最有效的数据类型。 通常,在32位体系结构上为32位类型,在16位体系结构上为16位类型,而在8位体系结构上为8位类型。BaseType_t通常用于只能接受非常有限的值范围的返回类型,以及用于pdTRUE / pdFALSE类型的布尔值。

一些编译器使所有不合格的char变量都无符号,而另一些使它们带符号。 由于这个原因,除非使用char来保存ASCII字符或使用指向char的指针来指向字符串,否则FreeRTOS源代码明确地将char的每次使用都限定为“ signed”或“ unsigned”。

普通的int类型未使用。

变量名

变量以其类型为前缀:'c’表示char,'s’表示int16_t(short),'l’表示int32_t(long),'x’表示BaseType_t和任何其他非标准类型(结构,任务句柄,队列) 手柄等)。

如果变量是无符号的,则它也以’u’为前缀。 如果变量是指针,则它也以“ p”为前缀。 例如,uint8_t类型的变量将以“ uc”作为前缀,而char类型指针的变量将以“ pc”作为前缀。

函数名称

函数以返回的类型和在其中定义的文件为前缀。 例如:

  • vTaskPrioritySet()返回空值,并在task.c中定义。
  • xQueueReceive()返回类型为BaseType_t的变量,并且在queue.c中定义。
  • pvTimerGetTimerID()返回指向void的指针,并在timers.c中定义。

文件范围(专用)功能的前缀为“ prv”。

格式设定

一个制表符始终设置为等于四个空格。

宏名称

大多数宏均以大写形式编写,并以小写字母作为前缀,以指示在何处定义了宏。 表3提供了前缀列表。

表3.宏前缀

词头宏定义的位置
port (for example, portMAX_DELAY)portable.h or portmacro.h
task (for example, taskENTER_CRITICAL())task.h
pd (for example, pdTRUE)projdefs.h
config (for example, configUSE_PREEMPTION)FreeRTOSConfig.h
err (for example, errQUEUE_FULL)projdefs.h

请注意,信号量API几乎完全作为一组宏编写,但遵循函数命名约定,而不是宏命名约定。

表4中定义的宏在整个FreeRTOS源代码中使用。

表4.通用宏定义

MacroValue
pdTRUE1
pdFALSE0
pdPASS1
pdFAIL0

过度类型转换的理由

FreeRTOS源代码可以用许多不同的编译器进行编译,所有这些编译器在生成警告的方式和时间方面都不同。 特别是,不同的编译器希望以不同的方式使用强制转换。 结果,FreeRTOS源代码包含的类型转换比正常情况下要保证的要多。


  1. 调度算法在3.12节中介绍。 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值