• 沒有找到結果。

嵌入式操作系统 FreeRTOS 的原理与实现

N/A
N/A
Protected

Academic year: 2022

Share "嵌入式操作系统 FreeRTOS 的原理与实现"

Copied!
4
0
0

加載中.... (立即查看全文)

全文

(1)

8

20051 7

嵌入式操作系统 FreeRTOS 的原理与实现

u 中国海洋大学 刘滨 王琦 刘丽丽

F reeRT OS 是一个源码公开的免费的嵌入式实时操作系统, 通过研究其内 核可以更好地 理解嵌入式 操作 系统的实现原理。本文主要阐述 FreeRT O S 系统中的任务调度机制、时间管理机制、任务管理机制以及 内存分配策略的实现原理, 并指出 FreeRT O S 在应用中的优缺点。

关键词 RT O S FreeRT O S 任务调度 内存管理

在嵌入式领域中, 嵌入式实时操作系统正得到越来越 广泛的应用。采用 嵌入 式实 时操 作 系统 ( RT OS) 可以更 合理、更有效地利 用 CPU 的资源, 简化应用软件的设计, 缩短系统开发时间, 更好地保证系统的实时性和可靠性。

由于 RT OS 需占用一定的系统资源( 尤其是 RA M 资源) , 只有LC/ OS II、embOS、salvo、FreeRT OS 等少数实时操 作系统能在小 RA M 单片机上运行。相对于 LC/ OS II、

embOS 等商业操作系统, FreeRT OS 操作系统是完全免 费 的操作系统, 具有源码公开、可移植、可裁减、调度策略灵 活的特点, 可以方便地移植到各种单片机上运行, 其最新 版本为 2. 6 版。

1 FreeRTOS 操作系统功能

作为一个轻量级的 操作系 统, FreeRT O S 提供的功能 包括: 任务管理、时间管理、信号量、消息队列、内存管理、

记录功能等, 可基本满足较小系统的需要。FreeRT O S 内 核支持优先级调度算法, 每个任务可根据重要程度的不同 被赋予一定的优先级, CPU 总是让处于就绪态的、优先级 最高的任务先 运行。F reeRT OS 内核同时支持轮换调度 算法, 系统允许不同的任务使用相同的优先级, 在没有更 高优先级 任 务 就 绪 的 情 况 下, 同一优先级的任 务共享 CPU 的使用时间。

FreeRT OS 的内核可 根据 用户 需 要设 置为 可 剥夺 型 内核或不可剥夺 型内核。 当 FreeRT OS 被设置为可剥夺 型内核时, 处于就绪态的高优先级任务能剥夺低优先级任 务的 CPU 使用权, 这样可保证系统满足实时性的要求; 当 Free RTO S被设置为不可剥夺型内核 时, 处于 就绪态的 高 优先级任务只有等当前运行任务主动释放 CPU 的使用权 后才能获得运行, 这样可提高 CPU 的运行效率。

2 FreeRTOS 操作系统的原理与实现

2. 1 任务调度机制的实现

任务调度机制是嵌入式实 时操 作系统 的一 个重要 概

念, 也是其核心技术。对于可剥夺型内核, 优先级高的任 务一旦就绪就能剥夺优先 级较 低任务 的 CPU 使用权, 提 高了 系 统 的 实 时 响 应 能 力。 不 同 于 LC/ OS II, Free RT OS 对系统任务的数量没有限制, 既支 持优先级调 度算 法也支持轮换调度算法, 因此 FreeRT O S 采用双向链表而 不是采用查任务就绪表的 方法 来进行 任务调 度。系统 定 义的链表和链表节点数据结构如下所示:

typedef struct x L IST { / / 定义链表结构 unsigned por tSH O RT usN umber OfItems;

/ / usNumberO fI tems 为链表的长度, 为 0 表示链表为空 volatile x L istItem * px Head; / / px H ead 为链表的头指针 volatile xListItem * pxIndex; / / pxIndex 指向链表当前结点的指针 volatile x L istItem xL istEnd; / / x ListEnd 为链表尾结点 } x L ist;

st ruct x L IST _I T EM { / / 定义链表结点的结构 po rtT ickT y pe x ItemV alue;

/ / x ItemV alue 的值用于实现时间管理 / / por tT ickT ype 为时钟节拍数据类型, / / 可根据需要选择为 16 位或 32 位 volatile str uct x LIST _IT EM * pxN ext;

/ / 指向链表的下一个结点 volatile str uct x LIST _IT EM * pxP revio us;

/ / 指向链表的前一个结点

void * pvO wner; / / 指向此链表结点所在的任务控制块 void * pvContainer; / / 指向此链表结点所在的链表 } ;

FreeRT OS 中 每 个 任 务 对 应 于 一 个 任 务 控 制 块 ( T CB) , 其定义如下所示:

typedef struct t skT askCo nt rolBlock {

po rtST A CK _T YP E * px T opOfStack;

/ / 指向任务堆栈结束处 po rtST A CK _T YP E * px Stack;

/ / 指向任务堆栈起始处

(2)

20051 7 M icr ocontr oller s & Em bedded Syst ems

9

unsigned portSH ORT usStackDept h; / / 定义堆栈深度 signed portCH AR pcT askN ame[ tskM AX_T A SK_

NAME_LEN ] ; / / 任务名称

unsigned portCH AR ucPr ior ity; / / 任务优先级 xListItem xG ener icListItem;

/ / 用于把 T CB 插入就绪链表或等待链表 xListItem xEventL istItem;

/ / 用于把 T CB 插入事件链表( 如消息队列) unsigned por tCH A R ucT CBN umber ; / / 用于记录功能 } tskT CB;

FreeRT OS 定义就绪任务链表数组为 xL ist pxReady- T asksL ist s[ portM A X _ PRIORIT IES ] 。其 中 port M AX _ PRIORIT IES 为系统 定义 的最大 优先 级。若 想使 优先 级 为 n 的任务进入就绪态, 需要把此任务对应的 T CB 中的 结 点 x GenericList It em 插 入到 链 表 px ReadyT asksL ist s [ n] 中, 还 要 把 x GenericL ist It em 中 的 pvContainer 指 向 pxReadyT asksL ist s [ n] 方可实现。

当进行任务调度时, 调度算法首先实现优先级调度。

系统按照优先级从高到低的 顺序从 就绪任 务链 表数组 中 寻找 usN umberOfIt ems 第一个不为 0 的优先级, 此优先 级即为当前最高就绪优先级, 据此实现优先级调度。若此 优先级下只有一个就绪任 务, 则此就绪任务进入运行态;

若此优先级下有多个就绪任务, 则需采用轮换调度算法实 现多任务轮流执行。

若在优先级 n 下执行轮换调度算法, 系统先通过执行 ( pxReadyT asksL ist s [ n ] ) → pxIndex = ( pxReadyT ask s- L ist s[ n] ) → pxIndex→ pxN ext 语句 得 到当 前结 点 所指 向 的下一个结点, 再通过此结点的 pvOw ner 指针得到对应 的任务控制块, 最后使此任务控制块对应的任务进入运行 态。由此可见, 在 F reeRT OS 中, 相同优先级任务之间的 切换时间为一个时钟节拍周期。

以图 1 为例, 设 系统 的最大 任务 数为 port M AX _ PRIORIT IES , 在 某 一 时 刻 进 行 任 务 调 度 时, 得 到 pxReadyT asksL ist s [ i] . usNumberOfItems = 0 ( i = 2. . . port M AX _ PRIORIT IES ) 以 及 pxReadyT asksList s [ 1 ] . usNumb erOfItems= 3。由此内核 可知 当前 最高 就 绪优 先 级为 1, 且此优先级下已有三个任务已进入就绪态。由于 最高就绪优先级下有多个就绪任务, 系统需执行轮换调度 算法实现任务切换: 通过指针 px Index 可知任务 1 为当前 任务, 而任务 1 的 pxN ext 结点指向任务 2, 因此系统把 pxInd ex 指向任务 2 并执行任务 2 来实现任务调度。当下 一个时钟节拍到 来 时, 若最高就绪优先级仍为 1, 由图 1 可见, 系统会把 pxIndex 指向任务 3 并执行任务 3。

为了 加 快 任 务 调 度 的 速 度, FreeRT OS 通过 变 量 ucT opReadyPriority 跟踪当前就绪的最高优先级。当把一

图 1 任务调度示意

个任 务 加 入 就 绪 链 表 时, 如 果 此任 务 的优 先级 高 于 ucT opReadyPriority, 则 把 这 个 任 务 的 优 先 级 赋 予 ucT opReadyPriority。这样 当 进 行优 先 级 调 度时, 调 度 算 法不 是 从 port M AX _PRIORIT IES 而是从 ucT opReady- Priorit y 开始搜索。这就 加快了 搜索 的速度, 同时 缩短 了 内核关断时间。

2. 2 任务管理的实现

实现多个任 务的 有效 管理 是 操作 系统 的 主要 功 能。

FreeRT OS 下可实现创建任务、删 除任务、挂 起任务、恢 复 任务、设定任务优先级、获 得任 务相关 信息等 功能。下 面 主要讨论 FreeRT OS 下任务创建和任务删除的实现。

当调 用 sT askCreate( ) 函数创建一个新的任务时, FreeRT OS 首先为新 任务 分配 所需 的 内存。若 内 存分 配 成功, 则初始化任务控制块的任务名称、堆栈深度和任务 优先级, 然后根据堆栈的增长方向初始化任务控制块的堆 栈。接着, F reeRT OS 把当前创建的任务加入到就绪任务 链表。若当前此任务的优先级为最高, 则把此优先级赋值 给变量 ucT opReadyPriorit y( 其作用见 2. 1 节) 。若任务调 度程序已经运行且当前创建的任务优先级为最高, 则进行 任务切换。

不同于LC/ OS II, F reeRT OS 下任务删除分两步进 行。当用户调用 vT askDelet e( ) 函数后, 执行任务删除的 第一步: FreeRT OS 先把要删除的任务从就绪任务链表和 事件等待链表 中删 除, 然后把此任务添加到任务删除链 表, 若删除的任务是当前运行任务, 系统就执行任务调度 函数, 至此完成任务删除的第一步。当系统空闲任务即 prvIdleT ask( ) 函数运行时, 若发现任务删除链表中有等待 删除的任务, 则进行任务删除的第二步, 即释放该任务占 用的内存空间, 并把该任务从任务删除链表中删除, 这样 才彻底删 除 了 这 个 任务。 值 得 注 意的 是, 在 FreeRT O S 中, 当系统被配置为不可剥夺内核时, 空闲任务还有实现

(3)

10

20051 7

各个任务切换的功能。

通过比较LC/ OS II 和 F reeRT OS 的具体代码发现, 采用两步删除的策略有利于减少内核关断时间, 减少任务 删除函数的执行时间, 尤其是当删除多个任务的时候。

2. 3 时间管理的实现

FreeRTOS 提供的典型时间管理函数是 vTaskDelay ( ) , 调用此函数可 以实 现将 任务 延 时一 段特 定时 间 的功 能。

在 FreeRT O S 中, 若一个任务要延时 xT icksT oDelay 个时 钟节拍, 系统内核会把当前系统已运行的时钟节拍总数 ( 定义为 xT ickCount, 32 位 长 度) 加 上 xT icksT oDelay 得 到任务下次唤 醒时 的时 钟节 拍数 xT imeT oWake。然后, 内核把此任务的任务控制块从就 绪链表中删 除, 把 xT im- eT oW ak e 作 为 结 点 值 赋 予 任 务 的 xIt emValu e, 再 根 据 xT imeT oW ake 的值把任务控制块按照顺序插入不同的 链 表。若 xT imeT oWake> xT ickCount , 即计算中没有出现 溢出, 内核把任务控制块插入到 pxDelayedT askLis t 链表;

若 xT imeT oWake < xT ickCount, 即在计算过程中出现溢 出, 内 核 把 任 务 控 制 块 插 入 到 pxOverflowDelayed- T askL ist 链表。

图 2 采用空闲内存块链表进行内存管理 每发 生 一 个 时 钟 节 拍, 内核就会把当 前的 xT ick-

Cou nt 加 1。若 xT ickCou nt 的结果为 0, 即发生溢出, 内核 会把pxO verflow DelayedT askL ist 作为当前链表; 否则, 内 核把 pxDelayedT askList 作为当前链表。内核依次比较 xT ick Count 和链表各个结点的 xT imeT oW ak e。若 xT ick- Cou nt 等于或大于 xT imeT oWake, 说明延 时时间 已到, 应 该把任务从等待链表中删除, 加入就绪链表。

由此可见, 不同于 LC/ OS II, F reeRT OS 采用/ 加0的 方式实现时间管理。其优点是 时间 节拍函 数的 执行时 间 与任务数量基本无关, 而 LC/ O S II 的 OST imeT ick( ) 的 执行时间正比于应用程序 中建立 的任 务数。因 此当任 务 较多时, F reeRT OS 采用的时间管理方式能有效加快时钟 节拍中断程序的执行速度。

2. 4 内存分配策略

每当任 务、队 列和 信号 量创 建的 时候, FreeRT OS 要 求分配一定的 RAM 。虽然采用 malloc( ) 和 free( ) 函数可 以实现申请和释放内存的功能, 但这两个函数存在以下缺 点: 并不是在所有的嵌入式系统中都可用, 要占用不定的 程序空间, 可重入性欠缺以及执行时间具有不可确定性。

为此, 除了可采用 malloc( ) 和 free( ) 函数外, FreeRT OS 还 提供了另外两种内存分配的策略, 用户可以根据实际需要 选择不同的内存分配策略。

第 1 种方法是, 按照需求内存的大小简单地把一大块 内存分割为若干小块, 每个小块的大小对应于所需求内存 的大小。这 样做 的好 处 是比 较简 单, 执行时间可严格确

定, 适用于任务和队列全部创建完毕后再进行内核调度的 系统; 这样做的缺点是, 由于内存不能有效释放, 系统运行 时应用程序并不能实现删除任务或队列。

第 2 种方法是, 采用链表分配内存, 可实现动态的创 建、删除任务或队列。系统根据空闲内存块的大小按 从小 到大的顺序组织空闲内存 链表。当 应用程 序申 请一块 内 存时, 系统根据申请内存的大小按顺序搜索空闲内存链 表, 找到满足申请内存要求的最小空闲内存块。为了提高 内存的使用效率, 在空闲内存块比申请内存大的情况下, 系统会把此空闲内存块一 分为 二。一块用 于满 足申请 内 存的要求, 一块作为新的空闲内存块插入到链表中。

下面以图 2 为例介绍方法 2 的实现。假定用于动态分 配的 RAM 共有 8 KB, 系统首先初始化空闲内存块链表, 把 8 KB RAM 全部作为一个空闲内存块。当应用程序分别申 请 1 KB 和 2 KB 内存后, 空闲内存块的大小变为 5 KB。2 KB 的内存使用完毕后, 系统需要把 2 KB 插 入到现有的空 闲内存块链表。由 于 2 KB< 5 KB, 所以把这 2 KB 插入 5 KB 的内存块之前。若应用程序又需 要申请 3 KB 的内存, 而在空闲内存块链表中能满足申请内存要求的最小空闲内 存块为 5 KB, 因此把5 KB 内存拆分为 2 部分, 3 KB 部分用 于满足申请内存的需要, 2 KB 部分作为新的空闲内存块插 入链表。随后 1 KB 的内存使用完毕需要释放, 系统会按顺 序把 1 KB 内存插入到空闲内存链表中。

方法 2 的优点是, 能根据任务需要高效率地使用内 存, 尤其是当不同的任务需要不同大小的内存的时候。方 法二的缺点是, 不能把应用程序释放的内存和原有的空闲 内存混合为一 体, 因此, 若应用程序频繁申请与释放/ 随 机0大小的内存, 就可能造成大量的内存碎片。这就要求 应用程序申请与释放内存的大小为/ 有限个0固定的值( 如 图 2 中申请与释放内存的大小 固定为 1 K B、2 KB 或 3 KB) 。方法 2 的另 一个 缺点是, 程序执 行时 间具 有一 定 的不确定性。

LC/ O S II 提供的内存管理机制是把连续的大块内 存按分区来管理, 每个分区中包含整数个大小相同的内存 块。由于每个分区的大小相同, 即使频繁地申请和释放内

(4)

20051 7 M icr ocontr oller s & Em bedded Syst ems

11

存也不会产生内存碎片问题, 但其缺点是内存的利用率相 对不高。当申请和释放的内存大小均为一个固定值时 ( 如 均为 2 K B) , FreeRT OS 的方法 2 内存分配策略就可以实 现类似LC/ OS II 的内存管理效果。

2. 5 FreeRTOS 的移植

FreeRT OS 操作系统 可以 被方 便 地移 植到 不 同处 理 器上工作, 现已提供了 ARM 、M SP430、A VR、PIC、C8051F 等多款处理器 的移 植。FreeRT O S 在不同处理器上的移 植类似于LC/ OS II, 故本文不再详述 F reeRT OS 的移 植。此外, T CP/ IP 协议栈 LIP 已被移植到 F reeRT OS 上, 具体代码可见 FreeRT O S 网站。

2. 6 FreeRTOS 的不足

相对于常见的LC/ OS II 操作系统, FreeRT OS 操作 系统既有优点也存在不足。其不足之处, 一方面体现在系 统的服务功能上, 如 FreeRT O S 只提供了消息队列和信号 量的实现, 无法以后进先出的顺序向消息队列发送消息;

另一方面, F reeRT OS 只是一个操作系统内核, 需外扩第 三方的 GU I( 图形用户界面) 、T CP/ IP 协议栈、F S( 文件系 统) 等才能实现一个较复杂的系统, 不像 LC/ OS II 可 以 和LC/ GU I、LC/ FS、LC/ T CP IP 等无缝结合。

3 结 论

作为一个源码公开的操作系统, 学习 FreeRT O S 可以 更好地掌握嵌入式实时操作系统的实现原理; 作为一个免 费的操作系统, 采用 FreeRT OS 可在基本满足较小系统需 要的情况下降低系统成 本、简化 开发 难度。在 实践中, 采 用 FreeRT OS 操作系统和 M SP430 单片机构成的温度控 制系统稳定可靠, 实现了较好的控制效果。相信随着时间 的发展, FreeRT OS 会不断完善其功能, 以更好地满足人 们对嵌入式操作系统实时性、可靠性、易用性的要求。

参考文献 1 w ww . F reeRT O S. or g

2 L abrosse Jean J. 嵌入 式实时操 作系统 LC/ OS II. 第 2 版.

邵贝贝译. 北京: 北京航空航天大学出版社, 2003

刘滨: 副教授, 主要从事嵌入式系统、智能仪器 仪表和单 片机应用 等 技术开发和产品研 制工作。 王琦: 硕 士研究 生, 主要 研究方 向为 嵌 入式系统和 DSP。刘丽丽: 硕 士研究 生, 主要 研究方 向为嵌 入式 系 统和运动控制。

( 收稿日期: 2005-03- 07)

7

( 2) 基于普通端口位 LIN从节点的实现

基于单片机普通端口位 L IN 从节点硬件电路和基于 单片机通用串口查询方式的从节点硬件电路基本相 同, 区 别同样也是没有用到单片机的通用串口。

由于没有外部中断的功能, 因此对主节点发送过来的 报文头的接收只能靠从节 点主动 地等 待查询。 考虑到 从 节点程序不可能一直在查询等待与主节点同步, 因此从节 点应该不定时地去查询等 待主节 点的 报文头。 开始阶 段 设置定时器为不定长时间中断方式, 时间到后从节点去查 询等待主节点发送的报文帧。当检测到同步信息后, 设置 定时器为标准位时时间中断方式, 对从节点接收或发送数 据过程进行位时界定。从节点 按照 上述提 到的 位操作 方 法接收 PID 场, 并转换为 byt e 类型的数据, 判断下一步数 据场的发送或接收方向, 接着按照位操作的方法实现数据 的发送或接收。定时 器的两种 工作 方式在 查询 等待和 报 文通信过程中轮流转换, 在报文通信过程结束后, 重新设 置定时器为不定长时间中断方式, 等待下一次的报文通信 过程, 以此类推。

从节点由于采用不定期查 询等 待方法 与主 节点的 同 步, 因此通信成功率不高; 但对于数据通信速率和实时性 要求不是很高的场合, 还可以满足要求。如果单片机有外

部中断能力, 则可以改从节点不定期查询为从节点用外部 中断查询主节点发送来的报文, 这样通信的成功率就可以 大大提高。

结 语

相对于增强型单片机, 普通单片机的功能显得简单多 了, 资源也很有限, 但它有一个价格低廉的优势。而 LIN 总线的特点是协议简单, 可用软件方式实现, 特别适合于 数据通信速率要求不高、控制简单的场合。如果能以 普通 单片机 有限的 资源实 现 LIN 通信协议, 无疑会为低端串 行通信领域提供一个很好 的选 择。以普通 单片 机为硬 件 基础构成的 LIN 节点也一定会在生产和生活的相关应用 领域大有作为。

参考文献

1 LI N Specificat ion Package Rev ision 2. 0. http: / / w ww . lin- subbus. o rg

2 广州周立功单片机发展有限公司. L IN 的规范( V 1. 2) 3 L IN Bus M aster ( Slave) Design IP . http: / / w ww . cy pr essm-i

cr o. com/ .

4 L IN P ro tocol Implementation o n the T 89C51CC01/ 02.

http: / / ww w. atmel. com

( 收稿日期: 2005-02-22)

參考文獻

相關文件

將產出鍊輸入後,各訂單會依其最有利的時間排定 其生產順序,因此會發生個訂單擠在同一天等產能不足

在点 不可导,则曲线 在点

4、任给空间中某一点,及某一方向,过该定点且垂

形成原因 反应物具有的总能量 生成物具有的总能量. 反应物具有的总能量

下图是单脚支撑形式的示意图,支撑脚和地面的接触点 A 与前、后轮和地面之间 的接触点 B 、 C 共同构成三点支撑,在地面形 成△

穿插课文之中、形 式多种多样的活动使 我们所学的知识与技 能得到及时的巩固、应 用和内化,它是我们主 动建构知识、拓展能

穿插课文之中、形 式多种多样的活动使 我们所学的知识与技 能得到即时的巩固、应 用和内化,它是我们主 动建构知识、拓展能

(1) 若 A、B 电荷固定不动,在它们连线的中 点放入带电量为+2Q 的电荷 C, 电荷 C 受到的静电力是多少?.. (2) 若 A、B