μC/OS系列内核都是源代码开放的、可移植、可固化、可裁剪的抢占式实时多任务内核。μC/OS诞生于1992年,是针对68HC11 CPU开发的。μC/OSII V2.0诞生于1998年,μC/OSII V2.52诞生于2002年。针对这3个版本的实时内核,Jean J. Labrosse先生出版了3本书,分别为《μC/OS The RealTime Kernel》、《Micro C/OSII The RealTime kernel》和《Micro C/OSII The RealTime kernel(Second Edition)》。其中,第2本和第3本书都有对应的中文译著,第3本书比第2本书增加了约250页新内容。μC/OSIII诞生于2009年,于2011年8月公开源码。《μC/OSIII The Real Time Kernel》一书分为两大部分:第1部分是对μC/OSIII硬件无关软件的描述;第2部分讲述μC/OSIII在不同型号的ARM CortexM3/4单片机评估板上应用的范例。第1部分相同,第2部分对应不同硬件,目前已经组合出版了6本书,分别对应如下:
◆ Freescale公司的以Kinetis53单片机为核心,面向医疗仪器类应用的TWRK53N512评估板;
◆ NXP公司的以LPC1768(CortexM3核)为核心的评估板;
◆ Renesas公司的以RX62N 为核心的评估板;
◆ Renesas公司的以带以太网口的SH7216 为核心的评估板;
◆ ST公司的以STM32F107 为核心的评估板;
◆ TI公司的以LM3S9B92为核心,面向小型机器人带以太网口的VMEVALBOT评估板。
μC/OSIII是针对32位CPU开发的,相比μC/OSII做了很多改动。下面将详细介绍μC/OSII中的一些可以改进的地方以及μC/OSIII中的一些新特性。
1 μC/OSII的特点与局限
μC/OSII主要针对8/16位CPU开发,是一个抢占式的实时多任务内核。任务调度策略是基于任务的优先级,总是运行处于就绪态的优先级最高的任务。在μC/OSII中,每个任务都有一个唯一的优先级。μC/OSII V2.8之前的版本最多支持64个优先级,从V2.8开始最多可支持255个优先级。
μC/OSII的核心是任务调度算法。任务调度算法的目标就是快速找出其中优先级最高的处于就绪态的任务。为了做到这一点,μC/OSII巧妙地采用了查表法。在查表过程中,μC/OSII需要快速找出1个8位数的第一个非零位的位置,这是通过1个由256个元素构成的查找表OSUnMapTbl实现的,该查找表记录了每一个8位数的第一个非零位的位置。通过这种巧妙的查表算法,不论有多少个任务处于就绪态,都能在很短的、确定的时间内找出其中优先级最高的那个就绪任务。
如今,很多新的CPU都有一条计算前导零指令(CLZ)或功能类似的指令,比如32位PowerPC处理器的CLZ指令、Freescale S12X双核微控制器中的协处理器XGATE的Bit Field Find First One指令等。对于有这类硬件指令的CPU,无需再使用μC/OSII中的查表算法,可以利用这类指令优化任务调度算法。
实时系统有2类:软实时系统和硬实时系统。软实时系统中,各任务运行得越快越好,并不限定某一任务必须在多长时间内完成。硬实时系统要求系统中的任何函数都有确定的执行周期数,任务运行必须准时,执行时间不因任务多少而改变。大多数实时系统是二者的结合。μC/OSII中仅有一处不满足硬实时条件:OSTimeTick()函数需要遍历所有任务控制块,执行时间受任务数目的影响,而该函数由时钟节拍中断服务程序调用,因此时钟节拍中断服务程序的执行时间也受任务多少影响。通过把这部分工作放到一个专门的系统级任务中去做,便可以解决这个问题,使其成为一个满足硬实时条件的RTOS。对于Freescale公司的双核微控制器S12X,还可以通过把时钟节拍中断的处理交给协处理器来完成,从而实现硬实时条件,提高RTOS的实时性。
2 μC/OSIII的新特性
μC/OSIII已经不仅仅是一个RTOS内核,而是包含很多与该内核配套的软件开发包。和传统的大型商用RTOS类似,μC/OSIII能以传统的BSP(板级支持包)方式,实现诸如USB主机、文件系统、TCP/IP协议栈等,还包括RTOS本身的调试工具等。Micrium公司和很多软件公司合作,提供很多基于μC/OSIII的通用商业软件,如GUI、FS、USB、TCP/IP等。今后还会与更多的半导体厂商合作,提供更多商家的以ARM CortexM3/4为核心的μC/OSIII评估板。
μC/OSIII在功能上得到了全面的扩展和提升。μC/OSII最多支持255个任务,而μC/OSIII可以支持任意数目的任务,实际使用的任务数目仅受CPU所能使用的存储空间的限制。μC/OSIII可以支持任意数目的信号量、事件标志组、消息队列、存储块等内核对象,而且,为了避免在程序编译过程中出现资源不够分配的问题,允许用户在程序运行中动态配置内核资源。μC/OSII允许挂起某个任务,但挂起操作不可以嵌套,而μC/OSIII允许嵌套挂起某个任务,嵌套挂起最深可达250层。μC/OSIII增加了一个时钟节拍任务来做延时处理和超时判断。通过在任务级代码完成时钟节拍服务,能极大地减少中断延迟时间。而且,μC/OSIII使用了哈希散列表机制,进一步降低了延时处理和超时判断的开销,提高了系统的实时性。
除了功能上的扩展和提升,μC/OSIII还增加了一些新功能。μC/OSIII增加了时间片轮转调度,允许多个任务有相同的优先级。当多个优先级相同的任务同时就绪并且所属优先级高于其他所有就绪任务时,μC/OSIII轮转调度这些任务,让每个任务运行一段用户指定的时间长度(即时间片)。
μC/OSIII允许中断或任务直接给另一个任务发信号或消息。在实际应用中,很多情况下,编程人员知道该向哪个任务发信号或消息,这时就可以使用μC/OSIII的这种新功能来向目标任务直接发信号或消息,从而避免创建和使用诸如信号量或消息队列等内核对象作为中介,提高信号或消息发送的效率。μC/OSIII增加了时间戳功能,可以给信号或消息打上时间戳,从而允许用户获取某个事件发生的时刻,以及信号或消息传递到目标任务所耗费的时间等。
另外,μC/OSIII的设计能方便地按照CPU架构优化,特别是其数据类型可按照CPU能适应的最佳位数宽度修改,以适应8/16/32位的CPU。关键算法可采用汇编编程,以发挥一些有特殊指令的CPU的优势。很多CPU有读改写指令,可方便实现存储器访问的原子操作,有的CPU有计算前导零指令,可用来快速查找任务就绪表。
μC/OSIII增加了中断处理任务,可以把内核对象的处理工作都放到任务级代码中完成,从而允许通过给调度器上锁的方式实现临界段代码的保护,这样就使内核关中断的时钟周期几乎为零。μC/OSIII内置了对系统性能进行测试的代码,能够检测每个任务的执行时间、堆栈使用情况、每个任务运行的次数、CPU利用率、关闭中断和给调度器上锁的时间等。μC/OSIII还支持内核觉察式调试,可以以友好的方式对μC/OSIII的变量、数据结构进行检查和显示,并且带有μC/Probe调试工具,可在程序运行过程中察看和修改变量。
结语
相比μC/OSII,μC/OSIII做了很多改进,比如改进了任务调度方法、改进了时钟节拍管理机制、增加了中断处理任务、允许向任务直接发信号或消息、增加了时间戳功能、支持内核觉察式调试等。从这些改进来看,μC/OSIII比μC/OSII上升到一个更高的档次。其中,一些主要的改进,比如μC/OSIII的任务调度方法的改进、时钟节拍管理机制的改进、中断管理方法的改进等会在后续专题文章中详细介绍。