目录
Windows CE中断处理机制
物理中断请求(Interrupt ReQuest,IRQ)
↓
OAL把物理中断信号映射成OEM定义的逻辑中断信号,如SYSINTR_KEYBOARD;
(硬件平台上产生的IRQ可能会不同,但是当键盘中断产生式,这些IRQ被统一转换成SYSINTR_KEYBOARD)
↓
内核模式的中断服务例程(ISR,Interrupt Service Routine)
ISR实际上是处理IRQ中断,然后返回相应的系统中断SYSINTR给内核
↓
用户模式的中断服务线程(Interrupt Service Thread,IST)
内核会根据相应的SYSINTR触发相应的IST来完成中断处理。
1.Windows CE下中断的基本概
大多数外部设备都会产生中断来请求操作系统服务。一般情况下,外部设备并不占用CPU,只有当外设工作时,才会通过中断来打断CPU的当前执行,请求CPU处理外部设备的数据。这时CPU会暂停当前的工作,来处理外部设备提出的请求。例如,用户按下键盘上的箭会产生键盘中断。因为外设会产生中断,所以,外设相对应的驱动程序就要处理这些中断。
在Windows CE中使用逻辑中断(SYSINTR)的概念,当中断发生时,OAL(功能上看,OAL颇似桌面机上的BIOS,具有初始化设备、引导操作系统以及抽象硬件功能等作用。与B10S不同的是,0AL隶属于操作系统)
需要把物理的中断信号映射成OEM定义的逻辑的中断信号。然后供操作系统和驱动程序调用,逻辑中断是对硬件物理中断的很好的抽象。
Windows CE下的中断处理分为两个阶段,
处于内核模式的中断服务例程(ISR,Interrupt Service Routine)
和
处于用户模式的中断服务线程(IST,Interrupt Service Thread)。
ISR与IRQ是一对N的关系,也就是说每个IRQ都对应一个ISR,但是一个ISR可以处理多个IRQ。大致来讲,ISR负责把IRQ转化成逻辑中断并返回给内核,IST则负责中断的逻辑处理。
这里要提到两个概念:IRQ和SYSINTR。IRQ是指物理中断或者叫硬件中断,而SYSINTR指的是系统中断(虚拟中断或者逻辑中断)每一个IRQ会和一个系统中断SYSINTR相对应,当硬件中断产生时,ISR实际上是处理IRQ中断,然后返回相应的系统中断SYSINTR给内核,内核会根据相应的SYSINTR触发相应的IST来完成中断处理。
IRQ和SYSINTR之间的对应关系称为映射,分为静态映射和动态映射。静态映射是指在系统编译时IRQ已经和SYSINTR相对应,一般通过OALIntrStaticTranslate函数来实现。而动态映射是指WinCE系统启动后,动态关联IRQ与SYSINTR,一般通过KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR…)来实现。
SYSINTR的类型在nkintr.h中定义,OEMInterruptHandler函数在处理完中断以后,会返回不同类型的SYSINTR给内核,内核会根据返回值进行下一步操作,分为以下几种类型:
SYSINTR_NOP:表示不需要进行任何处理
SYSINTR_RESCHED:表示要进行一次系统调度
SYSINTR_CHAIN:表示不是该中断源产生,在中断链中寻找下一个中断
SYSINTR_RTC_ALARM:表示RTC报警产生
SYSINTR_TIMING:用于ILTiming测试
SYSINTR_PROFILE:用于系统的profile
SYSINTR_FIRMWARE:用于用户自定义系统中断号,所有自定义的系统中断号都应该基于该值进行累加加1,这些自定义的系统中断号用于和IRQ一一对应
Windows CE中断处理模型
Windows CE中断体系结构
ISR的返回值
SYSINTR_NOP:中断不与设备的任何已注册 ISR 关联。内核启用所有其他中断。
SYSINTR_RESCHED:OS重新调度的计时器到期,OS进行重新调度。
SYSINTR_XXX,逻辑中断号:中断与已知的已注册ISR和设备关联。
2.中断服务例程ISR
ISR是运行在内核中的一段代码。通常是由OEM(OAL,OEM Adaption Layer)实现的。ISR会检查中断并决定如何处理该中断。如果中断需要被内核和IST进一步处理,ISR会返回一个逻辑的中断号SYSINTR_XXX。如果该中断不需要进一步的处理了,ISR只需要返回SYSINTR_NOP给内核。ISR必须非常高效,以避免对设备操作的滞后和对所有低优先级ISR处理的滞后。
从Windows CE 4.0开始,引入了可安装的ISR(IISR,Installable Interrupt Service Routine)。在没有可安装的ISR之前,如果应用程序开发商在通用总线上加载了自己的外设,并且需要处理该外设的中断,通常应用开发商需要找到硬件OEM上请求更改OAL的源代码以添加对词外设的逻辑中断支持。有了IISR之后,应用程序开发商只需要安装自己的ISR就完全可以处理这一切了。同样,有了IISR,多个设备可以共享同一个硬件IRQ了。要将ISR安装到平台中,需要完成两个步骤:
1.调用LoadIntChainHandler函数以加载包含ISR代码的DLL。
2.该ISR需要把IRQ转化为某个SYSINTR_XXX并返回。
LoadIntChainHandler函数将包含IISR代码的动态链接库加载到内核的地址空间中。这意味着代码不能调用任何非内核函数,包括任何C语言运行时库函数。我们必须检查所有代码以确保不需要任何外部库(即使这些库是由编译器自动产生的)。
3.中断服务线程IST
IST线程大多数时候是空闲的,只有操作系统通知IST有中断发生的时候IST才开始工作。这是通过把一个逻辑中断号与一个Win32的同步对象事件相关联实现的,当有中断发生时,操作系统会引发与该逻辑中断相关联的事件。
在IST中,通常会使用到
InterruptInitialize(),
WaitForSingleObject()
与InterruptDone(),
InterruptDisable(),
eSetThreadPriority等几个函数。
InterruptInitialize()函数负责把某个逻辑中断号与一个Event内核对象关联起来,当中断发生时,操作系统会负责引发这个事件。
WaitForSingleObject()函数会阻塞当前的线程,等待某个Event内核对象标识的事件发生。
InterruptDone()函数用来告诉操作系统对该中断的处理已经完成,操作系统可以重新开启该中断。调用此函数标志着一次中断处理结束。
当设备卸载的时候,需要对IST进行清理工作,例如调用InterruptDisable()函数,关闭Event句柄等等。
通常,IST线程运行在普通优先级之上。因此,在IST开始时,通常我们可以用CeSetThreadPriority函数为IST线程设置合适的优先级。
典型的IST流程
3.中断延迟及实时性
对中断处理的效率是衡量一个嵌入式操作系统实时性优劣的重要标准。在Windows CE的中断处理中,主要存在两类延迟,ISR延迟和IST延迟。它们的定义同样可以在中断体系结构的图中看到。
导致ISR延迟的因素包括:
1. 中断被关闭的时间
2. 总线指令锁定处理器的时间
3. 内核ISR的执行时间加上导向ISR的时间
导致IST延迟的因素包括:
1. ISR延迟时间
2. ISR执行时间
3. OS执行系统调用的时间
4. 调度IST时间
4.中断实现
当驱动程序调用InterruptInitialize()、InterruptDisable()和InterruptDone()函数的时候,操作系统只不过做了个简单的转接,实际真正被调用到的函数是OEMInterruptEnable()、OEMInterruptDisable()和OEMInterruptDone()。这三个函数负责开关中断和通知中断完成。此外,对于ARM平台,由于其CPU处理中断的特殊性,OEMInterruptHandler()和OEMInterruptHandlerFIQ()两个函数就充当了ISR的角色。
OEMInterruptEnable:Enables an interrupt with a specified identifier. This function is called from the InterruptInitialize and InterruptMask functions.
OEMInterruptDisable:Disables an interrupt with a specified identifier. This function is called from the InterruptDisable and InterruptMask functions
OE