wince 5.0 .2440 5.0BSP的中断过程(作者:wogoyixikexie@gliet)

wince 5.0 .2440 5.0BSP的中断过程(作者:wogoyixikexie@gliet)

     以前在CSDN写过一些wince5.0中断的文章,现在重新看看,发现以前的有些理解是错误的,想翻开来改改,可是郁闷的CSDN在前台没有返回后台的编辑功能,所以现在重新写一篇纠正一下。

      首先描述wince5.0 (2440BSP)的中断流程

     注册表等——》KernelIoControl(——》OEMIoControl——》OALIntrRequestIrqs )把物理中断转换成系统中断——》InterruptInitialize调用OEMInterruptEnable使能中断并用中断绑定线程——》OEMInterruptHandler屏蔽中断——》执行线程——》InterruptDone——》调用OEMInterruptDone——》调用OALIntrDoneIrqs完成中断线程并重新使能中断

     现在看来,5.0BSP和4.2BSP的中断并没有太大差别,一个是动态,一个是静态,OEMInterruptEnable,OEMInterruptHandler函数位置不一样而已——有空看看中断的汇编部分和PB帮助,那么一切都会明了。

File: oem.c

      

     看OALIntrTranslateSysIntr,

OALIntrTranslateSysIntr

     从上面的代码可以知道,以前说这个系统中断数目限制是从哪里来的SYSINTR_MAXIMUM是系统限定了。

不知道系统为什么要做这个限制,我想如果想改动,也是可行的。不过我觉得有点奇怪,这个中断相关的g_oalIrq2SysIntr是怎么回事呢

static UINT32 g_oalSysIntr2Irq[SYSINTR_MAXIMUM];
static UINT32 g_oalIrq2SysIntr[OAL_INTR_IRQ_MAXIMUM];

我原以为是个全局数组,现在看来,还是另有玄机。现在看看g_oalIrq2SysIntr这些到底在哪里被修改过了,就知道这是怎么来的了

Code

     再来看OALIntrEnableIrqs这个函数是怎么实现的

OALIntrEnableIrqs

     通过以上的分析,这个代码是比较明朗,但是我们还是不明白这个中断到底是如何申请的,现在找一些驱动的代码来看看,以简单的重启按键驱动为例子,发现这个InterruptInitialize函数起到初始化中断和绑定线程的作用,现在看看PB帮助。

This function initializes a hardware interrupt with the kernel. This initialization allows the device driver to register an event and enable the interrupt.

BOOL InterruptInitialize( DWORD idInt,HANDLE hEvent,LPVOID pvData,DWORD cbData );

Parameters

idInt
[in] Interrupt identifier to be associated with this interrupt service thread (IST).
hEvent
[in] Event to be signaled when the interrupt is triggered.
pvData
[in] This parameter can be used as a pointer to a block of data that is passed to OEMInterruptEnable. The block of data can be initialization data, scratch space, and so on.
cbData
[in] Size of data pointed to by pvData.

Return Values

TRUE indicates success; FALSE indicates failure.

Remarks

This function must be called before using the hEvent parameter, which provides a link between the idInt parameter and the SYSINTR value returned by an ISR.

The hEvent parameter can only be used in a WaitForSingleObject call to wait for the event to be triggered by the kernel.

A WaitForMultipleObjects call with hEvent will fail.

If you use hEvent in a call to WaitForSingleObject before you call InterruptInitialize, InterruptInitialize will fail.

Requirements

OS Versions: Windows CE 2.10 and later.
Header: Pkfuncs.h.
Link Library: Coredll.lib.——郁闷,不开源的。

     从PB帮助可以知道,这个

This function initializes a hardware interrupt with the kernel. This initialization allows the device driver to register an event and enable the interrupt.

BOOL InterruptInitialize( DWORD idInt,HANDLE hEvent,LPVOID pvData,DWORD cbData );

Parameters

idInt
[in] Interrupt identifier to be associated with this interrupt service thread (IST).
hEvent
[in] Event to be signaled when the interrupt is triggered.
pvData
[in] This parameter can be used as a pointer to a block of data that is passed to OEMInterruptEnable. The block of data can be initialization data, scratch space, and so on.
cbData
[in] Size of data pointed to by pvData.

Return Values

TRUE indicates success; FALSE indicates failure.

Remarks

This function must be called before using the hEvent parameter, which provides a link between the idInt parameter and the SYSINTR value returned by an ISR.

The hEvent parameter can only be used in a WaitForSingleObject call to wait for the event to be triggered by the kernel.

A WaitForMultipleObjects call with hEvent will fail.

If you use hEvent in a call to WaitForSingleObject before you call InterruptInitialize, InterruptInitialize will fail.

Requirements

OS Versions: Windows CE 2.10 and later.
Header: Pkfuncs.h.
Link Library: Coredll.lib.——郁闷,不开源的。

     从PB帮助可以知道InterruptInitialize函数的功能是绑定线程和系统中断,并且调用OEMInterruptEnable使能中断

(When a device driver calls the InterruptInitialize kernel routine, the kernel then calls OEMInterruptEnable

     

        InterruptInitialize 函数使用的是系统中断来绑定线程的,那么这个物理中断是如何转换成系统中断的呢?这个5.0和4.2BSP是不同的。——答案是伟大的KernelIoControl函数,这个函数的具体用法请参照PB帮助吧。

This function provides the kernel with a generic I/O control for carrying out I/O operations.

BOOL KernelIoControl( DWORD dwIoControlCode,LPVOID lpInBuf,DWORD nInBufSize,LPVOID lpOutBuf,DWORD nOutBufSize,LPDWORD lpBytesReturned );

Parameters

dwIoControlCode
[in] I/O control code, which should support the OAL I/O controls. For a list of these I/O controls, see OAL IOCTLs.
lpInBuf
[out] Pointer to a buffer that contains the data required to perform the operation.

Set to NULL if the dwIoControlCode parameter specifies an operation that does not require input data.

nInBufSize
[in] Size, in bytes, of the buffer pointed to by lpInBuf.
lpOutBuf
[out] Pointer to a buffer that receives the output data for the operation.

Set to NULL if the dwIoControlCode parameter specifies an operation that does not produce output data.

nOutBufSize
[in] Size, in bytes, of the buffer pointed to by lpOutBuf.
lpBytesReturned
[in] Long pointer to a variable that receives the size, in bytes, of the data stored in the buffer pointed to by lpOutBuf. Even when an operation produces no output data, and lpOutBuf is NULL, the KernelIoControl function uses the variable pointed to by lpBytesReturned. After such an operation, the value of the variable has no meaning.

Return Values

TRUE indicates success; FALSE indicates failure.

Remarks

The kernel calls the OEMIoControl function when a device driver or application calls the kernel function KernelIoControl and passes an I/O control code. ——这个很关键,关于OEMIoControl 函数我在CSDN博客有介绍。这是实现中断转换的关键函数

This function is also called when the SystemParametersInfo function is called with SPI_GETOEMINFO or SPI_GETPLATFORMINFO.

The system is fully preemptible when this function is called. The kernel does no processing, but it passes all parameters directly to the function supplied by you.

This function is provided solely to allow your device driver or application to communicate with an OAL and its specific functionality.

     现在就拿2440 5.0BSP串口驱动来具体分析一下

2440串口驱动

     根据我以前在CSDN写的博客,这个KernelIoControl是通过IOCTL_HAL_REQUEST_SYSINTR达到目的,在File:  oal_ioctl_tab.h

{ IOCTL_HAL_REQUEST_SYSINTR,                0,  OALIoCtlHalRequestSysIntr   }, 

这个OALIoCtlHalRequestSysIntr正是前面实现物理中断和系统中断转换的函数。

     OK,大功告成了!

参考资料:http://www.cnblogs.com/wogoyixikexie/archive/2009/02/04/1384012.html(OEMIoControl)

              何宗健——《windows CE嵌入式系统》

原文地址:https://www.cnblogs.com/gooogleman/p/1869755.html