[ZLG-ARM]

μC/OS任务调度算法的硬件实现

[复制链接]
4392|20
手机看帖
扫描二维码
随时随地手机跟帖
diny|  楼主 | 2011-1-20 15:53 | 显示全部楼层 |阅读模式
μC/OSII用于教学与研究是免费的。近些年来,我国各类大学的嵌入式系统教学中纷纷采用μC/OSII作为教材。而μC/OSII也被移植到几乎所有的CPU上。各类杂志上发表的相关论文也数目可观,虽然大部分论文只谈到移植。  μC/OSII是为8位 CPU写的RTOS小内核,任务调度算法巧妙,移植到任何处理器上都很好用。而对于一些有RTOS优先级算法硬件指令的16/32/64位的处理器,照搬μC/OSII的8位算法、强行移植μC/OSII未必恰当。
  1  μC/OS的调度算法
  μC/OS采用优先级至上的任务调度原则:“让进入就绪态任务中优先级最高的那个任务,一进入就绪态立刻就能立即运行”。这种基于优先级的任务调度原则,在嵌入式实时系统中最常用。μC/OS实现了一种巧妙的查表算法,利用这种算法能快速实现上述任务调度原则。这种查表算法的大致思路是,用8字节数组中的64位作为就绪任务表,每一位表示一个任务的状态,该位为1表示任务就绪,0为非就绪态。64位中第一个字节的b0位代表64个任务中优先级最高的任务,最后一个字节的b7位代表优先级最低的空闲任务。通过2次查用一张常数数组表,迅速找出任务就绪表中就绪态任务中优先级最高的那个。常数表中,按照0~7表示的8种不同权重,以一定规律排列128个0、64个1、32个2、16个3,8个4、4个5、2个6和1个7,再补上1个0后,共256字节。查表法避免了逐位检测各优先级位引起的执行时间的不确定性,程序简单,执行速度快,且时间是固定的,与就绪任务多少无关,与任务优先级无关。这是μC/OS任务调度的核心算法。在处理信号量、邮箱、消息队列等事件时,为了查找等待事件发生的任务列表中优先级最高的那个任务,也采用同样的算法,查的是同一张常数数组表。
  μC/OS最初是为Motorola的增强型8位处理器MC68HC11写的,算法精彩,将其移植到其他8位、16位处理器,这种8位机算法无懈可击。除任务就绪表外,μC/OSII在多处使用了上述调度算法。典型地,在事件控制块ECB中有:
  INT8UOSEventTbl[OS_EVENT_TBL_SIZE];
  INT8UOSEventGrp;
  这里,OS_EVENT_TBL_SIZE 的默认值为8,即以8个8位数的数组表示最多64个不同优先级的任务;OSEventGrp是OSEventTbl的索引字节,这就是μC/OS算法中著名的8+1个字节数据结构。当OSEventTbl 中的某一个字节不为0时(表示该字节代表的8个任务中至少有1个在等待事件发生),OSEventGrp 中的相应位置1。首先以OSEventGrp的值做偏移量,查那张256字节的常数表,获得1个0到7的数Y,作为优先级高3位,再根据Y的值,找出OSEventTbl中8个字节中最先出现的那个不为零的字节;然后再次查那张表,得到1个0到7的数X,找出字节中最靠近b0的那一位,作为优先级低3位的值,通过将Y左移3位再加上X的值,得到等待事件发生任务中优先级最高的那个任务的优先级。
  在每个任务的任务控制块TCB中有下列定义,可以看出,任务优先级被拆分成两个8进制数X和Y,用来以空间换时间,加快优先级查找速度:
  INT8UOSTCBX;/*=priority & 0x07;*/
  INT8UOSTCBY;/*=priority >> 3;*/
  INT8UOSTCBBitX;/*=OSMapTbl[priority & 0x07];*/
  INT8UOSTCBBitY;/*=OSMapTbl[priority >> 3];*/
  以上是μC/OS任务调度算法的简要介绍,Jean J. Laborosse 先生最先用这种算法实现了RTOS中基于优先级的调度策略,是μC/OS任务调度算法的精华与核心技术。
  2  优先级算法指令
  对于32位和64位处理器,特别是一些精简指令流类型的处理器,其内部有可直接用于RTOS优先级算法的硬件指令。以PowerPC 处理器为例,予以说明。这里顺便解释一下,PowerPC是IBM、Motorola和Apple三家公司于90年代初期联合设计的32位处理器,90年代后期出现增强型32位处理器,大量用于嵌入式系统,特别是汽车、通信等行业。本世纪初期,还出现了64位的处理器。在64位PowerPC 处理器指令中,有2条可供RTOS算法使用的指令:
  cntlzd (Count Leading Zeros Double Word)
  cntlzw (Count Leading Zeros Word)
  上述指令也可简称为CLZ指令。设某通用源寄存器RS中有一个64位数,b0是高位,b63是低位,执行cntlzd指令后,在目标寄存器RD中返回源寄存器RS中64位数的前导零的数目。返回0表示b0不为0,即该64位数没有前导0;返回n表示bn不为0,bn位的前面n位(b0~bn-1)共有n个零;返回64表示RS寄存器中所有位都为0。
  如果用一个64位数表示64个任务的优先级,从b0开始到b63,b0为最高优先级,b63表示最低优先级,使用cntlzd指令,可迅速找出优先级最高的那个任务。RISC类型的处理器,执行1条指令一般只需要1个CPU时钟周期。执行该指令,仅一个CPU时钟周期就可完成对64个不同优先级任务的判选。在这类处理器上直接移植和套用μC/OSII软件算法,显然不合理。
  对于32位的PowerPC,也有汇编指令cntlzw。 数出一个32位数前置零的数目。指令执行后,RD中返回指定源寄存器RS中32位数的前置零的数目,返回0表示b0不为0,即没有前导0,返回32表示寄存器RS中所有的位都为0。这一条指令可从32个任务中迅速找出优先级最高的那个任务。若使用2个32位数表示64个不同任务的优先级,则下面是使用该指令实现μC/OSII算法的示意性代码。
  初始化:
  Prio = 0;
  让寄存器变量指向任务就绪表;
  找出最高优先级程序:
  读入优先级表的第1个32位数;
  不为零则直接使用CLZ指令;
  Prio = 32;
  读入优先级表的第2个32位数;
  CLZ指令:
  CNTLZW RD,RS;
  RD += Prio;/*最高优先级*/
  这样,很少几条指令,就完成了μC/OS中需要查表来完成的算法,不仅速度快,还省去了程序中256字节的那张常数表。上述实现方法并非唯一的,还可进一步优化。对于增强型32位PowerPC[6],还有一条指令可对2个地址连续的32位数做并行操作,同时数出前导零的数目。此时若低32位不为0,则最高优先级者被立即找出;若为0,则取高32位中的优先级再加32即可。
  其他32位机,如MIPS的处理器,也有同类指令。一些处理器还有与上述指令对称的“数出前置1的数目”指令。总之,在有类似CLZ指令的处理器上,直接移植和使用μC/OSII的任务调度算法并不合理。移植后需要摒弃μC/OSII中的软件算法,代之以硬件指令算法指令,实现RTOS任务调度算法的优化。
  早期的ARM系列处理器并不支持CLZ指令,但从ARM Cortex 开始,或者说ARM v5及以后的ARM类CPU,如CortexA8、CortexM3等,开始支持CLZ指令。因此对于Cortex单片机,也没有必要套用μC/OS算法,这类处理器可运行μC/OSIII[7]。μC/OSIII是在μC/OSII的基础上发展起来的商业产品,目前还只能在ST的ARM Cortex 32位微控制器上实现。Cortex有RTOS硬件算法指令,不再需要使用μC/OS的查表算法。μC/OSIII还增加了同优先级任务的时间片轮转调度法等很多新功能,已经是一个全新的RTOS商业产品了,不再是μC/OSII的升级版。由于目前μC/OSIII产品单一且源码不再开放,以及价格方面等原因,我们还无法预见其未来。因此,深入研究和讨论μC/OSII的移植和优化是很有意义的。
  除了上面提到的几种处理器,还有一些16位处理器也支持CLZ这样的RTOS运算指令。在这类处理器上强行移植和直接使用μC/OSII也会有弄巧成拙的感觉。
  以16位的MC9S12XE系列和XF系列单片机为例,片内有2个CPU,一个是传统的CISC类型的CPU S12,另外一个是名为XGate的RISC类型CPU,XGate中有一条类似指令BFFO (Bit Field Find First ONe)指令格式为:
  BFFORD,RS
  意为找出第一个1,和数出前导零的数目其实是一回事。目标寄存器RD中得到源寄存器RS中16位数的第一个1的位置,如果RS中为全零,则C标志置位。在XGate处理器上,特别是使用 v2内核的处理器,可以利用BFFO指令优化μC/OSII任务调度算法。且对于μC/OSII的改进并不限于用BFFO指令替代查表算法,还可以尝试将RTOS和其管理的任务分别加载到2个CPU上。内核和任务调度在RISC类型的XGate上运行,被管理的任务放到CISC类型的S12 处理器上运行;XGate v1CPU虽然有BFFO指令,由于中断无法嵌套,无法完整地运行XGate,但至少可以将XGateII中的时钟节拍函数放到XGate上运行[8]。具有硬件优先级算法指令的处理器,以及多内核单片机,为μC/OSII的改进和性能优化开拓了丰富的想象空间。在决定移植和使用μC/OSII之前,应该仔细研究一下拟用处理器的指令集,切莫盲目移植了事。
  3  移植和优化中还应思考的问题
  因为越来越多的RISC类型处理器有了能用于RTOS任务调度算法的硬件指令,μC/OSII调度算法可以用硬件指令迅速完成,而不必依赖原来的软件查表算法,大大简化了程序,提高了运算速度。但由于RISC类型的处理器,没有直接对存储器操作的指令,所有操作都只能通过CPU内部寄存器完成,不能如同8位处理器那样直接对存储器做位操作,这类RISC类型处理器中有很多内部寄存器,可以设一些寄存器变量类型的指针来操作。如何用好寄存器变量,是要仔细研究的。
  RISC类型的CPU一般没有让存储器的某一位置位或把存储器的某一位清零的指令。往往需要先读存储器到CPU寄存器,再使用“与”、“或”等指令让寄存器某一位复位或置位,再写回到存储器。这一连串的操作可能需要保护,防止其间被中断。可以想象,若移植μC/OSII,在填写任务就绪表的时候,操作并不简单,要考虑全面,避免任何疏漏和隐患。另外还有编译器方面的问题。我们看到,上述讨论中涉及了不少汇编指令,如同cntlz,在C语言中是无法直接表达的,编译器对这样的汇编指令能支持到什么程度,是用户要细心研究的。现在,越来越聪明的编译器能将我们写的C程序按照执行速度或代码长度等用户定义的条件进行优化,能优化到什么程度?什么条件下能把类似cntlz这样的指令优化进去?这些都是要研究的。
  对于中高端的处理器,一般都有系统态模式和用户态模式(有的CPU称之为保护模式),过去看到的很多移植**都对此不予理会,让CPU完全工作在系统态。如果让RTOS内核工作在系统态,任务工作在用户态,有助于提高系统安全性。这类讨论也是过去那些关于μC/OSII移植的**中极少见到的。
  4  小结
  μC/OSII是在中国嵌入式系统应用中很有影响力的RTOS内核,已经被移植到几乎所有能想到的处理器上。其技术亮点体现在优先级调度算法上。由于当初是为8位处理器写的,对于8位处理器和多数16位处理器,运行μC/OSII是很不错的选择。处理器硬件技术的不断发展,为RTOS任务调度算法的实现方法开拓了广阔的想像空间。一些原来需要软件实现的算法可以硬件化。典型地,对于32/64位和部分高端16位处理器,有可用于RTOS优先级算法的硬件指令,例如文中提到的PowerPC、MIPS、ARM Cortex和XGate等,直接移植μC/OSII代码,套用其调度算法实际上很不合理。使用CLZ或BFFO等硬件指令替代μC/OSII中的软件算法,可大 14
  大简化μC/OSII代码并优化RTOS性能。本文提到的方法也决非唯一。技术在发展,对于μC/OSII,千万不要移植了事,尽管已经讨论了十来年,仍然需要静下心来学习并做些深入细致的研究,希望今后能够看到更多深入探讨μC/OSII优化的**。

相关帖子

coco11| | 2011-1-27 16:27 | 显示全部楼层
不错,帮顶了。

使用特权

评论回复
bit6019| | 2011-1-31 22:34 | 显示全部楼层
说的很细,不错

使用特权

评论回复
yoyowodeai| | 2011-1-31 23:12 | 显示全部楼层
酷,受教了

使用特权

评论回复
ladygaga| | 2011-2-1 22:26 | 显示全部楼层
学习了。

使用特权

评论回复
diny|  楼主 | 2011-2-24 16:45 | 显示全部楼层
本帖最后由 diny 于 2011-2-24 16:48 编辑

我激动鸟,我感谢CCAV,感谢21IC,感谢HOT,感谢所有关注此贴的朋友。我要更加努力,得到更多的“酷”!此后省略10000字。

使用特权

评论回复
vivisa| | 2011-2-24 17:33 | 显示全部楼层
让我的贴子里有个“酷”是我的目标。加油。:P

使用特权

评论回复
maoyanketi| | 2011-2-24 20:14 | 显示全部楼层
好帖子,不错

使用特权

评论回复
msp430ing| | 2011-2-25 18:13 | 显示全部楼层
不愧是酷贴,受教了

使用特权

评论回复
快乐出发| | 2011-2-25 21:58 | 显示全部楼层
酷。

使用特权

评论回复
ty新气象| | 2011-2-25 22:40 | 显示全部楼层
呵呵,谢谢。

使用特权

评论回复
maoyanketi| | 2011-2-27 11:33 | 显示全部楼层
好资料不得不顶啊!

使用特权

评论回复
金鱼木鱼| | 2011-2-27 14:15 | 显示全部楼层
确实不错,我什么时候也可以得个酷啊

使用特权

评论回复
linas| | 2011-4-22 16:26 | 显示全部楼层
我今天就是奔着酷来的。

使用特权

评论回复
思行合一| | 2011-4-23 14:06 | 显示全部楼层
确实不错

使用特权

评论回复
hxy6951| | 2011-4-23 15:26 | 显示全部楼层
正在学,有时间看看

使用特权

评论回复
午后苦丁茶| | 2011-6-20 21:19 | 显示全部楼层
:handshake

使用特权

评论回复
ShaoKn| | 2011-8-15 10:39 | 显示全部楼层
标记

使用特权

评论回复
gys123456| | 2011-10-17 15:38 | 显示全部楼层
现在看了ucos,急需实践锻炼下啊

使用特权

评论回复
bairan168| | 2011-10-19 10:57 | 显示全部楼层
比较实用。顶一下。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

482

帖子

2

粉丝