intr_static

来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· 代码 · 共 478 行

TXT
478
字号
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
//  File: intr.c
//
//  This file implement major part of interrupt module for SMDK24A0 SoC.
//
#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include <oal.h>
#include <s3c24A0.h>
#include <s3c24A0_intr.h>
#include <intr.h>
#include <drv_glob.h>

#define DBG_ON 1

//------------------------------------------------------------------------------
//
//  Globals.

//  The global variables are storing virual address for interrupt and port
//  registers for use in interrupt handling to avoid possible time consumig
//  call to OALPAtoVA function.
//
static volatile S3C24A0_INTR_REG	*g_pIntrRegs; 
static volatile S3C24A0_IOPORT_REG	*g_pPortRegs;
static volatile S3C24A0_SDI_REG		*g_pSDIRegs; 
static volatile S3C24A0_PWM_REG		*g_pPWMRegs;
static volatile S3C24A0_ADC_REG		*g_pADCRegs;
static volatile S3C24A0_SDI_REG		*g_pSDIORegs;
//  Function pointer to profiling timer ISR routine.
//
PFN_PROFILER_ISR g_pProfilerISR = NULL;


//------------------------------------------------------------------------------
//
//  Function:  OALIntrInit
//
//  This function initialize interrupt mapping, hardware and call platform
//  specific initialization.
//
BOOL OALIntrInit()
{
	BOOL rc = FALSE;
    
	OALMSG( OAL_FUNC&&OAL_INTR, (L"+OALInterruptInit\r\n"));
	RETAILMSG(DBG_ON, (TEXT("In OALIntrInit++\r\n")));

	// Initialize interrupt mapping
	OALIntrMapInit();

	// First get uncached virtual addresses
	g_pIntrRegs		= (S3C24A0_INTR_REG*)OALPAtoVA(S3C24A0_BASE_REG_PA_INTR, FALSE);
	g_pPortRegs		= (S3C24A0_IOPORT_REG*)OALPAtoVA(S3C24A0_BASE_REG_PA_IOPORT, FALSE);
//	g_pSDIRegs		= (S3C24A0_SDI_REG*)OALPAtoVA(S3C24A0_BASE_REG_PA_SDI, FALSE);
	g_pPWMRegs	= (S3C24A0_PWM_REG*)OALPAtoVA(S3C24A0_BASE_REG_PA_PWM, FALSE);
	g_pADCRegs		= (S3C24A0_ADC_REG*)OALPAtoVA(S3C24A0_BASE_REG_PA_ADC, FALSE);
	g_pSDIORegs		= (S3C24A0_SDI_REG*)OALPAtoVA(S3C24A0_BASE_REG_PA_SDI, FALSE);

	// Mask and clear external interrupts
	g_pPortRegs->EINTMASK =  0xFFFFFFFF;
	g_pPortRegs->EINTPEND =  0xFFFFFFFF;

	// Mask and clear internal interrupts
	g_pIntrRegs->INTMSK = BIT_ALLMSK;
	if (g_pIntrRegs->SRCPND) 
		g_pIntrRegs->SRCPND =  BIT_ALLMSK;

	// Write the INTPND value itself to clear.
	if (g_pIntrRegs->INTPND) 
		g_pIntrRegs->INTPND = g_pIntrRegs->INTPND;

	// Mask and clear sub interrupt regs
	if (g_pIntrRegs->SUBSRCPND) 
		g_pIntrRegs->SUBSRCPND = BIT_SUB_ALLMSK;
	g_pIntrRegs->INTSUBMSK = BIT_SUB_ALLMSK;
	
#ifdef OAL_BSP_CALLBACKS
    // Give BSP change to initialize subordinate controller
	rc = BSPIntrInit();
#else
	rc = TRUE;
#endif

	OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrInit(rc = %d)\r\n", rc));
	return rc;
}



//------------------------------------------------------------------------------
//
//  Function:  OALIntrRequestIrqs
//
//  This function returns IRQs for CPU/SoC devices based on their
//  physical address.
//
BOOL OALIntrRequestIrqs(DEVICE_LOCATION *pDevLoc, UINT32 *pCount, UINT32 *pIrqs)
{
    BOOL rc = FALSE;

    OALMSG(OAL_INTR&&OAL_FUNC, (
        L"+OALIntrRequestIrqs(0x%08x->%d/%d/0x%08x/%d, 0x%08x, 0x%08x)\r\n",
        pDevLoc, pDevLoc->IfcType, pDevLoc->BusNumber, pDevLoc->LogicalLoc,
        pDevLoc->Pin, pCount, pIrqs
    ));

    // This shouldn't happen
    if (*pCount < 1) goto cleanUp;

#ifdef OAL_BSP_CALLBACKS
    rc = BSPIntrRequestIrqs(pDevLoc, pCount, pIrqs);
#endif    

cleanUp:        
    OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrRequestIrqs(rc = %d)\r\n", rc));
    return rc;
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntrEnableIrqs
//
BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs)
{
	UINT32 sysIntr = SYSINTR_NOP;
    BOOL rc = TRUE;
    UINT32 i, 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	
		
		RETAILMSG(DBG_ON, (L"+OALIntrEnableIrqs(%d)\r\n", irq));
		INTERRUPTS_OFF();
		//TBDA change all sysintr to irq codes
		switch (irq) 
		{
		case INTSRC_TIMER34:
			RETAILMSG(DBG_ON,(TEXT("OALIntrEnableIrqs:Timing\r\n")));
			// Clear the interrupt
			g_pIntrRegs->INTMSK &= ~( 1 << INTSRC_TIMER34);
			g_pIntrRegs->INTSUBMSK &= ~ (1 << INTSRC_TIMER34);			
			break;
				
		case INTSRC_ADC:
			g_pIntrRegs->INTMSK &= ~BIT_ADC;
			g_pIntrRegs->INTSUBMSK &= ~(BIT_SUB_PENUP|BIT_SUB_PENDN);
			RETAILMSG(DBG_ON,(TEXT("OALIntrEnableIrqs:TOUCH\r\n")));
			break;
			
		case INTSRC_TIMER1:
			RETAILMSG(DBG_ON,(TEXT("OALIntrEnableIrqs:TOUCH CHANGED\r\n")));			
			g_pIntrRegs->INTMSK &= ~BIT_TIMER1;
			
			break;
			
		case SYSINTR_SERIAL:	// Serial port.
			RETAILMSG(1,(_T("OEMInterruptEnable:SERIAL\r\n")));
			g_pIntrRegs->SUBSRCPND  = (INTSUB_RXD0 | INTSUB_TXD0 | INTSUB_ERR0);
			g_pIntrRegs->INTSUBMSK &= ~INTSUB_RXD0;
			g_pIntrRegs->INTSUBMSK &= ~INTSUB_TXD0;
			g_pIntrRegs->INTSUBMSK &= ~INTSUB_ERR0;
			g_pIntrRegs->SRCPND     = BIT_UART0;
			
			if (g_pIntrRegs->INTPND & BIT_UART0) g_pIntrRegs->INTPND = BIT_UART0;
			g_pIntrRegs->INTMSK    &= ~BIT_UART0;
			break;

		default:
			RETAILMSG(DBG_ON,(TEXT("OALIntrEnableIrqs:Unsupported %d\r\n"),irq));
			rc = FALSE;	/* unsupported interrupt value */
			break;
		}
	
	}
    
	INTERRUPTS_ON();
    
    OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrEnableIrqs(rc = %d)\r\n", rc));
    return rc;    
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntrDisableIrqs
//
VOID OALIntrDisableIrqs(UINT32 count, const UINT32 *pIrqs)
{
    UINT32 i, irq;
	
    OALMSG(OAL_INTR&&OAL_FUNC, (
        L"+OALIntrDisableIrqs(%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 disable irq on subordinate interrupt controller
        irq = BSPIntrDisableIrq(pIrqs[i]);
        if (irq == OAL_INTR_IRQ_UNDEFINED) continue;
#endif
        INTERRUPTS_OFF();
		
		switch (irq) 
		{
		case INTSRC_TIMER1:
			RETAILMSG(DBG_ON,(TEXT("OEMInterruptDisable:TOUCH CHANGED \r\n\r\n")));
			break;
			
		case INTSRC_ADC:
			g_pIntrRegs->INTMSK |= BIT_ADC;
			g_pIntrRegs->INTSUBMSK |= (BIT_SUB_PENUP|BIT_SUB_PENDN);
			RETAILMSG(DBG_ON,(TEXT("OEMInterruptDisable:TOUCH \r\n\r\n")));
			break;
			
		case SYSINTR_SERIAL:
			g_pIntrRegs->INTMSK    |= BIT_UART0;
			g_pIntrRegs->INTSUBMSK |= INTSUB_RXD0;
			g_pIntrRegs->INTSUBMSK |= INTSUB_TXD0;
			g_pIntrRegs->INTSUBMSK |= INTSUB_ERR0;
			break;
		default:
			RETAILMSG(DBG_ON,(TEXT("OEMInterruptDisable:Unsupported \r\n")));			
			break;
		}
	}
	INTERRUPTS_ON();
	
    OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrDisableIrqs\r\n"));
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntrDoneIrqs
//
void 
OALIntrDoneIrqs(
				UINT32 count, 
				const UINT32 *pIrqs
				)
{
    UINT32 i, irq;
	
    //OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OALIntrDoneIrqs(%d, 0x%08x)\r\n", count, pIrqs));
	
	INTERRUPTS_OFF();
	
    for (i = 0; i < count; i++) 
	{
#ifndef OAL_BSP_CALLBACKS
        irq = pIrqs[i];
#else
        // Give BSP chance to finish irq on subordinate interrupt controller
        irq = BSPIntrDoneIrq(pIrqs[i]);
#endif    
		
		switch (irq) 
		{		
		case INTSRC_TIMER1:
			g_pIntrRegs->INTMSK &= ~BIT_TIMER1;
			RETAILMSG(DBG_ON,(TEXT("OEMInterruptDone:TOUCH CHANGED\n\r\n")));
			break;
			
		case INTSRC_ADC:
			g_pIntrRegs->INTMSK &= ~BIT_ADC;
//			g_pIntrRegs->INTSUBMSK &= ~(BIT_SUB_PENUP|BIT_SUB_PENDN);
			RETAILMSG(DBG_ON,(TEXT("OEMInterruptDone:TOUCH \n\r\n")));
			break;	
		case SYSINTR_SERIAL:
			g_pIntrRegs->INTMSK    &= ~BIT_UART0;
			g_pIntrRegs->INTSUBMSK &= ~INTSUB_RXD0;
			break;
			
       	default:
			RETAILMSG(DBG_ON,(TEXT("OEMInterruptDone:unsupported\r\n")));
			break;
		}
		
    }
	INTERRUPTS_ON();
	
//    OALMSG(0, (L"-OALIntrDoneIrqs\r\n"));
}


//------------------------------------------------------------------------------
//
//  Function:  OEMInterruptHandler
//
ULONG OEMInterruptHandler(ULONG ra)
{    
	static BYTE nLED = 0x1;	
	
	UINT32 sysIntr = SYSINTR_NOP;
	
	unsigned int IntPendVal;
	unsigned int SubIntPendVal;	// for serial
	//DWORD			submask;
	
	static DWORD HeartBeatCnt, HeartBeatStat;
	
	TOUCH_GLOBALS *odo_tsb;  //Sample buffer stuff
	// for this, You MUST modify bsp/inc/drv_glob.h.. check drv_glob.h_jylee TBD
	odo_tsb = &((DRIVER_GLOBALS *)DRIVER_GLOBALS_PHYSICAL_MEMORY_START)->tch;

//	RETAILMSG(DBG_ON,(TEXT("++++++++++++++++++++++++++Interrupthandler\n\r\n")));
	IntPendVal = g_pIntrRegs->INTOFFSET;	// Get pending IRQ mode interrupt in INTPND.
    
	//
	// Check the timer interrupt.
	//
	if (IntPendVal == INTSRC_TIMER34) 
	{
		SubIntPendVal = g_pIntrRegs->SUBSRCPND;
		
		if (SubIntPendVal & BIT_SUB_TIMER4)
		{			
			if (++HeartBeatCnt > 1000)
			{
				HeartBeatCnt   = 0;
				HeartBeatStat ^= 1;
				RETAILMSG(DBG_ON,(TEXT("Interrupthandler :--->BIT_SUB_TIMER4 \n\r\n")));
				if (HeartBeatStat)                        
					g_pPortRegs->GPDAT &= ~(1 << 7); // LED 7 On
				else
					g_pPortRegs->GPDAT |=  (1 << 7); // LED 7 Off
			}
			
/*			g_pPWMRegs->TCON &= (~(0xf << 20));
			
			g_pPWMRegs->TCON |= (2 << 20);		// update TCNTB4, stop
			g_pPWMRegs->TCON |= (1 << 20);		// one-shot mode,  start
*/			
			//
			// Clear the interrupt
			//
			g_pIntrRegs->SUBSRCPND	= BIT_SUB_TIMER4;
			g_pIntrRegs->SRCPND		= BIT_TIMER34;
			
			if (g_pIntrRegs->INTPND & BIT_TIMER34) 
				g_pIntrRegs->INTPND = BIT_TIMER34;
			
			// Rest is on timer interrupt handler
			sysIntr = OALTimerIntrHandler();
			return sysIntr;
		}
		else 
		{
			RETAILMSG(DBG_ON, (TEXT("Not needed-----Timer4 Inerrupt !!!!!!!!!!!!!!!!!!!!\r\n")));
			return SYSINTR_NOP;
		}
	} 
	else if (IntPendVal == INTSRC_RTC)
	{
		g_pIntrRegs->SRCPND  = BIT_RTC;   /* Interrupt Clear              */
		g_pIntrRegs->INTPND  = BIT_RTC;
		g_pIntrRegs->INTMSK |= BIT_RTC;   /* Alarm Interrupt Disable      */
		return SYSINTR_RTC_ALARM;
	}
	else if (IntPendVal == INTSRC_ADC) // INTSRC_ADC
	{
        // Touch Panel Int
       	SubIntPendVal = g_pIntrRegs->SUBSRCPND;
       	
       	if (SubIntPendVal & INTSUB_PENUP) 
		{
       		g_pIntrRegs->INTSUBMSK |= INTSUB_PENUP;
       		g_pIntrRegs->SUBSRCPND  = INTSUB_PENUP;
       	
            g_pIntrRegs->INTMSK |= BIT_ADC;
   	        g_pIntrRegs->SRCPND  = BIT_ADC;        
       	    if (g_pIntrRegs->INTPND & BIT_ADC) g_pIntrRegs->INTPND = BIT_ADC;

   	        odo_tsb->status = TOUCH_PEN_UP;
           
			//RETAILMSG(0,(TEXT("armint.c::INTSUB_PENUP\r\n")));
       
	        return SYSINTR_TOUCH_CHANGED;
		} 
		else if (SubIntPendVal & INTSUB_PENDN) 
		{
       		g_pIntrRegs->INTSUBMSK |= INTSUB_PENDN;
       		g_pIntrRegs->SUBSRCPND  = INTSUB_PENDN;
       	
            g_pIntrRegs->INTMSK |= BIT_ADC;
   	        g_pIntrRegs->SRCPND  = BIT_ADC;        
       	    if (g_pIntrRegs->INTPND & BIT_ADC) g_pIntrRegs->INTPND = BIT_ADC;

   	        odo_tsb->status = TOUCH_PEN_DOWN;

			//RETAILMSG(0,(TEXT("armint.c::INTSUB_PENDN\r\n")));
           
	        return SYSINTR_TOUCH_CHANGED;
		}
       	else if (SubIntPendVal & INTSUB_ADC)
		{
       		g_pIntrRegs->INTSUBMSK |= INTSUB_ADC;
       		g_pIntrRegs->SUBSRCPND = INTSUB_ADC;

	        g_pIntrRegs->INTMSK |= BIT_ADC;
   		    g_pIntrRegs->SRCPND = BIT_ADC;        
       		if (g_pIntrRegs->INTPND & BIT_ADC) g_pIntrRegs->INTPND = BIT_ADC;
            	
        	g_pIntrRegs->INTMSK &= ~BIT_ADC;

			//RETAILMSG(0,(_T("armint.c::INTSUB_ADC\r\n")));
           	return SYSINTR_NOP;
       	}
       	else
       		return SYSINTR_NOP;
	}

	else if (IntPendVal == INTSRC_TIMER1) // INTSRC_TIMER1
	{
       // Timer 1 interrupt to get touch point
      	g_pIntrRegs->INTMSK |= BIT_TIMER1;
       	g_pIntrRegs->SRCPND = BIT_TIMER1;
  	    if (g_pIntrRegs->INTPND & BIT_TIMER1) g_pIntrRegs->INTPND = BIT_TIMER1;

		if( (g_pADCRegs->ADCDAX & 0x8000) || (g_pADCRegs->ADCDAY & 0x8000) ){
			//RETAILMSG(0,(TEXT("armint.c::INT Touch SYSINTR_TOUCH_CHANGED 1\r\n")));
			odo_tsb->status = TOUCH_PEN_UP;
			return SYSINTR_TOUCH_CHANGED;
		}

        if(odo_tsb->status == TOUCH_PEN_UP) 
		{
			//RETAILMSG(0,(TEXT("armint.c::INT Touch SYSINTR_TOUCH_CHANGED 2 \r\n")));
			odo_tsb->status = TOUCH_PEN_UP;
			return SYSINTR_TOUCH_CHANGED;
		}
        else 
		{
			unsigned int TmpTCON;

        	odo_tsb->status = TOUCH_PEN_SAMPLE;

			TmpTCON = g_pPWMRegs->TCON;	// get TCON value to temp TCON register
			g_pPWMRegs->TCON = (TmpTCON & ~(0xf00)) | (0x200);	// stop, one-shot, inverter off, TCNTB1 update
			g_pPWMRegs->TCON = (TmpTCON & ~(0xf00)) | (0x100);	// start

			//RETAILMSG(0,(TEXT("armint.c::INT Touch SYSINTR_TOUCH timer1 restart\r\n")));
	
        	return SYSINTR_TOUCH;
		}
	}
	RETAILMSG(DBG_ON,(TEXT("Some Other Interrupt %d\r\n"), IntPendVal));
	return (SYSINTR_NOP);
}

//------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?