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 + -
显示快捷键?