Yongq Wong

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

这里我们主要讨论的是CE的中断建立和中断相应的大概流程以及所涉及的代码位置。这里所讲述的,是针对ARM平台的。在CE的中断处理里面,有一部分工作是CE Kernel完成的,有一部分工作是要由OEM完成的。

Kernel代码工作

ExVector.s:中断向量定义,里面定义的是armtrap.s的函数地址

Armtrap.s:中断处理定义,最重要是里面的IRQHandler函数,而其中最重要的是CALL OEMInterruptHandler

Mdarm.c:中断向量加载

Kdriver.cNKCallIntChain函数:把IRQ转换为SysIntr,值得留意的是pIntChainTable[],是IRQ所对应的ISR处理程序的入口,其中最主要的是其成员函数pfnHandlerpfnHandler的填充,是在HookIntChain里面,这个函数是ISR在初始化的时候调用的。在这个函数里面,如果pIntChainTable为空,则返回SYSINTR_CHAIN,如果pIntChainTable[]不为空,则调用pfnHandler得到一个sysintr值,然后返回之。

 

OEM定义工作:Oalintr.cOEMInterruptHandler函数,通过查询硬件的中断寄存器,得到硬件IRQ号。对于EINT04-23的中断,通过EINTMASK寄存器,得到相对应的系统IRQ。注意,这里的IRQCE定义的IRQ,是系统硬件IRQ的扩展。然后调用NKCallIntChain看看这个IRQ是否是一个ChainInterrupt。如果函数返回SYSINTR_CHAIN或者返回一个不合法的sysintr,则通过OALIntrTranslateIrqIRQ转化为sysintr。如果是一个合法的sysintr,则返回该值。

 

单一ISRDevice,主要通过OEMInterruptHandler处理,在OEMInterruptHandler没有定义的IRQ,可以在OAL里面或者驱动的加载里面,通过HookInterrupt函数进行关联。

多个ISRDevice,通常这是总线设备的需求,因为总线设备上面通常串有几个设备。这些总线上的设备,需要有一个ISR判断究竟是哪个设备发出的中断。这个ISR,是一个DLL的程序,设备驱动必须在初始化的时候通过LoadIntChainHandler(文件名,函数名,irq)加载这个DLL程序。LoadIntChainHandler的定义在kdriver.cNKLoadIntChainHandler里面。对于大多数的总线设备,可以利用微软已经写好的giisr.dll来实现。giisr的实现代码在Public\common\oak\drivers下面。

 

对于总线设备,如果利用GIISR的话,原理如下:

总线设备驱动在初始化的时候,通过LoadIntChainHandler加载GIISR,而加载的时候,LoadIntChainHandler会调用GIISRCreateInstance创建一个实例,GIISR会返回一个index值给LoadIntChainHandler,以标示实例,LoadIntChainHandler则会返回一个Handle给驱动,驱动则根据这个Handle存取GIISR。得到这个handle之后,初始化还需要包括从reg表里面读出相关的初始化参数,对GIISR进行赋值,譬如Port AddressMask AddressSysIntr等。

 

驱动程序在初始化的时候:

1、创建一个EventCreateEvent

2、然后用InterruptInitialize函数把sysintr和这个Event相关联

3Kick-off一个ThreadIST

4、这个Thread最终是WaitForSingleObjectEventID

具体的例子,可以参阅USBFN的例子:sc2410pdd.cpp里面,UfnPdd_Start函数;

 

转载处:http://space.itpub.net/16918737/viewspace-504351

posted on 2010-06-21 16:41  Yongq wong  阅读(256)  评论(0编辑  收藏  举报