本实例是根据S3C2440,WINCE5.0
1.中止分两大类:内部中止和外部中止。
外部中止:由外部设备所引发的中止,这些外部中止都是经过GPIO中的中止引脚产生的。S3C2440有24个外部中止,相关的寄存器如下:
EXTINT0-EXTINT2:三个寄存器设定EINT0-EINT23的触发办法。
EINTFLT0-EINTFLT3:操控滤波时钟和滤波宽度。
EINTPEND:中止挂起寄存器
EINTMASK:中止屏蔽寄存器
内部中止:内部中止是有CPU内部器材产生的中止,如定时器中止,USB中止,UART中止等。相关的寄存器如下:
SUBSRCPND:次级中止挂起寄存器。
INTSUBMSK:次级中止屏蔽寄存器。
INTMOD:中止办法寄存器
PRIORITY :优先级寄存器
SRCPND :中止挂起寄存器
INTMSK :中止屏蔽寄存器。
INTPND :中止产生后,SRCPND中会有方位1,或许好几个,这些中止会由优先级裁定器选出一个优先级最高的,然后INTPND中相应方位1,同一时间只需一位是1。
这儿要注意一级中止和次级中止的差异,次级中止的设置要比一级中止杂乱一些。
2.WINCE中止机制:ISR和IST
WINCE中止从大的方面分为ISR和IST两部分,详细ISR,IST是什么这儿就不详说了,网上一搜一大把。简略的说是ISR担任把IRQ转化为逻辑中止并回来给内核;IST则担任中止的逻辑处理。
3.WINCE中止实例:外部按键中止操控LED灯
(1)创立一个简略的流驱动模板,这一步能够手动创立,也能够经过”Windows CE Developer Samples” -> “Windows CE 5.0 Embedded Development Labs” -> “DrvWiz.exe” 结构产生。主张选用后者,简略分心,不易犯错。这儿工程命名为LED,即出产的DLL为LED_DLL。
(2)填充函数体。这儿首要介绍与中止相关的两个函数:
DWORD LED_Init( LPCTSTR pContext)//驱动初始化函数,首要做内存的分配和调用中止初始化函数。
DWORD WINAPI LED_IST( LPVOID lpvParam ) //中止处理线程,即IST,在这儿进行中止处理.
DWORD InitInterrupt( void ) //中止初始化函数,包含中止寄存器的设置,事情和线程的创立,初始化等。
首要介绍DWORD InitInterrupt( void ),代码如下:
DWORD InitInterrupt( void )
{
HANDLE g_htIST; //线程回来句柄
BOOL fRetVal;
DWORD dwThreadID;
printfmsg((TEXT(“come into the setup interrupt!!!\r\n”)));
//初始化外部中止8
s2440IO->rGPGCON &= ~(0X3);
s2440IO->rGPGCON |= 0X2;//设置为中止形式
s2440IO->rEXTINT1 &= ~(0X0f);
s2440IO->rEXTINT1 |= 0XA; //下降沿触发,使能滤波器
s2440IO->rEINTMASK &= ~(1<<8);//翻开中止 8
s2440IO->rEINTPEND |= (1<<8);//铲除中止
//GPIO 设置-LED
s2440IO->rGPBCON = (s2440IO->rGPBCON &~(3 << 14)) | (1<< 14); // GPB7 == OUTPUT.
s2440IO->rGPBCON = (s2440IO->rGPBCON &~(3 << 16)) | (1<< 16); // GPB8 == OUTPUT.
s2440INTR->rINTMSK &= ~(0x20); //撤销外部中止8的屏蔽
s2440INTR->rSRCPND |= (0x20); //铲除外部中止8
s2440INTR->rINTPND |=0X20; //铲除外部中止,即初始化
// Create an event
// 创立一个事情
g_hevInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
if(!g_hevInterrupt) return -10;
// 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 );
if( !fRetVal )
{ return -1 }
// Create a thread that waits for signaling
// 创立中止服务线程IST
g_htIST = CreateThread(NULL,// CE Has No Security
0, // No Stack Size
ThreadIST,// Interrupt Thread
NULL,// No Parameters
CREATE_SUSPENDED,// Create Suspended until we are done
&dwThreadID // Thread Id
);
if( !g_htIST )
{return -1 }
// Set the thread priority to real time
// 设置线程的优先级
int m_nISTPriority = 7;
if(!CeSetThreadPriority( g_htIST, m_nISTPriority))
{ return -1 }
// Initialize the interrupt
// 初始化中止,将逻辑中止号与事情相关,即中止产生时触发该事情
//在中止服务线程IST中会等该事情的产生,即WaitForSingleObject(g_hevInterrupt, INFINITE);
//然后中止产生就导致IST运转,处理中止使命
if ( !InterruptInitialize(g_dwSysInt, g_hevInterrupt, NULL, 0) )
{return -1; }
ResumeThread( g_htIST );
printfmsg((TEXT(“*leave the setup interrupt!!!\r\n”)));
return 1;
}
简略说一下初始化中止的流程,首要是初始化相关的中止寄存器,我这儿选用的是外部中止8。接下来是创立一个事情,用于相关外部中止8和IST线程。在IST中会经过dwStatus = WaitForSingleObject(g_hevInterrupt, INFINITE)来等候中止的产生。然后使用KernelIoControl( IOCTL_HAL_TRANSLATE_IRQ,
&dwIrq, sizeof( dwIrq ), &g_dwSysInt, sizeof( g_dwSysInt ), NULL ); 将物理中止IRQ转换为逻辑中止。这是给内核用的。接着就要创立中止服务线程了:g_htIST = CreateThread(NULL,// CE Has No Security
0, // No Stack Size
ThreadIST,// Interrupt Thread
NULL,// No Parameters
CREATE_SUSPENDED,// Create Suspended until we are done
&dwThreadID // Thread Id
);
这些都做好今后就能够初始化中止了.
// Initialize the interrupt
// 初始化中止,将逻辑中止号与事情相关,即中止产生时触发该事情
//在中止服务线程IST中会等该事情的产生,即WaitForSingleObject(g_hevInterrupt, INFINITE);
//然后中止产生就导致IST运转,处理中止使命
InterruptInitialize(g_dwSysInt, g_hevInterrupt, NULL, 0) 该函数就将物理中止对应的逻辑中止号和事情相关起来了。
到这儿整个初始化就做好了,这其间的函数调用次序不是仅有的,但只需理清各个函数的调用次序就行了。
DWORD TST_Init( LPCTSTR pContext)
{
printfmsg((TEXT(“come into the init!!!\r\n”)));
// GPIO Virtual alloc
s2440IO = (volatile IOPreg *) VirtualAlloc(0,sizeof(IOPreg),MEM_RESERVE, PAGE_NOACCESS);
if(s2440IO == NULL) {
printfmsg((TEXT(“For s2440IO: VirtualAlloc faiLED!\r\n”)));
}
else {
if(!VirtualCopy((PVOID)s2440IO,(PVOID)(IOP_BASE),sizeof(IOPreg),PAGE_READWRITE | PAGE_NOCACHE )) {
printfmsg((TEXT(“For s2440IO: Virtualcopy faiLED!\r\n”)));
}
}
s2440INTR = (volatile INTreg *) VirtualAlloc(0,sizeof(INTreg ),MEM_RESERVE, PAGE_NOACCESS);
if(s2440INTR == NULL) {
printfmsg((TEXT(“For s2440INTR: VirtualAlloc faiLED!\r\n!\r\n”)));
}
else {
if(!VirtualCopy((PVOID)s2440INTR,(PVOID)(INT_BASE),sizeof(INTreg),PAGE_READWRITE | PAGE_NOCACHE )) {
printfmsg((TEXT(“For s2440INTR: Virtualcopy faiLED!\r\n!\r\n”)));
}
InitInterrupt();
return 0x1234;
}
这个函数是在驱动被加载的时分调用的,所以要把初始化的使命放在这儿。
与中止相关的部分就这么多,这是动态请求中止的办法,比较杂乱。其实完全能够不必动态请求的办法,而且不引荐选用此办法。静态请求是一种很好的办法,比较简略。在后面的文章会进一步解说。