访问电脑版页面

导航:老古开发网手机版其他

嵌入式RTOS讲座(2)

导读:
关键字:
[编者按] RTOS是开发计算机嵌入式应用产品的有力工具,研究和掌握RTOS的思想方法有益于提高开发人员的水平,从而缩短产品开发周期、提高产品质量。从第7期起,学习园地连载《嵌入式RTOS讲座》,主要内容如下:什么是嵌入式RTOS;RTOS中的一些基本概念;介绍一个源码公开的实时内核;在PC机上实现该实时内核的运行;让该实时内核在8位单片机上运行;如何将该实时内核移植到32位CPU上。嵌入式RTOS讲座(2) 实时多任务系统中的一些基本概念清华MOTOROLA单片机应用开发研究中心邵贝贝许庆丰王若鹏实时系统的特点是,如果逻辑和时序出现偏差将会引起严重后果。有两种类型的实时系统:软实时系统和硬实时系统。软实时系统的宗旨是使各个任务运行得越快越好,并不要求限定某一任务必须在多长时间内完成;而在硬实时系统中,各任务不仅要执行无误,而且要做到准时。大多数实时系统是二者的结合。实时系统的应用涵盖广泛的领域,而多数实时系统又是嵌入式的。这意味着计算机在系统内部,而用户看不到。实时应用软件的设计一般比非实时应用软件设计难一些。实时系统的技术关键是如何保证系统的实时性。以下从不使用RTOS的系统说起。 1 不使用RTOS系统不使用RTOS系统也叫前后台系统。编写应用程序时先顺着一条线画好流程图,然后按照流程图来编程序。嵌入式应用的程序一般为一个无限循环,循环中调用相应的函数完成相应的操作,我们把这部分看成是后台行为。用中断来处理随机事件,这部分可以看成是前台行为。这样就构成了前后台系统。后台也可以叫作任务级,前台叫作中断级。后台程序逐个检查每个任务是否具备了运行条件,逐个完成相应的操作。时间要求苛刻的操作肯定是靠中断完成的。中断服务程序中置位一个事件发生了的标志,然后退出中断,待后台程序运行到检查这个标志的时候,才能完成事件处理,再将事件发生标志复位。如果把事件处理也放在中断服务中,中断服务程序就会变得特别长,影响后来的中断或其它中断。这种系统在处理信息的及时性上比实际可以做到的要差。也就是说,有办法做得更快一些。这个反映及时性的指标叫作任务级响应时间。最坏情况下的任务级响应时间取决于整个后台循环的执行时间,因为循环一圈的执行时间不是常数,程序经过某一点的准确时间也就不能确定。程序修改了,循环时序也会受影响。这种单任务程序的另一缺点是,如果这条线的任何一处因某种意外被破坏了,则整个系统就会“死机”。但这类系统的优点是简单,不需要什么RTOS,也没有什么RAM/ROM的额外开销,在相对简单的单片机产品中仍被广泛采用着。 2 任务与多任务以上引入了任务的概念,嵌入式RTOS中任务的概念与计算机操作系统中任务的概念有所不同。计算机操作系统中,任务是用户递交给计算机的一项工作。一个任务可以有许多进程,每个进程还可以有多个线程。在嵌入式RTOS中的一个任务,是指一个程序分段。这个分段被操作系统当作一个基本单元来调度,它大致相当于与计算机操作系统中的进程的概念。任务是一个可运行的简单程序,该程序可以认为CPU完全只属该程序自己。实时应用程序的设计过程,包括如何把问题分割成多个任务。每个任务都是整个应用的某一部分,每个任务被赋予一定的优先级,有它自己的一套CPU寄存器和自己的堆栈空间。典型地,每个任务都是一个无限的循环。每个任务都处在以下5种状态之一。这5种状态是:休眠态、就绪态、运行态、等待态和被中断态。休眠态相当于该任务驻留在内存中,但并不被多任务内核调度。就绪态指该任务已经准备好,可以运行了,但由于某种原因还暂时不能运行。运行态指该任务掌握了CPU的控制权,正在运行中。等待态指该任务在等待某一事件的发生,例如等待某外设的I/O操作,等待某共享资源由暂不能使用变成可以使用,等待定时脉冲的到来或等待超时信号的到来以结束目前的等待,等等。最后,发生中断时,CPU进行相应的中断服务,原来正在运行的任务暂不能运行,就进入了被中断状态。多任务运行的实现实际上是靠RTOS在许多任务之间切换、调度。CPU只有一个,轮番服务于一系列任务中的某一个任务。多任务运行使CPU的利用率得到最大的发挥,并使应用程序模块化。在实时应用中,多任务化的最大特点是,开发人员可以将很复杂的应用程序层次化。使用多任务,应用程序将更容易设计与维护。 3 任务切换与调度任务切换(context switch)在有的书中翻译成上下文切换,实际含义是任务切换或CPU寄存器内容切换。当多任务内核决定运行另外的任务时,它保存正在运行任务的当前状态(context),即CPU寄存器中的全部内容。这些内容保存在任务的当前状况存储区,也就是任务自己的栈区之中。入栈工作完成以后,就是把下一个将要运行任务的CPU寄存器状况从该任务的栈中重新装入到CPU的寄存器中,或者说恢复到CPU的寄存器中,并开始下一个任务的运行。这个过程叫作任务切换。任务的切换过程增加了应用程序的额外负荷。CPU的内部寄存器越多,额外负荷就越重。做任务切换所需要的时间取决于CPU有多少寄存器要入栈。实时内核的性能不应该以每秒钟能做多少次任务切换来评价。调度(scheduler),英文还有一词叫dispatch,也是调度的意思。这是内核的主要职责之一,是要决定该轮到哪个任务运行了。多数实时内核是基于优先级调度法的。每个任务根据其重要程度的不同被赋予一定的优先级。基于优先级的调度法,指CPU总是让处于就绪态的优先级最高的任务先运行。然而,究竟何时让高优先级任务掌握CPU的使用权,有两种不同的情况,这要看用的是什么类型的内核,是不可剥夺型的还是可剥夺型的内核。 4 嵌入式实时多任务系统 实时多任务系统是靠RTOS管理的。如同使用一般的计算机,开机以后先启动一个操作系统,Linux、Unix也好,然后是运行应用程序。应用程序由多个任务组成,这些任务相对独立又相互有关。Linux、Unix是分时的,有人把它们变成实时的,如实时Linux、Lynx等,办法是让事件中断的优先级由用户设置,直到高于定时器的优先级。这种系统性能肯定很不错,因为这类操作系统集中了计算机专家们上千人的劳动与智慧。问题是系统太大,内存的开销至少也有几百KB(字节),无法嵌入到一般的嵌入式应用类产品中去,于是着手对这样的系统进行裁剪。首先,在嵌入式应用中不需要文件系统,内存管理一般也可以省去,只剩下进程管理和I/O管理。进程管理在嵌入式系统中就是任务管理。每个I/O设备的管理也可以当若干个任务来管理。计算机的操作系统经过这样精简,剩下了面向嵌入式应用的部分,实时性变得更好,这部分通常称作实时内核。在嵌入式应用中,先在嵌入的计算机中运行一个实时内核,然后让这个实时内核管理应用程序中的各个任务,就形成了嵌入式实时多任务系统。从这种意义上说,实时内核就是嵌入式应用中所谓的实时操作系统RTOS。 5 实时内核(the real time kernel)多任务系统中,实时内核负责管理各个任务,或者说为每个任务分配CPU时间,并且负责任务之间的通信。内核提供的基本服务是任务切换。使用实时内核可以大大简化应用系统的设计,这是因为实时内核允许将应用分解成若干个任务,由实时内核来管理它们。内核本身也增加了应用程序的额外负荷,代码空间增加ROM的用量,内核本身的数据结构增加了RAM的用量。但更主要的是,每个任务要有自己的栈空间,而且要占很大的内存空间。内核本身对CPU的占用时间一般在2%~5%。实时内核可分为可剥夺型(preemptive)和不可剥夺型(non\ preemptive)两类。preemptive是抢占的意思。preemptive kernel翻译成抢占式(抢先式)内核就有点不好理解。以基于优先级的系统为例,preemptive kernel指内核可以剥夺正在运行着的任务的CPU使用权并将使用权交给进入就绪态的优先级更高的任务。是内核抢了CPU让别的任务占有。故笔者宁愿称之为可剥夺型或不可剥夺型。不可剥夺型RTOS在管理各个任务时“权威性”要差一些,它使用某种算法并决定让哪个任务运行后,就把CPU的控制权完全交给了这个任务,直到这个任务主动将CPU控制权还回来。中断依然发生,并由中断服务程序处理,中断可以激活一个休眠态的任务,使之进入就绪态;而这个进入就绪态的任务还不能运行,要等到当前运行的任务主动交出CPU的控制权。使用这种内核实时性比不使用RTOS的系统好很多,它的实时性取决于最长任务的执行时间。不可剥夺型内核的缺点也恰恰是这一点,如果最长任务的执行时间不能确定,系统的实时性就不能确定。可剥夺型内核的实时性最好,优先级高的任务只要具备了运行的条件,或者说进入了就绪态,就可以立即运行。也就是说,除了优先级最高的那个任务,其它任务在运行过程中都随时可能停下来,让给比它优先级高的任务先运行。只有这样做,才能保证系统的实时性;而这样做的后果是,如果任务之间的竞争问题处理不好,会产生系统崩溃、死机等严重后果。商品化的RTOS软件全部是可剥夺型的,贵在调度诸任务并将任务间竞争之类的问题解决得天衣无缝。以下介绍可剥夺型内核在调度各任务时,可能会出现的问题以及如何去解决。 6 任务优先级分配许多系统中,并非所有的任务都至关重要,不重要的任务自然优先级可以低一些。实时系统大多综合了软实时和硬实时这两种需求。软实时系统只是要求任务执行得尽量快,并不要求在某一特定时间内完成;硬实时系统中,任务不但要执行无误,还要准时完成。让我们从单调执行率调度法说起,以便于分配任务优先级的讨论。这种方法基于哪个任务执行的次数最频繁,执行最频繁的任务优先级最高。单调执行率调度法做了一系列假设: · 所有任务都是周期性的; · 任务间不需要同步,没有共享资源,没有任务间数据交换等问题; · CPU必须总是执行那个优先级最高且处于就绪态的任务。换句话说,要使用可剥夺型调度法。单调执行率调度法给出一系列n值表示系统中的不同任务数,要使所有的任务满足硬实时条件,必须使以下不等式成立,即单调执行率调度定理: ∑iti[]Ti≤n(21/n-1) 这里ti是任务i最长执行时间,Ti是任务i的执行周期。换句话说,ti/Ti是任务i所需的CPU时间。 n是系统中的任务数。只有一个任务时,关系式右边的值为1,CPU可以全归该任务使用;当任务数为2,3…时,关系式右边的值降为0.828,0779…;对于无穷多个任务,(21/n-1)的极限值是0693。这意味着基于单调执行率调度法,要任务都满足硬实时条件,所有有时间要求的任务总的CPU利用时间应小于70%!请注意,这是指有时间条件要求的任务,系统中当然还可以有对时间没有什么要求的任务,使得CPU的利用率能达到100%。但使CPU利用率达到100%并不好,因为那样,程序就没有修改的余地了,也无法增加新功能了。作为系统设计的一条原则,CPU利用率应小于70%。单调执行率调度法认为,最高执行率的任务具有最高的优先级,但在某些情况下,最高执行率的任务并非是最重要的任务。如果实际应用都真的像单调执行率调度法说的那样,也就没有什么优先级分配可讨论了。然而,讨论优先级分配问题,单调执行率调度法无疑是理解RTOS的一个切入点。 7 优先级反转问题使用实时内核,优先级反转是实时系统使用中出现得最多的问题。设想,有个最高优先级的任务要用打印机,而此时最低优先级的那个任务正在使用打印机,最高优先级的任务要等到最低优先级的任务用完并释放了打印机才能运行。这时,又有一些优先级在二者之间的任务不断进入就绪态,内核不断剥夺那个最低优先级任务的CPU使用权,让这些任务运行,尽管这些任务并不需要打印什么。于是,那个最低优先级的任务迟迟不能释放打印机,从而使最高优先级的任务迟迟不能运行。在这种情况下,最高优先级的任务实际上降到了优先级最低任务的优先级水平,于是优先级发生了反转。纠正的方法可以是,在低优先级的任务使用共享资源时,提升该任务优先级,任务完成时予以恢复。多任务内核应允许动态改变任务的优先级以避免发生优先级反转现象。然而,改变任务的优先级是很花时间的。如果该任务并没有被内核剥夺CPU使用权,花很多时间在共享资源使用前提升任务的优先级,然后,又在资源使用后花时间恢复任务的优先级,则无形中浪费了很多CPU时间。真正需要的是,为防止发生优先级反转,内核能自动变换任务的优先级,这叫作优先级继承。一些商品化的内核有优先级继承功能。使用不支持优先级继承的实时内核时,要注意人为造成优先级反转的可能。 8 任务间的竞争 实现任务间通信最简便的办法是使用共享数据结构。特别是当所有到达的任务都在一个单一地址空间下,能使用全程变量,包括指针、缓冲区、链表、循环缓冲区等,使用共享数据结构通信就更为容易。虽然共享数据区法简化了任务间的信息交换,但是必须保证每个任务在处理共享数据时的排它性,以避免竞争和数据的破坏。任务间的竞争首先表现在对共享资源的竞争上。任何任务所占有的实体都可以称为资源,如I/O设备、键盘、打印机、显示器等。使用中最容易被忽视而出问题的是共享内存,也就是全局变量。在RTOS下的每个任务编程时,要随时想到,如果此时CPU去响应中断了,程序会不会出问题?如果此时CPU使用权被剥夺了,又会怎样?例如,有一个16位计数器类型的I/O设备,CPU要分成2个8位来读取计数器的值,CPU刚刚读了1个8位,中断发生了,CPU做中断服务。在中断服务过程中,计数器的值发生了变化,到CPU读下1个8位并将2个8位合成1个16位时,就会出错。解决办法是在读寄存器前关中断,读完2个8位以后再开中断。在单任务程序中,这个过程很容易理解。RTOS中把这一类操作称为关键性操作,这种操作的代码称作临界区代码。避免竞争的方法是,在处理共享资源时使之满足互斥条件。与共享资源打交道时,使之满足互斥条件最一般的方法有: · 关中断; · 使用测试并置位指令; · 禁止做任务切换; · 利用信号量。 9 死锁死锁指两个任务无限期地互相等待对方控制着的资源。设任务i1正独享资源R1,任务i2在独享资源R2,而此时i1又要独享R2,i2也要独享R1,于是哪个任务都无法继续执行,发生了死锁。最简单的防止发生死锁的方法,是让每个任务都做到: · 先得到全部需要的资源再做下一步工作; · 用同样的顺序去申请多个资源; · 释放资源时使用相反的顺序。内核大多允许用户在申请信号量时定义等待超时,以此化解死锁。当等待时间超过了某一确定值时,信号量还是无效状态,就会返回某种形式的出现超时错误的代码。这个出错代码告知该任务,不是得到了资源使用权,而是系统错误。死锁一般发生在大型多任务系统中,在嵌入式系统中不易出现。 10 可重入性可重入函数可以被一个以上的任务调用,而不必担心数据的破坏。可重入函数任何时候都可以被中断,一段时间以后又可以运行,而相应数据不会丢失。可重入函数或者只使用局部变量,即变量保存在CPU寄存器中或堆栈中。如果某函数使用全局变量,又没有对全局变量予以保护,这个函数就不具备可重入性。不论这个函数是程序员自己写的还是来自C编译器的库函数。如果某任务调用了一个不可重入函数,在处理某全局变量过程中,CPU被另一个高优先的任务剥夺了,这个高优先级的任务改变了那个共享的全局变量,系统就会出错。应用程序中的不可重入函数引起的错误很可能在测试时发现不了,直到产品到了现场问题才出现。如果在多任务上您还是把新手,使用不可重入型函数时,千万要当心。同时要注意,使用的C编译器是否所有库函数都具有可重入性。使用以下技术之一即可使函数具有可重入性: · 只使用局部变量; · 处理全局变量之前关中断,调动后再开中断; · 用信号量禁止该函数在使用过程中被再次调用。 11 时钟节拍时钟节拍是特定的周期性中断。这个中断可以看作是系统心脏的脉动。中断之间的时间间隔取决于不同的应用,一般在10~200ms之间。时钟的节拍式中断使得内核可以将任务延时若干个整数时钟节拍,以及当任务等待事件发生时,提供等待超时的依据。时钟节拍率越快,系统的额外开销就越大。各种实时内核都有将任务延时若干个时钟节拍的功能。然而,这并不意味着延时的精度是1个时钟节拍,只是在每个时钟节拍中断到来时对任务延时做一次裁决而已。 12 信号与信号量(semaphore) 信号量实际上是一种约定机制,在多任务内核中普遍使用。信号量用于: · 控制共享资源的使用权(满足互斥条件); · 标志某事件的发生; · 使两个任务的行为同步。信号像是一把钥匙,任务要运行下去,得先拿到这把钥匙。如果信号已被别的任务占用,该任务只得被挂起,直到信号被当前使用者释放。换句话说,申请信号的任务是在说:“把钥匙给我,如果谁正在使用,我只好等待!”信号是只有两个值的变量,信号量是计数式的。信号是只取两个值0和1的量,因此也可以称之为信号量。信号和信号量在英语中都用semaphore 一词。计数式信号量的值可以是0~255或0~65535,取决于信号量规约机制使用的是8位还是16位。一般地说,对信号量只能实施三种操作:建立(create);等信号(wait),也可称作挂起(pend);给信号(signal)或发信号(post)。想要得到信号量的任务执行等待(wait)操作,如果该信号量有效(即信号量值大于0),则信号量值减1,任务得以继续运行;如果信号量的值为0,等待信号量的任务就被列入等待信号量任务表。多数内核允许用户定义等待超时,如果等待时间超过了某一设定值,该信号量还是无效,则等待信号量的任务进入就绪态准备运行,并返回出错代码(指出发生了等待超时错误)。任务以发信号操作(signal)释放信号量。如果没有任务在等待信号量,信号量的值仅仅是简单地加1;如果有任务在等待该信号量,那么就会有一个任务进入就绪态,信号量的值也就不加1。于是钥匙给了等待信号量的诸任务中的一个任务。至于给了哪个任务,要看内核是如何调度的。当诸任务共享输入输出设备时,信号量特别有用。可以想象,如果允许两个任务同时给打印机送数据时会出现什么现象:打印机会打出相互交叉的两个任务的数据。计数式信号量用于某资源可以同时为几个任务共享。例如,用信号量管理缓冲区阵列。缓冲区阵列中共有10个缓冲区,就好像有10把钥匙可以发给诸任务。当所有的钥匙都用完了,申请缓冲区的任务被挂起,直到信号量重新变为有效。缓冲区管理程序在处理链表指针时,为满足互斥条件,中断是关掉的(这一操作非常快)。任务使用完某一缓冲区,通过调用缓冲区释放函数将缓冲区还给系统。系统先将该缓冲区指针插入到空闲缓冲区链表中,然后再给信号量加1或释放该信号量。这一过程隐含在缓冲区申请函数和缓冲区释放函数之中,调用这两个函数的任务不用管函数内部的详细过程,RTOS已经替用户做好了。信号量主要用于任务间的通信与同步。在RTOS中常用的手段还有邮箱、消息队列等。信号量常被用过了头。处理简单的共享变量也使用信号量则是多余的。请求和释放信号量的过程是要花相当的时间的,有时这种额外的负荷是不必要的。用户可能只需要关中断、开中断来处理简单共享变量,以提高效率。假如两个任务共享一个32位的整数变量,一个任务给这个变量加1,另一个任务给这个变量清0。如果注意到不管哪种操作,对微处理器来说,只花极短的时间,就不会使用信号量来满足互斥条件了。每个任务只须操作这个任务前关中断,之后再开中断就可以了。然而,如果这个变量是浮点数,而相应微处理器又没有硬件的浮点协处理器,浮点运算的时间相当长,关中断时间长了会影响中断延迟时间,这种情况下就有必要使用信号量了。 Jean J.Labrosse写的《μC/OS\ II The Real Time Kernel》一书对RTOS原理作了更详尽的叙述。该书由美国R&D出版社出版,相应的中译本由中国电力出版社出版。(待续)
来源:单片机与嵌入式系统应用   作者:清华MOTOROLA单片机应用开发研究中心 邵贝贝 许庆丰 王若鹏  2006/2/12 0:00:00
栏目: [ ]

相关阅读

安森美推出新的高功率图腾柱PFC控制器,满足具挑战的能效标准

动态功耗低至60μA/MHz!助力设备超长续航,首选国民技术低功耗MCU!