这两天一直看WinCE 5.0下逻辑中断号的动态映射和动态分配的一些东西,产生一些问题,想向大家请叫?
我现在手头上一块板子,EP9315,看了很多后,发现根据手头的资料分析,它正典型静态分配,interrupthandle()函数里(贴一断代码)
register ULONG ulVic1Irq, ulVic2Irq;
DWORD retval;
LARGE_INTEGER tmpCurTicks;
//
// Read the interrupt status registers.
//
ulVic1Irq = *VIC1_IRQSTATUS;
ulVic2Irq = *VIC2_IRQSTATUS;
//
// Set the default value to nop
//
retval = SYSINTR_NOP;
//
// Fake CPUEnterIdle needs to know about interrupt firing.
//
if(ulVic1Irq & INT1_TIMER1)
{
//
// Temporary hack for the PS2 keyboard driver.
/*
if((gdwInterruptMask2 & INT2_SPI) && (*SPI_SR & SPISR_RNE) && !fPS2Int)
{
fPS2Int = 1;
*VIC2_INTCLEAR = INT2_SPI;
retval = SYSINTR_SPI;
}
else*/
{
retval = TimerInterrupt();
CPUClearSysTimerIRQ();
}
//
// Check if RTC Alarm arrived when TimerInterrupt returns NOP.
//
if( (gfRTCAlarm) && (retval == SYSINTR_NOP) )
{
// Tell the world that we were here....
#if (1 == DEBUG_ALARM)
OEMWriteDebugByte('e');
#endif // ( DEBUG_ALARM )
tmpCurTicks.QuadPart = CurTicks.QuadPart ;
if (gliRTCAlarmTicks.QuadPart <= tmpCurTicks.QuadPart)
{
#if (1 == DEBUG_ALARM)
// Tell the world that the interrupt was hit...
OEMWriteDebugByte('t');
OEMWriteDebugByte('\r');
OEMWriteDebugByte('\n');
#endif // ( DEBUG_ALARM )
gfRTCAlarm = FALSE;
retval = SYSINTR_RTC_ALARM;
}
}
}
else
{
//
// If we're timing interrupts, keep track of when this one came in
//
if (fIntrTime)
{
//
// Subtract off dwReschedIncrment since interrupt hasn't been cleared
//
dwIsrTime1 = PerfCountSinceTick();
wNumInterrupts++;
}
//
// If we get any device interrupts, signal the resume flag. The flag
// will release the CPU from OEMPowerOff if the user had previously
// chosen to suspend the platform. In OEMPowerOff, only the interrupts
// allowed to wake us up will be enabled so we needn't worry about
// that here.
//
//gfResumeFlag = TRUE;
//
// This was not a timer interrupt, must be a device interrupt.
// Change the priority of the interrupt by changing the order that
// the interrupt is processed.
//
//
// Ethernet interrupt.
//
if(ulVic2Irq & INT2_ETHERNET)
{
*VIC2_INTCLEAR = INT2_ETHERNET;
retval = SYSINTR_ETHER;
}
//
// USB interrupt
//
else if(ulVic2Irq & INT2_USB)
{
*VIC2_INTCLEAR = INT2_USB;
retval = SYSINTR_USB;
}
//
// Check the serial port interrupts.
//
else if(ulVic2Irq & INT2_UART1)
{
*VIC2_INTCLEAR = INT2_UART1;
retval = SYSINTR_UART1;
}
else if(ulVic2Irq & INT2_UART2)
{
*VIC2_INTCLEAR = INT2_UART2;
retval = SYSINTR_UART2;
}
else if(ulVic2Irq & INT2_UART3)
{
*VIC2_INTCLEAR = INT2_UART3;
retval = SYSINTR_UART3;
}
else if(ulVic1Irq & INT1_UNUSED1)
{
*VIC1_INTCLEAR = INT1_UNUSED1;
retval = SYSINTR_PIO_PLAYBACK;
}
else if(ulVic1Irq & INT1_UNUSED2)
{
*VIC1_INTCLEAR = INT1_UNUSED2;
retval = SYSINTR_PIO_RECORD;
}
//
// Check to see if it is a keyboard interrupt
//
else if(ulVic1Irq & INT1_KEYPAD)
{
*VIC1_INTCLEAR = INT1_KEYPAD;
retval = SYSINTR_KEYBOARD;
}
//
// Check to see if the SPI port has generated an interrupt.
// This is used for the PS/2 keyboard driver.
//
else if(ulVic2Irq & INT2_SPI)
{
fPS2Int = 1;
*VIC2_INTCLEAR = INT2_SPI;
retval = SYSINTR_SPI;
}
而在wince带的s3c2410采有是动态映射
ULONG OEMInterruptHandler(ULONG ra)
{
UINT32 sysIntr = SYSINTR_NOP;
UINT32 irq, irq2 = OAL_INTR_IRQ_UNDEFINED, mask;
// Get pending interrupt(s)
irq = INREG32(&g_pIntrRegs->INTOFFSET);
// System timer interrupt?
if (irq == IRQ_TIMER4) {
// Clear the interrupt
OUTREG32(&g_pIntrRegs->SRCPND, 1 << IRQ_TIMER4);
OUTREG32(&g_pIntrRegs->INTPND, 1 << IRQ_TIMER4);
// Rest is on timer interrupt handler
sysIntr = OALTimerIntrHandler();
}
// Profiling timer interrupt?
else if (irq == IRQ_TIMER2)
{
// Mask and Clear the interrupt.
mask = 1 << irq;
SETREG32(&g_pIntrRegs->INTMSK, mask);
OUTREG32(&g_pIntrRegs->SRCPND, mask);
OUTREG32(&g_pIntrRegs->INTPND, mask);
// The rest is up to the profiling interrupt handler (if profiling
// is enabled).
//
if (g_pProfilerISR)
{
sysIntr = g_pProfilerISR(ra);
}
}
else
{
#ifdef OAL_ILTIMING
if (g_oalILT.active) {
g_oalILT.isrTime1 = OALTimerCountsSinceSysTick();
g_oalILT.savedPC = 0;
g_oalILT.interrupts++;
}
#endif
if (irq == IRQ_EINT4_7 || irq == IRQ_EINT8_23) {
// Find external interrupt number
mask = INREG32(&g_pPortRegs->EINTPEND);
mask &= ~INREG32(&g_pPortRegs->EINTMASK);
mask = (mask ^ (mask - 1)) >> 5;
irq2 = IRQ_EINT4;
while (mask != 0) {
mask >>= 1;
irq2++;
}
// Mask and clear interrupt
mask = 1 << (irq2 - IRQ_EINT4 + 4);
SETREG32(&g_pPortRegs->EINTMASK, mask);
OUTREG32(&g_pPortRegs->EINTPEND, mask);
// calculate mask for primary interrupt
mask = 1 << irq;
// update irq
irq = irq2;
} else {
// Mask the interrupt
mask = 1 << irq;
SETREG32(&g_pIntrRegs->INTMSK, mask);
}
// clear primary interrupt
OUTREG32(&g_pIntrRegs->SRCPND, mask);
OUTREG32(&g_pIntrRegs->INTPND, mask);
// First find if IRQ is claimed by chain
sysIntr = NKCallIntChain((UCHAR)irq);
if (sysIntr == SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr)) {
// IRQ wasn't claimed, use static mapping
sysIntr = OALIntrTranslateIrq(irq);
}
// unmask interrupts in case it's NOP or invalid
if (SYSINTR_NOP == sysIntr) {
if (OAL_INTR_IRQ_UNDEFINED == irq2) {
// Unmask the primary interrupt
CLRREG32(&g_pIntrRegs->INTMSK, mask);
} else {
// Unmask the external interrupt
mask = 1 << (irq2 - IRQ_EINT4 + 4);
CLRREG32(&g_pPortRegs->EINTMASK, mask);
}
}
}
return sysIntr;
}
下面问题就产生了:
1.动态映射相对于静态分配有什么好处?难道是这样做灵活吗?但是这样做多了一些函数调用,相对静态分配来讲,哪个物理中断对应那个逻辑中断一看就很明确。
2.动态映射的一个流程是怎么样的,在网上找到一些资料,但是发现都没怎么说清楚。那位能说清楚一点,谢谢!
3.在网上查到的资料有
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 = OAL_INTR_IRQ_UNDEFINED;
}
for (i = 0; i < OAL_INTR_IRQ_MAXIMUM; i++) {
g_oalIrq2SysIntr = SYSINTR_UNDEFINED;
}
OALMSG(OAL_FUNC&&OAL_INTR, (L"-OALIntrMapInit\r\n"));
}
这样初始化,逻辑中断号都是-1,没有什么意义啊,那每个每个特定的中断,又是在那里理更改的这个两个数组了。做了两个数组做什么,应该只要一个数组就行了,只要把IRQ映射到SYSINTR不就行了?