wince 5.0 .2440 5.0BSP的中斷過程(轉)

以前在CSDN寫過一些wince5.0中斷的文章,現在重新看看,發現以前的有些理解是錯誤的,想翻開來改改,可是鬱悶的CSDN在前臺沒有返回後臺的編輯功能,所以現在重新寫一篇糾正一下。

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

     註冊表等——》KernelIoControl(——》OEMIoControl——》OALIntrRequestIrqs )把物理中斷轉換成系統中斷——》InterruptInitialize調用OEMInterruptEnable使能中斷並用中斷綁定線程——》OEMInterruptHandler屏蔽中斷——》執行線程——》InterruptDone——》調用OEMInterruptDone——》調用OALIntrDoneIrqs完成中斷線程並重新使能中斷

     現在看來,5.0BSP和4.2BSP的中斷並沒有太大差別,一個是動態,一個是靜態,OEMInterruptEnable,OEMInterruptHandler函數位置不一樣而已——有空看看中斷的彙編部分和PB幫助,那麼一切都會明瞭。

 

wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客File: oem.c

  1 //

  2 // Copyright (c) Microsoft Corporation.  All rights reserved.

  3 //

  4 //

  5 // Use of this source code is subject to the terms of the Microsoft end-user

  6 // license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.

  7 // If you did not accept the terms of the EULA, you are not authorized to use

  8 // this source code. For a copy of the EULA, please see the LICENSE.RTF on your

  9 // install media.

 10 //

 11 //------------------------------------------------------------------------------

 12 //

 13 //  File: oem.c

 14 //

 15 //  This file implements a standard implementation of OEMInterrupt functions

 16 //  relating to enabling, disabling and finishing interrupts.

 17 //

 18 #include <windows.h>

 19 #include <nkintr.h>

 20 #include <oal.h>

 21  

 22 

 23 //------------------------------------------------------------------------------

 24 //

 25 //  Function:  OEMInterruptEnable

 26 //

 27 //  This function enables the IRQ given its corresponding SysIntr value.

 28 //  Function returns true if SysIntr is valid, else false.

 29 //

 30 BOOL OEMInterruptEnable(DWORD sysIntr, LPVOID pvData, DWORD cbData)

 31 {

 32     BOOL rc = FALSE;

 33     const UINT32 *pIrqs;

 34     UINT32 count;

 35 

 36     OALMSG(OAL_INTR&&OAL_VERBOSE, 

 37         (L"+OEMInterruptEnable(%d, 0x%x, %d)/r/n", sysIntr, pvData, cbData

 38     ));

 39 

 40     // SYSINTR_VMINI & SYSINTR_TIMING are special cases

 41     if (sysIntr == SYSINTR_VMINI || sysIntr == SYSINTR_TIMING) {

 42         rc = TRUE;

 43         goto cleanUp;

 44     }

 45 

 46     // Obtain the SYSINTR's underlying IRQ number

 47     if (!OALIntrTranslateSysIntr(sysIntr, &count, &pIrqs)) {

 48         // Indicate invalid SysIntr

 49         OALMSG(OAL_ERROR, (

 50             L"ERROR: OEMInterruptEnable: IRQs are undefined for SysIntr %d/r/n", 

 51             sysIntr 

 52         ));

 53         goto cleanUp;

 54     }

 55 

 56     // Enable the interrupt

 57     rc = OALIntrEnableIrqs(count, pIrqs);

 58 

 59 cleanUp:    

 60     OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OEMInterruptEnable(rc = 1)/r/n"));

 61     return rc;

 62 }

 63 

 64 

 65 //------------------------------------------------------------------------------

 66 //

 67 //  Function:  OEMInterruptDisable(DWORD sysIntr)

 68 //

 69 //  This function disables the IRQ given its corresponding SysIntr value.

 70 //

 71 //

 72 VOID OEMInterruptDisable(DWORD sysIntr)

 73 {

 74     const UINT32 *pIrqs;

 75     UINT32 count;

 76 

 77     OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OEMInterruptDisable(%d)/r/n", sysIntr));

 78 

 79     // Obtain the SYSINTR's underlying IRQ number

 80     if (!OALIntrTranslateSysIntr(sysIntr, &count, &pIrqs)) {

 81         // Indicate invalid SysIntr

 82         OALMSG(OAL_ERROR, (

 83             L"ERROR: OEMInterruptEnable: IRQs are undefined for SysIntr %d/r/n", 

 84             sysIntr 

 85         ));

 86         goto cleanUp;

 87     }

 88 

 89     // Disable the interrupt

 90     OALIntrDisableIrqs(count, pIrqs);

 91 

 92 cleanUp:

 93     // Indicate exit

 94     OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OEMInterruptDisable/r/n"));

 95 }

 96 

 97 

 98 //------------------------------------------------------------------------------

 99 //

100 //  Function: OEMInterruptDone

101 //

102 //  OEMInterruptDone is called by the kernel when a device driver

103 //  calls InterruptDone(). The system is not preemtible when this

104 //  function is called.

105 //

106 VOID OEMInterruptDone(DWORD sysIntr)

107 {

108     const UINT32 *pIrqs;

109     UINT32 count;

110 

111     OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OEMInterruptDone(%d)/r/n", sysIntr));

112     if (OALIntrTranslateSysIntr(sysIntr, &count, &pIrqs)) {

113         OALIntrDoneIrqs(count, pIrqs);

114     }

115     OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OEMInterruptDone/r/n"));

116 }

117 

118 //------------------------------------------------------------------------------

119 

 

      

     看OALIntrTranslateSysIntr,

 

wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客OALIntrTranslateSysIntr

 1 //------------------------------------------------------------------------------

 2 //

 3 //  Function:  OALIntrTranslateSysIntr

 4 //

 5 //  This function maps a SYSINTR to its corresponding IRQ. It is typically used

 6 //  in OEMInterruptXXX to obtain IRQs for given SYSINTR.

 7 //

 8 BOOL OALIntrTranslateSysIntr(

 9     UINT32 sysIntr, UINT32 *pCount, const UINT32 **ppIrqs

10 ) {

11     BOOL rc;

12 

13     OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OALTranslateSysIntr(%d)/r/n", sysIntr));

14     

15     // Valid SYSINTR?

16     if (sysIntr >= SYSINTR_MAXIMUM) {

17         rc = FALSE;

18         goto cleanUp;

19     }

20     *pCount = 1;

21     *ppIrqs = &g_oalSysIntr2Irq[sysIntr];

22     rc = TRUE;

23 

24 cleanUp:

25     OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OALTranslateSysIntr(rc = %d)/r/n", rc));

26     return rc;

27 }

28 

 

     從上面的代碼可以知道,以前說這個系統中斷數目限制是從哪裏來的SYSINTR_MAXIMUM是系統限定了。

不知道系統爲什麼要做這個限制,我想如果想改動,也是可行的。不過我覺得有點奇怪,這個中斷相關的g_oalIrq2SysIntr是怎麼回事呢

static UINT32 g_oalSysIntr2Irq[SYSINTR_MAXIMUM];

static UINT32 g_oalIrq2SysIntr[OAL_INTR_IRQ_MAXIMUM];

我原以爲是個全局數組,現在看來,還是另有玄機。現在看看g_oalIrq2SysIntr這些到底在哪裏被修改過了,就知道這是怎麼來的了

 

wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客Code

  1 //------------------------------------------------------------------------------

  2 //  剛開始的時候,g_oalSysIntr2Irq和g_oalIrq2SysIntr都是初始化爲未定義的

  3 //  Function:  OALIntrMapInit

  4 //

  5 //  This function must be called from OALInterruptInit to initialize mapping

  6 //  between IRQ and SYSINTR. It simply initialize mapping arrays.

  7 //

  8 VOID OALIntrMapInit()

  9 {

 10     UINT32 i;

 11     

 12     OALMSG(OAL_FUNC&&OAL_INTR, (L"+OALIntrMapInit/r/n"));

 13 

 14     // Initialize interrupt maps

 15     for (i = 0; i < SYSINTR_MAXIMUM; i++) {

 16         g_oalSysIntr2Irq[i] = OAL_INTR_IRQ_UNDEFINED;

 17     }

 18     for (i = 0; i < OAL_INTR_IRQ_MAXIMUM; i++) {

 19         g_oalIrq2SysIntr[i] = SYSINTR_UNDEFINED;

 20     }

 21 

 22     OALMSG(OAL_FUNC&&OAL_INTR, (L"-OALIntrMapInit/r/n"));

 23 }

 24 

 25 //------------------------------------------------------------------------------

 26 //  靜態映射中斷 在2440 5.0BSP沒有使用到

 27 //  Function:   OALIntrStaticTranslate

 28 //

 29 //  This function sets static translation between IRQ and SYSINTR. In most

 30 //  cases it should not be used. Only exception is mapping for 

 31 //  SYSINTR_RTC_ALARM and obsolete device drivers.

 32 //

 33 VOID OALIntrStaticTranslate(UINT32 sysIntr, UINT32 irq)

 34 {

 35     OALMSG(OAL_FUNC&&OAL_INTR, (

 36         L"+OALIntrStaticTranslate(%d, %d)/r/n", sysIntr, irq

 37     ));

 38     if (irq < OAL_INTR_IRQ_MAXIMUM && sysIntr < SYSINTR_MAXIMUM) {

 39         g_oalSysIntr2Irq[sysIntr] = irq;

 40         g_oalIrq2SysIntr[irq] = sysIntr;

 41     }        

 42     OALMSG(OAL_FUNC&&OAL_INTR, (L"-OALIntrStaticTranslate/r/n"));

 43 }

 44 

 45 //------------------------------------------------------------------------------

 46 //  這個函數作用很大,把物理中斷轉換成系統中斷

 47 //  Function:  OALIntrRequestSysIntr

 48 //

 49 //  This function allocate new SYSINTR for given IRQ and it there isn't

 50 //  static mapping for this IRQ it will create it.

 51 //

 52 UINT32 OALIntrRequestSysIntr(UINT32 count, const UINT32 *pIrqs, UINT32 flags)

 53 {

 54     UINT32 irq, sysIntr;

 55 

 56     OALMSG(OAL_INTR&&OAL_FUNC, (

 57         L"+OALIntrRequestSysIntr(%d, 0x%08x, 0x%08x)/r/n", count, pIrqs, flags

 58     ));

 59     

 60     // Valid IRQ?

 61     if (count != 1 || pIrqs[0] >= OAL_INTR_IRQ_MAXIMUM) {

 62         sysIntr = SYSINTR_UNDEFINED;            

 63         goto cleanUp;

 64     }

 65     irq = pIrqs[0];

 66 

 67     // If there is mapping for given irq check for special cases

 68     if (g_oalIrq2SysIntr[irq] != SYSINTR_UNDEFINED) {

 69         // If static mapping is requested we fail

 70         if ((flags & OAL_INTR_STATIC) != 0) {

 71             OALMSG(OAL_ERROR, (L"ERROR: OALIntrRequestSysIntr: "

 72                L"Static mapping for IRQ %d already assigned/r/n", irq

 73             ));

 74             sysIntr = SYSINTR_UNDEFINED;            

 75             goto cleanUp;

 76         }

 77         // If we should translate, return existing SYSINTR

 78         if ((flags & OAL_INTR_TRANSLATE) != 0) {

 79             sysIntr = g_oalIrq2SysIntr[irq];

 80             goto cleanUp;

 81         }

 82     }

 83 

 84     // Find next available SYSINTR valuewince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客

 85     for (sysIntr = SYSINTR_FIRMWARE; sysIntr < SYSINTR_MAXIMUM; sysIntr++) {

 86         if (g_oalSysIntr2Irq[sysIntr] == OAL_INTR_IRQ_UNDEFINED) break;

 87     }

 88     

 89     // Any available SYSINTRs left?

 90     if (sysIntr >= SYSINTR_MAXIMUM) {

 91         OALMSG(OAL_ERROR, (L"ERROR: OALIntrRequestSysIntr: "

 92             L"No avaiable SYSINTR found/r/n"

 93         ));            

 94         sysIntr = SYSINTR_UNDEFINED;

 95         goto cleanUp;

 96     }

 97     

 98     // Make SYSINTR -> IRQ association.

 99     g_oalSysIntr2Irq[sysIntr] = irq;

100     

101     // Make IRQ -> SYSINTR association if required

102     if ((flags & OAL_INTR_DYNAMIC) != 0) goto cleanUp;

103     if (

104         g_oalIrq2SysIntr[irq] == SYSINTR_UNDEFINED ||

105         (flags & OAL_INTR_FORCE_STATIC) != 0

106     ) {

107         g_oalIrq2SysIntr[irq] = sysIntr;

108     }

109 

110 cleanUp:

111     OALMSG(OAL_INTR&&OAL_FUNC, (

112         L"-OALIntrRequestSysIntr(sysIntr = %d)/r/n", sysIntr

113     ));

114     return sysIntr;

115 }

116 

117 //------------------------------------------------------------------------------

118 //  釋放系統中斷

119 //  Function:  OALIntrReleaseSysIntr

120 //

121 //  This function release given SYSINTR and remove static mapping if exists.

122 //

123 BOOL OALIntrReleaseSysIntr(UINT32 sysIntr)

124 {

125     BOOL rc = FALSE;

126     UINT32 irq;

127 

128     OALMSG(OAL_INTR&&OAL_FUNC, (L"+OALIntrReleaseSysIntr(%d)/r/n", sysIntr));

129 

130     // Is the SYSINTR already released?

131     if (g_oalSysIntr2Irq[sysIntr] == OAL_INTR_IRQ_UNDEFINED) goto cleanUp;

132 

133     // Remove the SYSINTR -> IRQ mapping

134     irq = g_oalSysIntr2Irq[sysIntr];

135     g_oalSysIntr2Irq[sysIntr] = OAL_INTR_IRQ_UNDEFINED;

136 

137     // If we're releasing the SYSINTR directly mapped in the IRQ mapping, 

138     // remove the IRQ mapping also

139     if (g_oalIrq2SysIntr[irq] == sysIntr) {

140         g_oalIrq2SysIntr[irq] = SYSINTR_UNDEFINED;

141     }

142 

143 cleanUp:

144     OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrReleaseSysIntr(rc = %d)/r/n", rc));

145     return rc;

146 }

147 以上代碼均來自C:/WINCE500/PLATFORM/COMMON/SRC/COMMON/INTR/BASE/map.c

148 

149 //------------------------------------------------------------------------------

 

 

     再來看OALIntrEnableIrqs這個函數是怎麼實現的

 

 

wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客OALIntrEnableIrqs

 1 //------------------------------------------------------------------------------

 2 //

 3 //  Function:  OALIntrEnableIrqs

 4 //

 5 BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs)

 6 {

 7     BOOL rc = TRUE;

 8     UINT32 i, mask, irq;

 9 

10     OALMSG(OAL_INTR&&OAL_FUNC, (

11         L"+OALIntrEnableIrqs(%d, 0x%08x)/r/n", count, pIrqs

12     ));

13 

14     for (i = 0; i < count; i++) {

15 #ifndef OAL_BSP_CALLBACKS

16         irq = pIrqs[i];

17 #else

18         // Give BSP chance to enable irq on subordinate interrupt controller

19         irq = BSPIntrEnableIrq(pIrqs[i]);

20 #endif

21         if (irq == OAL_INTR_IRQ_UNDEFINED) continue;

22         // Depending on IRQ number use internal or external mask register

23         if (irq <= IRQ_ADC) {

24             // Use interrupt mask register

25             CLRREG32(&g_pIntrRegs->INTMSK, 1 << irq);

26         } else if (irq <= IRQ_EINT7) {

27             // Use external mask register

28             CLRREG32(&g_pIntrRegs->INTMSK, 1 << IRQ_EINT4_7);

29             CLRREG32(&g_pPortRegs->EINTMASK, 1 << (irq - IRQ_EINT4 + 4));

30         } else if (irq <= IRQ_EINT23) {

31             // Use external mask register

32             mask = 1 << (irq - IRQ_EINT4 + 4);

33             OUTREG32(&g_pPortRegs->EINTPEND, mask);

34             CLRREG32(&g_pPortRegs->EINTMASK, mask);

35             mask = 1 << IRQ_EINT8_23;

36             if ((INREG32(&g_pIntrRegs->INTPND) & mask) != 0) {

37                 OUTREG32(&g_pIntrRegs->INTPND, mask);

38             }

39             CLRREG32( &g_pIntrRegs->INTMSK, 1 << IRQ_EINT8_23);

40         } else {

41             rc = FALSE;

42         }

43     }        

44 

45     OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrEnableIrqs(rc = %d)/r/n", rc));

46     return rc;    

47 }

 

     通過以上的分析,這個代碼是比較明朗,但是我們還是不明白這個中斷到底是如何申請的,現在找一些驅動的代碼來看看,以簡單的重啓按鍵驅動爲例子,發現這個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串口驅動來具體分析一下

 

 

wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客2440串口驅動

 1     virtual BOOL Init() {

 2         PHYSICAL_ADDRESS    ioPhysicalBase = { S3C2440A_BASE_REG_PA_IOPORT, 0};

 3         ULONG               inIoSpace = 0;

 4         if (TranslateBusAddr(m_hParent,Internal,0, ioPhysicalBase,&inIoSpace,&ioPhysicalBase)) {

 5             // Map it if it is Memeory Mapped IO.

 6             m_pIOPregs = (S3C2440A_IOPORT_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C2440A_IOPORT_REG),FALSE);

 7         }

 8         if (m_pIOPregs) {

 9             DDKISRINFO ddi;

10 //讀取註冊表的IRQ的鍵值(這個鍵值還是物理中斷的值,是中斷偏移寄存器(INTOFFSET指定IRQ中斷源)的值,4.2BSP就利用了這個東西)

11             if (GetIsrInfo(&ddi)== ERROR_SUCCESS && 

12                     KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &ddi.dwIrq, sizeof(UINT32), &ddi.dwSysintr, sizeof(UINT32), NULL))

13             {   //使用KernelIoControl完成物理中斷和系統中斷轉換之後,又把這個系統中斷寫入到註冊表中,下次讀出的中斷

14                   //就是系統中斷了wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客wince 5.0 .2440 5.0BSP的中斷過程(轉) - 男兒當自強 - 男兒當自強的博客這樣就完成了物理中斷和系統中斷之間的轉換,比4.2BSP的方法聰明多了。

15                 RegSetValueEx(DEVLOAD_SYSINTR_VALNAME,REG_DWORD,(PBYTE)&ddi.dwSysintr, sizeof(UINT32));

16             }

17             else

18                 return FALSE;

19             m_pDTRPort = (volatile ULONG *)&(m_pIOPregs->GPDDAT);

20             m_pDSRPort = (volatile ULONG *)&(m_pIOPregs->GPDDAT);

21             m_dwDTRPortNum = 0;

22             m_dwDSRPortNum = 1;

23 

24             m_pIOPregs->GPHCON &= ~(0x3<<0 | 0x3<<2 | 0x3<<4 | 0x3<<6 );//tx,rx,rts,cts

25             m_pIOPregs->GPHCON |=  (0x2<<0 | 0x2<<2 | 0x2<<4 | 0x2<<6 ); 

26             m_pIOPregs->GPHCON |= (0x2<<0 | 0x2<<2);

27             m_pIOPregs->GPHUP  |= 0xf;

28 

29             m_pIOPregs->GPDCON &= ~(0x3<<0 | 0x3<<2);//dtr,dsr

30             m_pIOPregs->GPDCON |= (0x1<<0 | 0x0<<2);

31             m_pIOPregs->GPDUP  |= 0x3;

32 

33             return CPdd2440Uart::Init();//這裏有大量的讀註冊表的操作,讀出的中斷是被上面修改過的系統中斷了

34         }

35         return FALSE;

36     };

37 

38 //---------------------------- 來看看這個再次讀註冊表的情況吧---------------------

39 BOOL CPdd2440Uart::Init()

40 {

41     if ( CSerialPDD::Init() && IsKeyOpened() && m_XmitFlushDone!=NULL) { 

42         // IST Setup .--------Get IRQ forom regedit

43         DDKISRINFO ddi;

44        //再次讀出註冊表的中斷,已經是系統中斷了。

45         if (GetIsrInfo(&ddi)!=ERROR_SUCCESS) {

46             return FALSE;

47         }

48         m_dwSysIntr = ddi.dwSysintr;

49         if (m_dwSysIntr !=  MAXDWORD && m_dwSysIntr!=0 ) 

50             m_hISTEvent= CreateEvent(0,FALSE,FALSE,NULL);//創建事件,線程創建在後

51         

52       //綁定中斷PDD線程  ,和MDD中的線程有什麼區別?

53       //ThreadRun

54         if (m_hISTEvent!=NULL)

55             InterruptInitialize(m_dwSysIntr,m_hISTEvent,0,0);

56         else

57             return FALSE;

58         

59         // Get Device Index.

60         if (!GetRegValue(PC_REG_DEVINDEX_VAL_NAME, (PBYTE)&m_dwDevIndex, PC_REG_DEVINDEX_VAL_LEN)) {

61             m_dwDevIndex = 0;

62         }

63         if (!GetRegValue(PC_REG_SERIALWATERMARK_VAL_NAME,(PBYTE)&m_dwWaterMark,sizeof(DWORD))) {

64             m_dwWaterMark = 8;

65         }

66         if (!GetRegValue(PC_REG_2440UART_INTBIT_VAL_NAME,(PBYTE)&m_dwIntShift,sizeof(DWORD))) {

67             RETAILMSG(1,(TEXT("Registery does not have %s set. Drivers fail!!!/r/n"),PC_REG_2440UART_INTBIT_VAL_NAME));

68             m_dwIntShift =0;

69             return FALSE;

70         }

71         if (!GetRegValue(PC_REG_2440UART_IST_TIMEOUTS_VAL_NAME,(PBYTE)&m_dwISTTimeout, PC_REG_2440UART_IST_TIMEOUTS_VAL_LEN)) {

72             m_dwISTTimeout = INFINITE;

73         }

74         if (!MapHardware() || !CreateHardwareAccess()) {

75             return FALSE;

76         }

77         

78         return TRUE;        

79     }

80     return FALSE;

81 }

82 

83 

84 

 

     根據我以前在CSDN寫的博客,這個KernelIoControl是通過IOCTL_HAL_REQUEST_SYSINTR達到目的,在File:  oal_ioctl_tab.h有

{ IOCTL_HAL_REQUEST_SYSINTR,                0,  OALIoCtlHalRequestSysIntr   }, 

這個OALIoCtlHalRequestSysIntr正是前面實現物理中斷和系統中斷轉換的函數。

     OK,大功告成了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章