中断服务线程负责处理中断大部分的工作。Wince5.0下IST为用户态线程,而在wince6.0下,IST的加载空间会和加载驱动程序的载体相同,也就是说载体为内核态IST就为内核态。
对于IST的大体描述是:
IST的大部分时间都是在等待某一个事件,这个事件与相对应的逻辑中断号相关联。当有中断发生时,操作系统就会引发与该逻辑中断号相关联的事件,那么IST将会得到调度执行。
编写处理中断驱动程序的两个步骤:
一、进行中断初始化。
二、 编写中断服务线程。
下面我们来具体介绍这两步的细节:
一、进行中断初始化。
1、 创建事件
2、 获取IRQ的系统中断号
3、 创建挂起的中断服务线程IST
4、 调用InterruptInitialize以创建IRQ与事件之间的关联。(创建未挂起的中断服务线程有可能导致InterruptInitialize函数调用失败,因为该事件已经处于等待状态)
5、 调用CeSetThreadPriority函数设置IST的优先级
6、 启动IST线程
void InitialInterrupt( void )
{
// Create an event 创建事件
g_hevInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
if (g_hevInterrupt == NULL)
{
RETAILMSG(1, (TEXT("DEMO: Event creation failed!!!\r\n")));
return;
}
// Have the OAL Translate the IRQ to a system irq 获取IRQ的系统中断号
fRetVal = KernelIoControl( IOCTL_HAL_TRANSLATE_IRQ, &dwIrq, sizeof( dwIrq ),
&g_dwSysInt, sizeof( g_dwSysInt ), NULL );
// Create a thread that waits for signaling 创建挂起的中断服务线程
g_fRun = TRUE;
g_htIST = CreateThread(NULL, // Security
0, // No Stack Size
ThreadIST,//Interrupt Thread
NULL, // No Parameters
CREATE_SUSPENDED, // Create Suspended
&dwThreadID // Thread Id );
// Set the thread priority – arbitrarily 5 设置线程优先级
m_nISTPriority = 5;
if( !CeSetThreadPriority( g_htIST, m_nISTPriority ))
{
RETAILMSG(1,(TEXT("DEMO: Failed setting Thread Priority.\r\n")));
return;
}
// Initialize the interrupt 创建IRQ与事件之间的关联
if ( !InterruptInitialize(g_dwSysInt,g_hevInterrupt,NULL,0) )
{
RETAILMSG (1, (TEXT("DEMO: InterruptInitialize failed!!!\r\n")));
return;
}
// Get the thread started 启动IST线程
ResumeThread( g_htIST );
}
需要注意的是,对 InterruptInitialize 的调用仅采用 SYSINTR 值和事件作为
参数。内核不知道或者不关心将要等待该事件的线程。这样,就可以建立多种应用程序和驱动程序体系结构。应用程序的简单主循环可以初始化中断,然后立即
等待该事件。中断只能与一个事件关联,并且该事件不能用于对
WaitForMultipleObjects 的调用中。我们将观察一个简单的为中断提供服务的
线程。这是大多数实现中的标准解决方案。
二、编写中断服务线程
1、 等待中断事件
2、 确认得到来自操作系统的事件通知
3、 执行必要的中断处理
4、 在尽可能短的时间内完成中断的处理
5、 创建CELOGDATA,供内核调试工具Kernel Tracker查看
6、 调用InterruptDone通知内核中断完成(系统收到信号后会将该优先级中断恢复)
7、 再次等待中断事件
DWORD WINAPI ThreadIST( LPVOID lpvParam )
{
DWORD dwStatus;
BOOL fState = TRUE;
// Always chec the running flag 检查运行标志
while( g_fRun )
{
dwStatus = WaitForSingleObject(g_hevInterrupt, INFINITE);
// Check to see if we are finished 确认是否需要关闭IST
if(!g_fRun )
return 0;
// Make sure we have the object 确认是否成功获得事件
if( dwStatus == WAIT_OBJECT_0 )
{
// Do all interrupt processing to complete the interaction做关于中断的相应处理,用户实现
// with the board so we can receive another interrupt.
if (!( READ_REGISTER_ULONG(g_pBoard Register) & INTR_MASK))
{
RETAILMSG(1, (TEXT("DEMO: Interrupt...")));
g_dwInterruptCount ++;
}
// Finish the interrupt 中断完成
InterruptDone( g_dwSysInt );
}
}
return 0;
}
未理解下面一段话的真正含义!!!????????????????
该示例读取一个 ULONG 寄存器以确定中断状态。您只需用您的代码替换该代码
段。非常关键的一点是,要使 IST 处理尽可能地简单。如果将来需要处理来自
该设备的数据:
* 在 IST 中尽可能快速地从该设备获取数据。
* 创建一个事件,以通知某个优先级较低的线程完成该工作。
* 通过 InterruptDone 从该 IST 中立即返回。
* 让优先级较低的线程进一步处理数据。
* 在 IST 与优先级较低的线程之间放置 FIFO 以处理溢出。