本帖最后由 华禹支持 于 2010-3-1 17:37 编辑
转载:http://www.study-bbs.com/thread-29658-1-1.html
WINCE5.0的中断深入了解
1.总体了解流程
首先描述wince5.0 (2440BSP)的中断流程:
流程1.创建事件aà创建线程ISTà用InterruptInitialize〈系统中断号绑定线程IST〉à线程IST进入等待事件a状态(挂起状态)。
流程2.外部引发中断à OEMInterruptHandler<屏蔽中断à把物理中断转换成系统中断,其他à重新使能中断。(ISR过程)>à操作系统根据系统中断号触发事件a。
流程3.挂起的IST线程等待到事件a进入就绪状态,得到执行时间后开始执行中断服务代码, 最后调用InterruptDone重新使能当前的中断。
你需要为你的设备驱动写好中断处理请求(ISR)和中断服务线程(IST),并牢记这些事件的顺序:
1).当一个中断发生,处理器跳转到核心的中断处理程序(exception handler );
2).这个中断处理程序禁止所有同级或低优先级的其他中断,然后为当前的IRQ调用对应的ISR;
3).ISR中会按照中断标识的形式,返回一个逻辑中断号给中断处理程序,并会置位板级设备中断;
4).中断处理程序重新使能所有的中断,而目前的中断已经在上一步中置位了,然后就触发对应的IST事件;
5).IST就绪,服务于中断设备,然后完成对中断的处理;
6).IST调用InterruptDone函数,该函数将顺序调用OAL层的OEMInterruptDone函数,它将重新使能当前的中断。
1.1物理中断和逻辑中断的对应关系如何建立
这个函数用将物理中断号来获取逻辑中断号:
KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_PwrButtonIrq, sizeof(UINT32), &g_PwrButtonSysIntr, sizeof(UINT32), NULL))
其中:UINT32 g_PwrButtonIrq = IRQ_EINT0;
从help里面查出,KernelIoControl函数最终是调用OEMIoControl函数。
在D:\WINCE500\PLATFORM\COMMON\SRC\COMMON\IOCTL里找到它的定义了,关键代码:
// Execute the handler
rc = g_oalIoCtlTable.pfnHandler(
code, pInBuffer, inSize, pOutBuffer, outSize, pOutSize
);在SMDK2440\Src\Kernel\Oal\ioctl.c中可以找到:
const OAL_IOCTL_HANDLER g_oalIoCtlTable[] = {
#include "ioctl_tab.h"
};
在SMDK2440\Src\Inc\ioctl_tab.h文件中,找到这个表的定义。这个命令对应的函数是OALIoCtlHalRequestSysIntr。
PLATFORM\COMMON\SRC\COMMON\IOCTL\ioctl.c找到这个函数定义:
// Find if it is new or old call type
if (inpSize > sizeof(UINT32) && pInpData[0] == -1) {
// Second UINT32 contains flags, third and subsequents IRQs
sysIntr = OALIntrRequestSysIntr(inpSize/sizeof(UINT32) - 2, &pInpData[2], pInpData[1]); } else {
// This is legacy call, first UINT32 contains IRQ
sysIntr = OALIntrRequestSysIntr(1, pInpData, 0);
}
在WINCE500\PLATFORM\COMMON\SRC\COMMON\INTR\BASE\map.c找到OALIntrRequestSysIntr定义:
irq = pIrqs[0];
sysIntr = g_oalIrq2SysIntr[irq];
在同一个文件中定义:static UINT32 g_oalIrq2SysIntr[OAL_INTR_IRQ_MAXIMUM];
对这个表格赋值仅有两个地方:VOID OALIntrStaticTranslate(UINT32 sysIntr, UINT32 irq)
{
OALMSG(OAL_FUNC&&OAL_INTR, (
L"+OALIntrStaticTranslate(%d, %d)\r\n", sysIntr, irq
));
if (irq < OAL_INTR_IRQ_MAXIMUM && sysIntr < SYSINTR_MAXIMUM) {
g_oalSysIntr2Irq[sysIntr] = irq;
g_oalIrq2SysIntr[irq] = sysIntr;
}
OALMSG(OAL_FUNC&&OAL_INTR, (L"-OALIntrStaticTranslate\r\n"));
}
OALIntrStaticTranslate和OALIntrRequestSysIntr本身两个函数负责建立对应表。后者如果在现有的中断表中找不到已经建立的对应关系,就会分配一个未定义的Sysintr逻辑中断号给这个物理中断号。因此逻辑中断和物理中断的对应,可以说是随机的,只要保证两者是一一对应就好了,不必要硬性建立一个中断号表格(像WINCE4.2那样)。代码中只找到OALIntrStaticTranslate(SYSINTR_OHCI,IRQ_USBH);是静态对应。当中断处理程序获得了逻辑中断号,那么就会触发该中断号关联着的事件。 |