嵌入式实时操作系统VxWorks提供的中断处理机制中断延迟小,应用编程方便。MPC860是目前在网络与通信领域应用非常广泛的一款微处理器芯片。论文详细分析了VxWorks及MPC860的中断处理机制,阐述了中断处理应用编程的过程,并给出了应用实例。
1 引言
中断是外部事件通知操作系统的最常用手段。中断处理机制是计算机多任务环境运行的基础,是系统实时性的保证[1]。
VxWorks是美国Wind River公司于1983年设计开发的一种嵌入式实时操作系统。内核wind在任务调度、中断处理及网络处理等方面与其它嵌入式实时操作系统相比具有一定的优势。特别是其提供的微秒级的中断处理为VxWorks在嵌入式实时操作系统领域的旗舰地位奠定了基础。
Motorola公司推出的MPC860是目前在网络与通信领域应用非常广泛的一款微处理器芯片。高速的PowerPC内核,连同集成的网络与通信外围设备,为用户提供了一个建立高端通信系统的全新系统解决方案。因其体系结构与通用的x86体系结构有很大的不同,理解其中断处理机制及编写相应的中断处理程序成为系统移植与应用中的难点。
2 VxWorks下的中断处理机制
2.1 中断处理的实时性设计
VxWorks采用中断处理与普通任务分别在不同的栈中处理的中断处理机制[2]。中断处理程序运行于一种特殊的上下文环境中,没有任务控制块(Task Control Block, TCB),这使得中断的产生只会引发一些关键寄存器的存储而不会导致任务上下文的切换,从而减小了中断延迟。
VxWorks下的中断服务程序(ISR, Interrupt Service Routine)只完成在最小时间内通告中断的发生,而将其它的非实时处理尽量通过中断与任务间的通信机制放在被引发的任务上下文中来完成,类似于Linux中的底半处理机制,这样既可以避开中断服务程序编写的种种限制,又进一步缩小了中断延迟。
VxWorks在内核Wind中普遍采用被高度优化的信号量而不是关中断来实现互斥访问,这也对缩小中断延迟有一定的贡献。
2.2 方便的中断编程接口
为了让用户方便的使用C语言编写中断服务程序来实现对中断的控制,VxWorks在体系结构无关例程库intLib和体系结构相关例程库intArchLib中提供了系统接口函数[3]。对于应用程序员一般只需了解intLib库即可,而BSP(Board Support Packet,板级支持包)程序员则还需要了解intArchLib库。对例程库的详细描述请参见参考文献[3]。
接口函数中最常用的是在intLib库中提供的中断连接函数intConnect()。其函数原型为
STATUS intConnect
(
VOIDFUNCPTR * vector,/*需要连接的外部中断向量*/
VOIDFUNCPTR routine,/*中断发生时调用的中断服务程序*/
int parameter /*传递给中断服务程序的参数*/
)
该函数将指定的中断服务程序routine与指定的外部事件中断向量vector相关联。当指定的外部中断事件发生时,该函数以指定的参数parameter为参数,调用中断服务程序,完成相应的中断服务。
3 MPC860的中断处理机制
MPC860[4]有三个主要组成部分:嵌入式PowerPC内核(Core)、系统接口单元(SIU,System Interface Unit)和通信处理模块(CPM, Communications Processor Module)。MPC860属于双处理器体系结构。嵌入式PowerPC内核是主处理单元,包括高速缓存(CACHE)和内存管理单元(MMU),它是一个RISC芯片,通常开发编译后的程序指令都是由它执行。通信处理模块内部也集成了一个RISC微处理器,对各种常用的通信模块进行管理。由于CPM 分担了嵌入式PowerPC内核的外围工作任务,这种双处理器体系结构功耗低于传统体系结构的处理器。系统接口单元主要提供内外总线的接口,以及一些其它功能如SIU中断的管理等。
3.1 MPC860的中断体系结构
MPC860的中断体系结构有三个模块:PowerPC内核、SIU中断控制器(SIU Interrupt Controller)和CPM中断控制器(CPM Interrupt Controller)。如图1所示。
CPM中断控制器对通信处理模块的各个中断进行管理,它接收12个外部中断源和17个内部中断源的中断请求,经过屏蔽和判优处理后,把中断请求送往SIU中断控制器。CPM中断控制器为每个中断源分配了一个中断向量号,并且分配了不同的优先级,还可以编程设定哪个中断源为最高优先级。所有的CPM中断在SIU中断控制器中产生的中断向量号都是一样的。
图1 MPC860中断体系结构
SIU中断控制器负责管理8个外部中断源(IRQ0~7)和8个内部中断源(Level0~7),其中IRQ0一般用作不可屏蔽中断,通过NMI向PowerPC内核请求中断,其余15个通过外部中断引脚IREQ请求中断。对于8个内部中断源,包括时间基准(TB)、周期性的中断定时器(PIT)、实时时钟(RTC)、PCMCIA以及CPM等,用户可以通过对寄存器的操作,把它们设定为Level0~7中的任何一级。SIU中断控制器已经设定了这16个中断源之间的优先级,其中IRQ0的优先级最高,Level0其次,IRQ1再次,依此类推,Level7的优先级最低。
PowerPC内核接收到中断请求信号后,保存内核中断现场,即将程序计数器保存到SRR0,机器状态寄存器(MSR,Machine State Register)保存到SRR1,并改变MSR相关的信息,然后按异常向量表转入外部中断偏移地址处(0x500)执行最大长度为256个字节的SIU中断服务程序,完成中断服务。
3.2 中断处理流程
MPC860的中断处理流程如图2所示。内核在收到中断请求,保存中断现场后执行SIU中断服务程序。首先保存用户中断现场,保存关键寄存器到中断堆栈,并设置堆栈入口,然后读取产生SIU中断的中断向量号,根据中断向量号判断中断源,再跳转到各个中断源相应的服务程序中执行。读到的中断向量号如果对应的是CPM,要转入CPM中断服务程序中执行。在CPM中断服务程序中,首先内核将CPM中断向量寄存器(CIVR,CPM Interrupt Vector Register)的IV位置1,然后读取CPM中断向量号,再根据中断向量号调用对应的中断服务程序。这样,所有的CPM中断源,在进入中断处理程序之前,都经过了SIU中断控制器和CPM中断控制器两级处理。另外,由于MPC860是RISC处理器,它有许多通用寄存器,在中断服务程序中应该把影响到的关键寄存器压入到堆栈中,在退出中断服务程序之前再恢复。
图2 MPC860的中断处理流程
4 中断处理应用编程
实际中断处理应用编程主要包括两部分工作:一是编写中断初始化程序,进行初始化和中断连接;二是编写中断服务程序完成中断服务功能。
4.1 编写中断初始化程序
中断初始化程序的首要工作是初始化中断寄存器,包括打开SIU中断屏蔽寄存器(SIMASK,SIU Interrupt Mask)对应的屏蔽位,使能外部中断。如果是SIU的外部中断,应该初始化SIU中断边沿/电平寄存器(SIEL,SIU Interrupt Edge/Level Register),以设定中断是下降沿触发还是低电平触发。如果使用了CPM中断,还应该初始化CPM中断配置寄存器(CICR,CPM Interrupt Configuration Register)和CPM中断屏蔽寄存器(CIMR,CPM Interrupt Mask Register),以设定CPM在SIU中断控制器中的中断优先级,以及其内部的最高优先级中断源。对于子块可屏蔽中断源,还应该打开对应的事件屏蔽寄存器。
中断初始化程序还必须把SIU中断服务程序放到正确的位置。在VxWorks环境下调用intConnect()函数即将中断服务程序与外部中断源连接起来。
4.2 编写中断服务程序
由于中断服务程序不是在规则的任务上下文中运行(它没有任务控制块,中断处理程序共享一个堆栈等),中断服务程序必须遵守一个基本约束:它必须不能调用可能直接或间接导致阻塞的函数。例如,ISR不能获取信号量,但可以释放信号量;ISR不能直接或间接调用内存操作函数malloc()和free();ISR不能通过VxWorks驱动来执行I/O操作,但VxWorks的管道驱动程序是一个例外;ISR也不能使用printf()进行打印,VxWorks专门为ISR打印信息设计了一个记录功能,允许向系统输出平台打印文本信息。具体能被中断服务程序调用的函数请参见参考文献[5]。
由于中断服务通常涉及到任务级代码,并且中断服务程序受到种种限制,VxWorks支持在中断级运行的中断服务程序直接与一般任务进行通信。其通信机制有共享数据结构、信号量、消息队列、管道、信号等。其中,信号量是VxWorks提高中断服务程序与任务的合作性能的最好机制。理想情况下,一个中断服务程序仅仅调用semGive()函数释放一个信号量,发起一个任务来完成必要的处理[6]。
5 中断处理应用实例
下面给出VxWorks下MPC860的中断处理的应用实例。我们在某项目开发中利用中断通知MPC860读取外围器件FIFO的数据。相关的硬件连接如图3所示。
图3 中断处理应用实例的硬件连接
其中,FIFO采用IDT公司的IDT72V3650芯片,FPGA采用ALTERA公司APEX20K系列的EP20K1500E器件。FIFO芯片提供了五个空满状态标志位,可根据不同的实际需求方便的通过FPGA编程向MPC860的IRQ2和IRQ1分别发送开始读信号和停止读信号,从而在时钟的驱动下读取FIFO数据。
中断应用程序的主要实现函数的代码及注释如下:
/***初始化,中断连接***/
void tRdFifoInit(void)
{
*SIEL(RegBase)|=0x28000000; /*设置外部中断源IRQ1、IRQ2下降沿触发*/
startSem=semBCreate(SEM_Q_FIFO,SEM_EMPTY);
/*创建二进制信号量,以便实现中断与任务的通信*/
intConnect(IV_IRQ1,(VOIDFUNCPTR)stopRdISR,NULL);
intConnect(IV_IRQ2,(VOIDFUNCPTR)startRdISR,NULL);
/*分别将外部中断源与中断服务程序相连接*/
intEnable(IVEC_TO_INUM(IV_IRQ1)); intEnable(IVEC_TO_INUM(IV_IRQ2));
/*分别使能外部中断*/
}
/***开始读FIFO中断服务程序***/
void startRdISR(void)
{
semGive(startSem);
/*释放信号量*/
RdFlag=1;
/*设置读FIFO数据标志*/
*SIPEND(RegBase)=0x08000000;
/*清除外部中断源IRQ2的状态位*/
}
/***停止读FIFO中断服务程序***/
void stopRdISR(void)
{
RdFlag=0;
/*禁止读FIFO数据标志*/
*SIPEND(RegBase)=0x20000000;
/*清除外部中断源IRQ1的状态位*/
}
/***按照中断通知读取FIFO数据***/
void tRdFifo(void)
{
while(1)
{
semTake(startSem,WAIT_FOREVER);
/*获取信号量*/
while(RdFlag)
{
…/*读取FIFO数据*/
}
}
}
6 结束语
嵌入式实时操作系统VxWorks提供的中断处理机制中断延迟小、用户编程方便,被广泛应用于实际工程中。MPC860的中断体系结构是理解如PowerPC系列芯片等双处理器体系结构的中断处理机制的难点。本文在详细分析两者中断处理机制的基础上介绍了具体的开发实例。该实例已在TornadoⅡ 2.0.2版本上调试通过,并成功应用于某型网络设备开发中。