刚才看了何宗健老师的书,在5.0BSP中,在系统启动阶段,除了时钟中断以外,其他中断都是关闭的。在加载驱动的时候,驱动程序负责加载自己所用到的驱动,方法是调用InterruptInitialize。真正工作的是OEMInterruptEnable而这个函数又调用OALIntrEnableIrqs函数。
现在让我们一步一步来看代码分析。
首先看InterruptInitialize----------奇怪了,在4.2中的驱动中能找到这个函数被调用,5.0下的却不行。哎怎么回事?
然后OEMInterruptEnable
这个函数在C:/WINCE500/PLATFORM/COMMON/SRC/COMMON/INTR/COMMON/oem.c
- //------------------------------------------------------------------------------
- //
- // File: oem.c
- //
- // This file implements a standard implementation of OEMInterrupt functions
- // relating to enabling, disabling and finishing interrupts.
- //
- #include <windows.h>
- #include <nkintr.h>
- #include <oal.h>
- //------------------------------------------------------------------------------
- //
- // Function: OEMInterruptEnable
- //
- // This function enables the IRQ given its corresponding SysIntr value.
- // Function returns true if SysIntr is valid, else false.
- //
- BOOL OEMInterruptEnable(DWORD sysIntr, LPVOID pvData, DWORD cbData)
- {
- BOOL rc = FALSE;
- const UINT32 *pIrqs;//注意这个是个常量指针,以前我总想找他的老家,汗!
- UINT32 count;
- OALMSG(OAL_INTR&&OAL_VERBOSE,
- (L"+OEMInterruptEnable(%d, 0x%x, %d)/r/n", sysIntr, pvData, cbData
- ));
- // SYSINTR_VMINI & SYSINTR_TIMING are special cases
- if (sysIntr == SYSINTR_VMINI || sysIntr == SYSINTR_TIMING) {
- rc = TRUE;
- goto cleanUp;
- }
- // Obtain the SYSINTR's underlying IRQ number
- //下面使用的函数很有用,等下会分析。是个关键函数
- if (!OALIntrTranslateSysIntr(sysIntr, &count, &pIrqs)) {
- // Indicate invalid SysIntr
- OALMSG(OAL_ERROR, (
- L"ERROR: OEMInterruptEnable: IRQs are undefined for SysIntr %d/r/n",
- sysIntr
- ));
- goto cleanUp;
- }
- // Enable the interrupt
- rc = OALIntrEnableIrqs(count, pIrqs);//这个也是关键函数
- cleanUp:
- OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OEMInterruptEnable(rc = 1)/r/n"));
- return rc;
- }
再看OALIntrEnableIrqs这个函数
C:/WINCE500/PLATFORM/SMDK2440A/Src/Common/Intr/intr.c
- //------------------------------------------------------------------------------
- //
- // Function: OALIntrEnableIrqs
- //
- BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs)
- {
- BOOL rc = TRUE;
- UINT32 i, mask, irq;
- OALMSG(OAL_INTR&&OAL_FUNC, (
- L"+OALIntrEnableIrqs(%d, 0x%08x)/r/n", count, pIrqs
- ));
- for (i = 0; i < count; i++) {
- #ifndef OAL_BSP_CALLBACKS
- irq = pIrqs[i];
- #else
- // Give BSP chance to enable irq on subordinate interrupt controller
- irq = BSPIntrEnableIrq(pIrqs[i]);
- #endif
- if (irq == OAL_INTR_IRQ_UNDEFINED) continue;
- // Depending on IRQ number use internal or external mask register
- if (irq <= IRQ_ADC) {
- // Use interrupt mask register
- CLRREG32(&g_pIntrRegs->INTMSK, 1 << irq);
- } else if (irq <= IRQ_EINT7) {
- // Use external mask register
- CLRREG32(&g_pIntrRegs->INTMSK, 1 << IRQ_EINT4_7);
- CLRREG32(&g_pPortRegs->EINTMASK, 1 << (irq - IRQ_EINT4 + 4));
- } else if (irq <= IRQ_EINT23) {
- // Use external mask register
- mask = 1 << (irq - IRQ_EINT4 + 4);
- OUTREG32(&g_pPortRegs->EINTPEND, mask);
- CLRREG32(&g_pPortRegs->EINTMASK, mask);
- mask = 1 << IRQ_EINT8_23;
- if ((INREG32(&g_pIntrRegs->INTPND) & mask) != 0) {
- OUTREG32(&g_pIntrRegs->INTPND, mask);
- }
- CLRREG32( &g_pIntrRegs->INTMSK, 1 << IRQ_EINT8_23);
- } else {
- rc = FALSE;
- }
- }
- OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrEnableIrqs(rc = %d)/r/n", rc));
- return rc;
- }
------------OALIntrEnableIrqs函数的确是使能了一些中断,不过在OAL中根本没有调用这些函数(甚至这这个oem.c大部分函数都没有用到,这里只是分析一下5.0静态中断的一个方法)
中断禁止函数OEMInterruptDisable,中断完成函数OEMInterruptDone都是同样的道理(他们都在oem.c)在这里不再赘述。
下面来看OALIntrTranslateSysIntr这个关键函数
C:/WINCE500/PLATFORM/SMDK2440A/Src/Inc/oal_intr.h有这个函数的声明,但是没有具体实现(貌似这里限定了2440最大中断数目)。我觉得这是三星想自己做,但是后来没有做完——哎!这些BSP都是三星的实验版本。我们要小心使用。N多函数名相同,但是却没有使用,并且没有文档的
这下看PB下的OALIntrTranslateSysIntr
- //------------------------------------------------------------------------------
- //
- // File: C:/WINCE500/PLATFORM/COMMON/SRC/COMMON/INTR/BASE/map.c
- //
- // The file implement simple table/array based mapping between IRQ and SYSINTR
- // which is suitable for most OAL implementations.
- //
- #include <windows.h>
- #include <nkintr.h>
- #include <oal_intr.h>
- #include <oal_log.h>
- //------------------------------------------------------------------------------
- static UINT32 g_oalSysIntr2Irq[SYSINTR_MAXIMUM];
- static UINT32 g_oalIrq2SysIntr[OAL_INTR_IRQ_MAXIMUM];
- //------------------------------------------------------------------------------
- //
- // Function: OALIntrTranslateSysIntr
- //
- // This function maps a SYSINTR to its corresponding IRQ. It is typically used
- // in OEMInterruptXXX to obtain IRQs for given SYSINTR.
- //
- BOOL OALIntrTranslateSysIntr(
- UINT32 sysIntr, UINT32 *pCount, const UINT32 **ppIrqs
- ) {
- BOOL rc;
- OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OALTranslateSysIntr(%d)/r/n", sysIntr));
- // Valid SYSINTR?
- if (sysIntr >= SYSINTR_MAXIMUM) {
- rc = FALSE;
- goto cleanUp;
- }
- *pCount = 1;
- //从下一句可以看出,这里只是取出相应的中断而已,不过g_oalIrq2SysIntr这个存储
- //中断向量的数组是static类型,并没有得到初始化,所以我据此推测我这个三星
- //BSP并没有使用这个OEM函数中断使能、禁止的中断方法而是使用的是KernelIoControl
- *ppIrqs = &g_oalSysIntr2Irq[sysIntr];
- rc = TRUE;
- cleanUp:
- OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OALTranslateSysIntr(rc = %d)/r/n", rc));
- return rc;
- }
不过C:/WINCE500/PLATFORM/COMMON/SRC/COMMON/INTR/BASE/map.c(32):// Function: OALIntrMapInit这个函数在我的BSP中使用到了,他的作用是初始化中断为未定义类型
- //------------------------------------------------------------------------------
- static UINT32 g_oalSysIntr2Irq[SYSINTR_MAXIMUM];
- static UINT32 g_oalIrq2SysIntr[OAL_INTR_IRQ_MAXIMUM];
- //------------------------------------------------------------------------------
- //
- // Function: OALIntrMapInit
- //
- // This function must be called from OALInterruptInit to initialize mapping
- // between IRQ and SYSINTR. It simply initialize mapping arrays.
- //
- VOID OALIntrMapInit()
- {
- UINT32 i;
- OALMSG(OAL_FUNC&&OAL_INTR, (L"+OALIntrMapInit/r/n"));
- // Initialize interrupt maps
- for (i = 0; i < SYSINTR_MAXIMUM; i++) {
- g_oalSysIntr2Irq[i] = OAL_INTR_IRQ_UNDEFINED;
- }
- for (i = 0; i < OAL_INTR_IRQ_MAXIMUM; i++) {
- g_oalIrq2SysIntr[i] = SYSINTR_UNDEFINED;
- }
- OALMSG(OAL_FUNC&&OAL_INTR, (L"-OALIntrMapInit/r/n"));
- }
它是在哪里被使用的呢?来看看,我至今不明白它是怎么被调用的。
其他关于使用OEM函数禁止中断的函数也在这个map.c里面,
注意:这个笔记还没有完成,可能我的认识有极大错误,请大家看了不要太深信,如果发现有误,请在博客留言给我。谢谢。
转载请表明wogoyixikexie@gliet桂林电子科技大学一系科协,如有错误,希望能够指出。