μC/OSII的时钟中断技术研究
1 系统中断与时钟节拍
1.1 系统中断
中断是一种硬件机制,用于通知CPU有个异步事件发生了。中断一旦被系统识别,CPU则保存部分(或全部)现场(context),即部分(或全部)寄存器的值,跳转到专门的子程序,称为中断服务子程序(ISR)。中断服务子程序做事件处理,处理完成后执行任务调度,程序回到就绪态优先级最高的任务开始运行(对于可剥夺型内核)。
中断使得CPU可以在事件发生时才予以处理,而不必让微处理器连续不断地查询(polling)是否有事件发生。通过两条特殊指令:关中断(disable interrupt)和开中断(enable interrupt)可以让微处理器不响应或响应中断。在实时环境中,关中断的时间应尽量的短,关中断影响中断响应时间,关中断时间太长可能会引起中断丢失。中断服务的处理时间应该尽可能的短,中断服务所做的事情应该尽可能的少,应把大部分工作留给任务去做。
1.2 系统时钟节拍
时钟节拍是特定的周期性中断(时钟中断),这个中断可以看作是系统心脏的脉动。操作系统通过时钟中断来确定时间间隔,实现时间的延时及确定任务超时。中断之间的时间间隔取决于不同的应用,一般在10~200 ms之间。时钟的节拍式中断使得内核可以将任务延时若干个整数时钟节拍,以及当任务等待事件发生时提供等待超时的依据。时钟节拍频率越快,系统的额外开销就越大。系统定义了32位无符号整数OSTime来记录系统启动后时钟滴答的数目。用户必须在多任务系统启动以后再开启时钟节拍器,也就是在调用OSStart()之后。μC/OSII中的时钟节拍服务是通过在中断服务子程序中调用OSTimeTick()实现的。时钟节拍中断服务子程序的示意代码如下:
void OSTickISR(void) {
保存处理器寄存器的值;
调用OSIntEnter ()或是将OSIntNesting加1;
调用OSTimeTick ();
调用OSIntExit ();
恢复处理器寄存器的值;
执行中断返回指令;
}
2 时钟管理系统
2.1 μC/OSII时钟管理系统
μC/OSII原有的时钟管理系统类似于Linux,但是比Linux简单得多。它仅向用户提供一个周期性的信号OSTime,时钟频率可以设置在10~100 Hz,时钟硬件周期性地向CPU发出时钟中断,系统周期性响应时钟中断,每次时钟中断到来时,中断处理程序更新一个全局变量OSTime。μC/OSII时钟中断服务程序的核心是调用OSTimeTick ()函数。OSTimeTick ()函数用来判断延时任务是否延时结束从而将其置于就绪态。其程序伪代码如下:
void OSTimeTick(void) {
OSTimeTickHook();// 调用用户定义的时钟节拍外连函数
while { (除空闲任务外的所有任务)
OS_ENTER_CRITICAL();//关中断
对所有任务的延时时间递减;
扫描时间到期的任务,并且唤醒该任务;
OS_EXIT_CRITICAL();//开中断
指针指向下一个任务;
}
OSTime++;//累计从开机以来的时间
}
在μC/OSII的时钟节拍函数中,需要执行用户定义的时钟节拍外连函数OSTimeTickHook (),以及对任务链表进行扫描并且递减任务的延时。这样就造成了时钟节拍函数OSTimeTick ()有两点不足:
① 在时钟中断中处理额外的任务OSTimeIickHook (),这样增加了中断处理的负担,影响了定时服务的准确性;
② 在关中断情况下扫描任务链表,任务越多所需要时间越长,而长时间关中断对中断响应有不利影响,是中断处理应当避免的。
2.2 改进的时钟管理系统
针对上述OSTimeTick ()的不足之处,需加以改进来优化时钟节拍函数。在Linux中一般对中断的响应分为两部分:立即中断服务和底半中断处理(bottom half)。立即中断服务仅仅做重要的并且能快速完成的工作,而把不太重要的需要较长时间完成的工作放在底半处理部分来完成,这样就可以提高中断响应速度。
μC/OSII不支持底半处理,为了减轻时钟中断处理程序的工作量来提高μC/OSII的时钟精确度,可以将一部分在每次时钟中断需处理的工作内容放在任务级来完成。这样就可以减少每次时钟中断处理的CPU消耗,从而提高中断响应速度和μC/OSII的时钟精确度。为此,定义任务OSTimeTask (),由它来处理原来在OSTimeTick()中需要处理的操作。因为μC/OSII采用基于优先级的抢占式调度策略,而每次时钟中断处理程序结束后需要首先调度该任务执行,因此让任务OSTimeTask()具有系统内最高优先级。由它执行用户定义的时钟节拍外连函数OSTimeTickHook (),以及对所有任务的延时时间进行递减,并把到期的任务链入到链表OSTCBRList中,OSTCBRList管理所有到期任务。OSTimeTask()函数伪代码如下:
void OSTimeTask() {
OSTimeTickHook()//用户定义的时间处理函数
while { (除空闲任务外的所有任务)
对所有任务的延
- LPC2292的伪中断与伪中断处理(03-25)
- Linux 2.4.x内核软中断机制(04-06)
- 嵌入式系统开发之中断控制的实现(04-18)
- uC/OS-II的任务切换机理及中断调度优化(05-11)
- 微内核RTOS的核外中断管理(07-27)
- TMS320C54x系列DSP的中断机制(08-08)