您的位置:58编程 > freertos详解 卷2:第3章 FreeRTOS

freertos详解 卷2:第3章 FreeRTOS

2023-03-11 15:33 开源软件架构

freertos详解 卷2:第3章 FreeRTOS

freertos详解

FreeRTOS是一款嵌入式实时操作系统,它是一个小型的、可扩展的、可靠的、实时的操作系统,用于在微控制器上运行多任务应用。FreeRTOS可以在很多不同的处理器上运行,包括ARM Cortex-M、ARM7/9、X86、MIPS等。

FreeRTOS最大的特点就是它能够让开发者快速地将应用移植到不同的平台上,而且它也能够帮助开发者快速地解决多任务间的协调问题。FreeRTOS有一个核心部分,也就是内核(Kernel);内核负责任务调度、中断服务函数、时间片轮询以及其他一些低级别的服务。


#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h" 

FreeRTOS内核包含了四个重要部分:任务(Task)、队列(Queue)、信号量(Semaphore)和时钟/计时器(Clock/Timer)。这四个部分都是由内核来控制和协调的。

任务(Task)是FreeRTOS中最重要的部分之一,它代表了应用中不同子系统或者子任务之间相互独立运行的单元。每个任务都有一个优先级(Priority)来表明它相对于其它任务耗时或者优先性。当一个新任务准备好执行时,内核会将其放在就绪队列中并根据优先级来执行该任务。

   
 xTaskCreate( vTaskFunction,  
              "TaskName",     
              1000,           
              NULL,           
              1,              
              NULL );           

队列(Queue)是FreeRTOS中用来在不同任务之间传递数据或者信号量的数据类型。当一个任务想要将数据传递给另一个任务时,就可以使用队列来实现这一目标。当然也可以使用信号量来实现这一目标;但是信号量不能存储数据而队列却能够存储数据。

  
 xQueueCreate( 10,         								    sizeof( int ) );    

信号量(Semaphore)也是FreeRTOS中常用的数据类型之一;它能够帮助开发者快速地解决多个不同子系統之间协作或者竞争问题。信号量也能够带来县划思想中“生产者- 消费者”问题的解决方法。

   xSemaphoreCreateBinary(); 

卷2:第3章 FreeRTOS

FreeRTOS(读作"free-arr-toss")是一个嵌入式系统使用的开源实时操作系统。FreeRTOS被设计为“小巧,简单,和易用”,能支持许多不同硬件架构以及交叉编译器。

FreeRTOS自2002年Richard Barry开始开发以来,一直都在积极开发中。至于我,我不是FreeRTOS的开发人员或贡献者,我只不过是一个最终用户和爱好者。因此,这章将着重与FreeRTOS架构之“是什么”和“怎么做”,而相对本书其他章节来说,较少去讲“为什么”。

就像所有操作系统一样,FreeRTOS的主要工作是执行任务。大部分FreeRTOS的代码都涉及优先权、调度以及执行用户自定义任务。但又与所有其他操作系统不同,FreeRTOS是一款运行在嵌入式系统上的实时操作系统。

到本章结束,我希望你可以了解FreeRTOS的基本架构。大部分FreeRTOS致力于执行任务,所以你可以很好地看到它究竟是如何做到的。

如果这是你首次去深入了解一个操作系统,我还是希望你可以学习到最基本的操作系统是如何工作的。FreeRTOS是相对简单的,特别是相比Windows,linux,或者OS X而言,不过所有操作系统都有着相同的概念和目标,所以不论学习哪个操作系统都是有启发和有趣的。

3.1 什么是“嵌入式”和“实时”?

“嵌入式”和“实时”对于不同的人来说代表不同的理解,所以让我们像FreeRTOS用户那样来定义它们。

嵌入式系统就是一个专门设计用来做一些简单事情的计算机系统,就像是电视遥控器,车载GPS,电子手表,或者起搏器这类。嵌入式系统比通用计算机系统显著的区别在于更小和更慢,通常也更便宜。一个典型的低端嵌入式系统可能有一个运行速度为25MHz的8位CPU,几KB的内存,和也许32KB的闪存。一个高端的嵌入式系统可能有一个运行速度为750MHz的32位CPU,一个GB左右的内存,和几个GB的闪存。

实时系统是设计去完成一定时间内的事,它们保证这些事是在应该做的时候去做。

心脏起搏器是实时嵌入式系统的一个极好例子。起搏器必须在正确的时间收缩心肌,以挽救你的生命;它不能够太忙而没有及时响应。心脏起搏器以及其他的实时嵌入式系统都必须精心设计,以便在任何时刻都能及时执行它们的任务。

3.2架构概述

FreeRTOS是一个相对较小的应用程序。最小化的FreeRTOS内核仅包括3个(.c)文件和少数头文件,总共不到9000行代码,还包括了注释和空行。一个典型的编译后(二进制)代码映像小于10KB。

FreeRTOS的代码可以分解为三个主要区块:任务,通讯,和硬件接口。

●任务:大约有一半的FreeRTOS的核心代码用来处理多数操作系统首要关注的问题:任务。任务是给定优先级的用户定义的C函数。task.c和task.h完成了所有有关创建,调度,和维护任务的繁重工作。

●通讯:任务很重要,不过任务间可以互相通讯则更为重要!它给我们带来FreeRTOS的第二项任务:通讯。大约40%的FreeRTOS核心代码是用来处理通讯的。queue.cqueue.h是负责处理FreeRTOS的通讯的。任务和中断使用队列互相发送数据,并且使用信号灯和互斥来发送临界资源的使用情况。

●硬件接口:接近9000行的代码拼凑起基本的FreeRTOS,是硬件无关的;相同的代码都能够运行,不论FreeRTOS是运行在不起眼的8051,还是最新、最炫的ARM内核上。大约有6%的FreeRTOS的核心代码,在硬件无关的FreeRTOS内核与硬件相关的代码间扮演着垫片的角色。我们将在下个部分讨论硬件相关的代码。

硬件注意事项

硬件无关的FreeRTOS层在硬件相关层之上。硬件相关层声明了你选择什么样的芯片架构。图3.1显示了FreeRTOS的各层。

一个阻塞任务——叫它任务A——将保持阻塞只要它的插入/移除操作没有完成,并且它的超时(如果存在)没有过期。如果一个中断或者另一个任务编辑了这个队列以便任务A的操作能够完成,任务A将被解除阻塞。如果此时任务A的队列操作仍然是允许的,那么它实际上会执行操作,于是任务A会完成它的队列操作,并且返回“成功”的状态。不过,任务A正在执行的那个时间,有可能同时有一个高优先级任务或者中断也在同一个队列上执行另一个操作,这会阻止任务A正在执行的操作。在这种情况下任务A将检查它的超时,同时,如果它未超时就恢复阻塞,否则就返回队列操作“失败”的状态。

特别需要注意的是,当任务被阻塞在一个队列时,系统保持运行所带来的风险;以及当任务被阻塞在一个队列时,有其他任务或中断在继续运行。这种阻塞任务的方法能不浪费CPU周期,使其他任务和中断可以有效地使用CPU周期。

FreeRTOS使用xTasksWaitingToSend列表来保持对正阻塞在插入队列里的任务的跟踪。每当有一个元素被移出队列,xTasksWaitingToSend列表就会被检查。如果有个任务在那个列表中等待,那个是未阻塞任务。同样的,xTasksWaitingToReceive保持对那些正阻塞在移除队列里的任务的跟踪。每当有一个新元素被插入到队列,xTasksWaitingToReceive列表就会被检查。如果有个任务在那个列表中等待,那个是未阻塞任务。

信号灯和互斥

FreeRTOS使用它的队列与任务通信,也在任务间通信。FreeRTOS也使用它的队列来实现信号灯与互斥。

有什么区别?

信号灯与互斥听上去像一回事,但它们不是。FreeRTOS同样地实现了它们,但本来它们以不同的方式被使用。它们是如何不同地被使用?嵌入式系统宗师Michael Barr说这是在他文章中写得最好的,“信号灯与互斥揭秘”:

The correct use of a semaphore is for signaling from one task to another. A mutex is meant to be taken and released, always in that order, by each task that uses the shared resource it protects. By contrast, tasks that use semaphores either signal ["send" in FreeRTOS terms] or wait ["receive" in FreeRTOS terms] - not both.

正确使用的一个信号是从一个任务向另一个发信号。从每个使用被保护共享资源的任务来看,总是认为,一个互斥意味着获得和释放。相比之下,使用信号灯的任务不是发信号[在FreeRTOS里“发送”]就是在等信号[在FreeRTOS里“接收”]——不能同时。

互斥被用来保护共享资源。一个使用共享资源的任务获得互斥,接着释放互斥。当有另一个任务占据互斥时,没有一个任务可以获得这个互斥。这就是保证,在同一时刻仅有一个任务可以使用共享资源。

一个任务向另一个任务发信号时使用信号灯。以下引用Barr的文章:

For example, Task 1 may contain code to post (i.e., signal or increment) a particular semaphore when the "power" button is pressed and Task 2, which wakes the display, pends on that same semaphore. In this scenario, one task is the producer of the event signal; the other the consumer.

举例来说,任务一可能包含当“电源”按钮被按下时,发布(即,发信号或增加信号量)一个特定的信号灯的代码,并且唤醒显示屏的任务二,取决于同一个信号灯。在这种情况下,一个任务是发信号事件的制造者;另一个是消费者。

如果你是在信号灯和互斥有任何疑问,请查阅Michael的文章。

实现

FreeRTOS像队列一样来实现一个N元素的信号灯,这样就可以控制N个项。它没有去存储队列每项的任何实际数据;信号灯只关心有多少在队列的uxMessagesWaiting字段中被跟踪的队列记录,目前正被占用。当FreeRTOS的头文件semphr.h调用它的时候,它正在做“纯同步”。因此这个队列有一个零字节的项 (uxItemSize == 0)。每个信号灯uxMessagesWaiting字段递增或递减;没有项或数据的复制是需要的。

同信号灯一样,互斥也被实现为一个队列,不过有几个xQUEUE结构字段被用#defines重载:


#define uxQueueType           pcHead
#define pxMutexHolder         pcTail

当互斥没有在队列中存储任何数据时,它不需要任何内部存储器,同样pcHeadpcTail字段也不需要。FreeRTOS设置uxQueueType字段(实际上的pcHead字段)为0来表明,这个队列正在被一个互斥使用。FreeRTOS使用重载的pcTail字段来实现互斥的优先级继承。

万一你不熟悉优先级继承,我将再次引用Michael Barr的话来定义它,这次是来自他的文章,“优先级倒置”:

[Priority inheritance] mandates that a lower-priority task inherit the priority of any higher-priority task pending on a resource they share. This priority change should take place as soon as the high-priority task begins to pend; it should end when the resource is released.

[优先级继承]要求低优先级任务继承任何高优先级任务的优先级,取决于它们共享的资源。这个优先级的改变应当在高优先级任务一开始挂起时就发生;资源被释放时就结束。

FreeRTOS使用pxMutexHolder字段(实际上是#define重载的pcTail字段)来实现优先级继承。FreeRTOS记录在pxMutexHolder字段里包含一个互斥的任务。当一个高优先级任务正在等待一个由低优先级任务取得的互斥,FreeRTOS“更新”低优先级任务到高优先级任务的优先级,直至这个互斥再次可用。

3.7. 结论

我们完成了对FreeRTOS架构的一览。希望你现在对于FreeRTOS的任务是如何执行以及通信有一个好的感觉。如果之前你从未了解过操作系统的内在,我希望现在你对于它们是如何工作的有一个基本的思路。

显然,本章没有覆盖FreeRTOS架构的全部。值得注意的是,我没有提到的内存分配,中断服务,调试,或MPU支持。本章也没有讨论如何设置或使用FreeRTOS。Richard Barry已经写了一本极好的书,使用FreeRTOS实时内核:实用指南,这本书就是讲这些内容的;如果你要使用FreeRTOS的话,我强烈推荐它。

3.8. 致谢

我想感谢Richard Barry创造和维护了FreeRTOS,并选择将它开源。在写这一章的时候Richard给予了极大的帮助,提供了关于FreeRTOS的历史以及非常有价值的技术回顾。

也感谢Amy Brown和Greg Wilson共同拉动这整个AOSA的事情。

最后也是最(最多),感谢我的妻子Sarah共同承担了我对本章的研究和写作。幸运的是,她在嫁给我的时候就知道我是一名极客。

阅读全文
以上是58编程为你收集整理的freertos详解 卷2:第3章 FreeRTOS全部内容。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。
相关文章
  •  卷2:第6章 Git

    卷2:第6章 Git

    作者:Susan Potter,翻译:张吉原文:http://www.aosabook.org/en/git.html6.1 Git概述Git能够让不同的协作者通过一个点对点的...

© 2024 58编程 58biancheng.com 版权所有 联系我们
桂ICP备12005667号-32 Powered by CMS