原帖地址http://topic.csdn.net/u/20071008/11/D54DF4A6-09EF-4D7F-AADB-2F60FF3824FC.html
1 WinCE中第一次对中断的处理是在OAL的OEMInit()中,该函数调用OALIntrInit()完成对中断的初始化.
2 OALIntrInit()对中断的初始化做了如下工作:
2.1 通过配置IPR0-IPR33设置中断优先级,优先级定义在g_IntPriorities和g_IntPriorities2中,其中IRQ_OSMR0为最高优先级, IRQ_KEYPAD为最低优先级.
2.2 设置ICCR,在空闲模式时只对有效的,非屏蔽的中断响应.
2.3 BSPIntrInit().该函数对BSP中需要处理的中断进行初始化工作,主要是设置ICMR寄存器使GPIO1(CPLD)和GPIO2为非屏蔽状态,然后通过OALIntrStaticTranslate建立IRQ和sysintr之间的关联.
2.4 对于WinCE来说,中断可以作如下分类:
1> 与BSP无关的Kernel使用的内部中断, 比如IRQ_OSMR0(for
sched),IRQ_RTCALARM;
2> 与BSP有关的CPU内部中断,比如IRQ_USBOHCI, IRQ_OSM
R1, IRQ_KEYPAD, IRQ_FFUART, IRQ_BTUART, IRQ_STUART, IRQ_DMAC, IRQ_USBFN;
3> CPLD所管理的中断,以GPIO1通知CPU中断的产生,在收到G
PIO1产生的中断后可以通过读取地址0x0A00_0010判断具体的中断源,比如IRQ_GPIO1_MMCCD(MMC_IN_INT, MMC_OUT_INT), IRQ_GPIO1_USBCD(USB_IN_INT, USB_OUT_INT), IRQ_GPIO1_PCMCIA_S0_CSC(CF_IN_INT. CF_OUT_INT),还有在代码中没有处理的SIM卡中断(SIM_IN_INT, SIM_OUT_INT).
4> GPIO2_120产生的中断,通过寄存器ICIP的位10-GPIO_x通
知CPU中断的产生,然后查询寄存器GEDR_x可以判断具体的中断源,比如IRQ_GPIO12_MARATHO, IRQ_GPIO10_ETHERNET,IRQ_GPIO13_UCB1400;
5> 以Installable ISR形式产生的中断,这类中断通常是以DLL的形式安装,在注册表中定义其实际的IRQ中断值,比如IRQ_MMC_DETECT,IRQ_MMC_CONTROL;
2.5 有几种方式可以建立实际中断IRQ到系统中断sysintr之间的关联,对于build-in设备,可以在OEMInit中通过OALIntrStaticTranslate来建立静态的关联;但是对于installable ISRs,可以在注册表中定义实际的中断IRQ,然后通过在KernelIOControl中使用IOCTL_HAL_REQUEST_SYSINTR来实时分配新的sysintr,这有助于驱动的移植.
3 在CPU接收到中断后,对中断的处理是在 OEMInterruptHandler()中,该函数的首先屏蔽该中断,最后得到实际中断IRQ所对应的sysintr的值.
3.1 首先它通过中断寄存器ICHP得到实际的IRQ值;
3.2 对于GPIO产生的中断,通过清空GFER和GRER寄存器来屏蔽相同的中断;对于其余的CPU内部中断,通过清空ICMR寄存器的相应位来屏蔽中断;
3.3 对于Kernel使用的IRQ_OSMR0和IRQ_OSMR2,分别进行处理,得到sysintr;
3.4 对于通过GPIO0,GPIO1和GPIO2_120产生的中断,将IRQ的值进行转化,使之与OAL/intr.c和bulverder_intr.h中所定义的新的IRQ值相对应,此时的IRQ值就不是在ICIP中对定义的IRQ值了;
3.5 接着调用NKCallIntChain(irq)判断该IRQ是否已经被加入中断列表,同时开始调用该中断的ISR程序.
4 当中断处理完成后,调用OALIntrDoneIrqs(),重新使能中断.