所有硬件中断都被映射到该 ISR 并在该 ISR 中进行处理。线 018 得到当前的中断号。线 020 和 088 分别处理计时器 0 中断和 RTC(实时时钟)中断。如果该中断是其他某种中断,则线 096 会执行快速验证,调用任何链化的 ISR(参见 MSDN 中的函数 NKCallIntChain),将中断号转换为 SYSINTR_ 值,禁用该中断,并且最后在 ulRet 中返回 SYSINTR_ 值。如果找不到 SYSINTR_ 映射的 Irq,则用 SYSINTR_NOP 填充 ulRet。任何已注册的 IST(中断服务线程)事件都按照 ISR 的 SYSINTR_ 返回值进行设置。通过调用 InterruptInitialize 来注册 IST:
在上述函数中,事件 hEvent 被映射到 ISR 返回值 SYSINTR_SOFT1MS。
最后,ISR 通过向可编程中断控制器写 EOI(中断结束)值 (0x20),通知它中断已被处理。如果中断号大于 7,则必须首先通知第二个 PIC(两个 PIC 控制器通过中断线 2 级联)。
因为我们调整了计时器频率,所以我们还必须调整上述 ISR,原因是现在 ISR 通常被调用两次,因此计划程序也工作两倍的次数(对于每个线程,计划次数被除以 2)。
首先,我们必须声明一个静态布尔值,以便能够在 timer0 中断发生时切换 ISR 行为:
001 ULONG PeRPISR(void)
002 {
003 ULONG ulRet = SYSINTR_NOP;
004 UCHAR ucCurrentInterrupt;
#define USE_SOFT_1MS
#ifdef USE_SOFT_1MS
static BOOL bToggle = FALSE;
#endif
005
006 if (fIntrTime)
007 {
// Append rest of code here
我们必须只为 timer0 中断切换该行为:
020 if (ucCurrentInterrupt == INTR_TIMER0)
021 {
#ifdef USE_SOFT_1MS
bToggle = !bToggle; // Toggle value
if (bToggle)
{
#endif
022 if (PProfileInterrupt)
023 {
024 ulRet= PProfileInterrupt();
025 }
026 else
027 {
// Lines 028 to 077 are unchanged, and not showed here to save
// the rainforest...
078 }
079
080 //
081 // Check if a reboot was requested.
082 //
083 if (dwRebootAddress)
084 {
085 RebootHandler();
086 }
#ifdef USE_SOFT_1MS
}
else
{
ulRet = SYSINTR_SOFT1MS;
}
#endif
087 }
088 else if (ucCurrentInterrupt == INTR_RTC)
089 {
// Append rest of code here
现在,发生 timer0 中断时的行为在“运行正常的 CE ISR 代码”和“返回 SYSINTR_SOFT1MS”之间切换。我们现在可以通过 SYSINTR_SOFT1MS 值使用 InterruptInitialize,以便将某个事件绑定到 timer0 中断。然后,该事件将每 1 ms 产生一次。
修改 oalintr.h
Before we can use the SYSINTR_SOFT1MS value
we have to define it in oalintr.h, which resides in
\WINCE410\PUBLIC\COMMON\OAK\CSP\I486\INC, like this:
#define USE_SOFT_1MS
#ifdef USE_SOFT_1MS
#define SYSINTR_SOFT1MS (SYSINTR_FIRMWARE+6)
#endif
只要您按照下面的说明修改 OEMInterruptEnable 函数,就可以随便使用任何基于 SYSINTR_FIRMWARE 的值(就像 SYSINTR_FIRMWARE+20 一样)。
修改 OEMInterruptEnable 函数
我们还必须更改 cfwpc.c 内部的 OEMInterruptEnable 函数,以确保对于我们的 timer0 中断,该函数总是成功。如果我们不这样做,则对于 SYSINTR_SOFT1MS 中断,InterruptInitialize 函数将失败。将下面的代码行添加到该函数:
#ifdef USE_SOFT_1MS
if (idInt == SYSINTR_SOFT1MS)
{
DEBUGMSG (1, (TEXT("Accepting the soft 1ms interrupt enable request.\r\n")));
return (TRUE);
}
#endif
生成平台
因为我们更改了一些内核代码,所以必须对内核进行完整的生成,包括重新生成依赖项树。首先,保存所有已更改的文件,然后在 Platform Builder 的“Tools”菜单中选择“Options”,并单击“Build”选项卡。现在,确保“Enable Deptree Build”被选中。此时,就可以通过单击“Build”菜单中的“Rebuild Platform”重新生成整个平台了。完成所有工作以后,请从“Tools”->“Options”菜单的“Build”选项卡中取消选中“Enable Deptree Build”。