关键词:嵌入式系统 实时内核 时间片 任务分割
引言
随着工业的飞速发展,人们对系统实时性的要求越来越高。计算机技术的进步客观上也为进一步提高实时性提供了可能。因此近年来,嵌入式实时系统的研究已经成为单片同应用领域的又一大热点,实编排软件也越来越多,有商业软件,也有免费的代码。然而影响系统实时性的因素很多,有硬件,也有软件的。这就决定了提高系统的实时性并不是一件十分容易的事情,除了使用高性能的CPU和高效的实时内核外,在实时系统应用的过程中,还要结合具体情况进行具体分析,充分利用CPU的效率,挖掘内核的实时潜能。
1 任务与嵌入式多任务实时系统
1.1 任务与多任务
在嵌入式多任务实时系统时,任务是指一个程序分段。这个分段被操作系统当作一个基本单元来调度。
典型地,每个任务都是一个无限的循环,而且在同一时刻只能处于以下5种状态之一。这5种状态是休眠态、就绪态、运行态、等待态和被中断态,如图1所示。
多任务系统的执行过程实际上就是一系列任在这5种状态中循环流动、轮流被内核调度的过程。多任务运行使CPU的利用率得到最大的发挥,并使应用程序模块化。
1.2 嵌入式多任务实时系统
RTOS本质上就是嵌入的实时内核,它负责管理各个任务,或者说是为每上任务分配CPU时间,并且负责任务之间的通信。实时内核可分为可剥夺型和不同剥夺型两类。因此,按照所使用内核的不同,嵌入式实时系统也可分为两类:使用不可剥夺型内核的嵌入式实时系统和使用可剥夺型内核的嵌入式实时系统。
2 实时系统中的长任务问题
2.1 长任务的定义
在RTOS中,长任务就是指整个任务的执行时间较长,超出了RTOS中其它某一个或某几个任务的实时要求容限,而对整个RTOS的实时性构成威胁的那些任务。
2.2 长任务对RTOS的影响
当使用可剥夺型实时内核时,长任务由于执行的时间较长,因而更容易被高优先级的任务打断;一旦高优先级的任务进入了就绪态,当前任务的CPU使用权就被剥夺了,或者说任务被挂起了,那个高优先级的任务立刻得到了CPU的控制权。这样会出现两个问题:一是长任务可能在一次执行的过程中被频敏打断,长时间得不到一次完整的执行;二是长任务被打断时,可能要保存大量的现场信息,其目的是为了保证在高优先级的任务执行完返回后,长任务能得以继续执行。然而,这样做要占用一定的系统资源,同时保存现场本身也是要占用CPU时间的,因此,实时性也会下降。
当使用不可剥夺型实时内核时,长任务对RTOS的影响更为明显,因为在这种内核中,任务级响应时间取决于最长的任务执行时间。这也就是说由于长任务的存在,任务级的响应时间要变长。其结果是CPU长时间停留在长任务中,其它的任务得不到实时的响应,甚至于根本得不到执行,系统的实时性势必要下降。
总之,无论是使用可剥夺型内核,还是使用不可剥夺型内核,长任务都会对RTOS构成严重的威胁。
3 长任务问题的解决
解决长任务问题最有效的途径是进行任务分割。所谓任务分割指将影响系统实时性的长任务分割成若干个小任务。这样单个任务的执行时间变短,系统的任务级响应时间变短,实时性提高。
3.1 对RTOS的分析与计算
当然,长任务的分割必须结合系统中所使用的内核,以及各任务对实时性的要求情况,进行必要的分析计算,才能保证分割的合理性和有效怀,具体的步骤如下:
①分析系统共有多少个任务,这些任务对实时性的要求有多高,求出各个任务所要求的最小执行频率f1,f2,f3……fn。
②计算目前各任务的实际执行时间t1,t2,t3……tn。
③确定系统中的长任务
如果max(t1,t2,t3……tn)≤min(1/f1,1/f2,1/f3……1/fn)
则此系统中不存在长任务。
如果max(t1,t2,t3……tn)>min(1/f1,1/f2,1/f3……1/fn)
则存在长任务,而且执行时间为max(t1,t2,t3……tn)的那个任务就是要找的长任务。
④分析此长任务是否需要分割
分析一下是什么原因导致执行的时间过长,这个时间还能够通过程序的优化来缩短?如果能,则不需要进行任务分割;否则要对这个长任务进行分割。
3.2 任务分割
常用的任务分割的方法有以下两种:
①将长任务按功能分为若干个小模块,每一个模块构成一个小任务,每个小任务执行一个相对独立的功能,且要保证执行时间t<min(1/f1,1/f2,1/f3……1/fn)。各个任务被内核顺序调用,合起来完成整个任务的功能。
②有的长任务比较特殊,例如键盘任务和动态LED显示任务,很难按照方法1所说的把它分成若干个功能相对独立的小模块。这时,一般是按照方便保存现场信息原则,强制将其分割成若干个小任务,每个任务在min(1/f1,1/f2,1/f3……1/fn)时间内主动保存现场信息、放弃CPU的控制权,等到再次被内核调度时继续执行。
这种分割方法相对复杂,各任务之间界限不是很明显,看似未经分割,但实际上它确实是由多次任务中断来完成。下面就以这种分割方法为例具体说明。
4 实例分析
4.1 系统介绍
在此,系统的硬件基础是基于MC68HC908GP32单片机系统的,用其普通I/O口作为矩阵式键盘的输入输出引脚;软件基础是在MC68HC908GP32中运行Motorola公司的Joanne Santangeli编写的基于时间片的不可剥夺的实时内核,如图2所示。
此内核主要是利用微控制器内部的时间模块产生恒定的实时中断,将CPU的运行时间分成一个个时间片。内核的任务调度工作都是在时间片的开始阶段完成的,而每个任务都必须在单个时间片内完成。
在这个内核中,每0.5ms发生1次时钟中断,而每10次时钟中断组成了1个时间片(5ms)。任务1的优先级最高,每2个时间片(10ms)会执行1次,任务2每4个时间片(20ms)执行1次,优先级最低的任务6则每64个时间片(320ms)会执行1次。
4.2 系统中的键盘任务问题
在单片机系统中,键盘主要用于输入数据、代码和命令,因此系统必须循环不停地扫描扫描;一是有键波按下,CPU立即做出响应。键盘任务子程序也是根据这个要求而设计的。一般有两种处理方式:一是中断方式,二是查询方式。从有键按下时开始,到按键释放并转相应子程序而终止。该任务被内核调度的情况如图3所示。
图3中,Δt是人手按键的时间,一般为100~300ms。为了能说明问题,这里取100ms。
令 t1'-t1=Δt1,t2'-t2=Δt2
则一次键盘任务的执行时间
Δt'=t'2-t'1=t2+(t'2-t2)-[t1+(t'1-t1)]=
t2+Δt2-t1-Δt1=
t2-t1+(Δt2+Δt1)=
Δt+(Δt2-Δt1)
由图3可知
Δt1≤tms Δt2≤5ms
实际上,由于两次任务执行的情况不完全相同,Δt1与Δt2可能会有相当于几个指令周期的时间差异,但也只是μs级的误差。而且,这里是以时间片的形式来计算的,所以依然可以认为
Δt2-Δt1=0
因而有
Δt'=Δt+(Δt2-Δt1)=Δt=100ms(20个时间片)
也就是说,在这20个时钟片内只执行1次键盘任务,大部分的时间都在空等待。在此期间,系统中会有20-1=19次其它任务的执行被错过,图3中虚线所示就是在此100ms期间被错过执行的19个任务。显然,这在大多数多任务系统中都是不允许的。
因此,在这个多任务实时系统中,键盘任务是个典型的长任务,要使其它19次任务中断都有被应用的机会,必须对该键盘任务进行分割。
4.3 键盘任务的分割
键盘分割的方法是将一次键盘任务分成多个小任务,通过多次任务中断来完成。我们将其放在任务4中(80ms执行1次)。这样有ttask4≤ttask≤2ttask4,即可以保证键盘任务完整可靠地执行,又提高了CPU的效率。图4是分割后的键盘任务的执行过程。
从图4可以看出,1次完整的键盘任务是由2~3次任务中断来完成的。情况a中,每一次任务中断发生在ta1时刻,在接下来的一个时间片(5ms)内,检测到有键按下,调用查询值任务;第一次任务中断发生在ta2时刻,在接下来的一个时间片(5ms)内,检测到按键已释放,跳转并执行相应键处理程序。
情况b中,第二次任务中断时(tb2时刻),键还没有松开,因此实际上什么也不做;第三次中断(tb3时刻)才跳到与键值对应的子程序。
通过这样的分割,每个子任务都可以在5ms内完成。如果系统中还有大于5ms的长任务的话,可按此法继续进行分割;如果没有的话,系统任务级响应时间一定小于5ms。这样,此系统的实时性大大提高,由100ms提高到5ms。本刊网络补充版(http://www.dpj.com.cn)中,介绍了此任务改进后的部分源程序。
结语
通过任务分割,可以显著地提高多任务系统的实时性。本文改进后的源程序已经在基于MC68HC908GP32的温室控制器中成功地运行过。除此以外,还成功地对LED和SCI任务进行了分割。改进后,除了实时性大大提高外,CPU的执行效率也有显著提高。