📄 intr.c
字号:
// Copyright (c) David Vescovi. All rights reserved.
// Part of Project DrumStix
// Windows Embedded Developers Interest Group (WE-DIG) community project.
// http://www.we-dig.org
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
//
// File: oalintr.c
//
// This file implement major part of interrupt module for the Intel PXA255 SoC.
//
#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include <oal.h>
#include "pxa255.h"
//------------------------------------------------------------------------------
// External Functions
// External Variables
// Defines
// Types
// Profiler ISR function pointer type.
//
typedef UINT32 (*PFN_PROFILER_ISR)(UINT32 ra);
// Global Variables
PFN_PROFILER_ISR g_pProfilerISR = NULL;
static volatile INTC_REG_T *g_pINTCRegs = NULL;
// Local Variables
// Local Functions
//------------------------------------------------------------------------------
//
// 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") );
// Initialize interrupt mapping
OALIntrMapInit();
// Map a pointer to the interrupt controller.
//
g_pINTCRegs = (volatile INTC_REG_T *) OALPAtoVA(PXA255_BASE_REG_PA_INTC, FALSE);
//
// Set DIM, the only bit in the ICCR.
// The effect is that only enabled and unmasked
// interrupts bring the processor out of IDLE mode.
//
g_pINTCRegs->ICCR = ICCR_DIM;
// Give BSP change to initialize subordinate controller
rc = BSPIntrInit();
// Setup static interrupt mappings (first one isn't really needed)
OALIntrStaticTranslate(SYSINTR_RESCHED, IRQ_OSMR0);
OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALInterruptInit(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALIntrRequestIrqs
//
// This function returns IRQ 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;
rc = BSPIntrRequestIrqs(pDevLoc, pCount, pIrqs);
cleanUp:
OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrRequestIrqs(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALIntrEnableIrqs
//
BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs)
{
BOOL rc = TRUE;
UINT32 irq, i;
OALMSG(OAL_INTR&&OAL_FUNC, (
L"+OALIntrEnableIrqs(%d, 0x%08x,%d)\r\n", count, pIrqs, *pIrqs
));
for (i = 0; i < count; i++) {
// Give BSP chance to enable irq on subordinate interrupt controller
irq = BSPIntrEnableIrq(pIrqs[i]);
if (irq == OAL_INTR_IRQ_UNDEFINED) continue;
if (irq <= IRQ_RTCALARM) {
// Enable the primary IRQ
SETREG32(&g_pINTCRegs->ICMR, (1 << irq));
} else {
rc = FALSE;
}
}
OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrEnableIrqs(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALIntrDisableIrqs
//
VOID OALIntrDisableIrqs(UINT32 count, const UINT32 *pIrqs)
{
UINT32 irq, i;
OALMSG(OAL_INTR&&OAL_FUNC, (
L"+OALIntrDisableIrqs(%d, 0x%08x)\r\n", count, pIrqs
));
for (i = 0; i < count; i++) {
// Give BSP chance to disable irq on subordinate interrupt controller
irq = BSPIntrDisableIrq(pIrqs[i]);
if (irq <= IRQ_RTCALARM) {
// Disable the primary IRQ
CLRREG32(&g_pINTCRegs->ICMR, (1 << irq));
}
}
OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrDisableIrqs\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: OALIntrDoneIrqs
//
VOID OALIntrDoneIrqs(UINT32 count, const UINT32 *pIrqs)
{
UINT32 irq, i;
OALMSG(OAL_INTR&&OAL_VERBOSE, (
L"+OALIntrDoneIrqs(%d, 0x%08x)\r\n", count, pIrqs
));
for (i = 0; i < count; i++) {
// Give BSP chance to finish irq on subordinate interrupt controller
irq = BSPIntrDoneIrq(pIrqs[i]);
if (irq == OAL_INTR_IRQ_UNDEFINED) continue;
if (irq <= IRQ_RTCALARM) {
// Enable the primary IRQ
SETREG32(&g_pINTCRegs->ICMR, (1 << irq));
}
}
OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OALIntrDoneIrqs\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: OEMInterruptHandler
//
ULONG OEMInterruptHandler(ULONG ra)
{
UINT32 irq = OAL_INTR_IRQ_UNDEFINED;
UINT32 sysIntr = SYSINTR_NOP;
if (!g_pINTCRegs) {
return(SYSINTR_NOP);
}
// Read the interrupt pending register
irq = g_pINTCRegs->ICIP;
if (irq == 0)
{
return(SYSINTR_NOP);
}
// Service the OS timer interrupt - OSMR0
if (irq & INTC_OSMR0)
{
// The rest is up to the timer interrupt handler.
//
sysIntr = OALTimerIntrHandler();
}
// Profiling timer interrupt?
else if (irq & INTC_OSMR2)
{
// Mask the interrupt
CLRREG32(&g_pINTCRegs->ICMR, INTC_OSMR2);
// The rest is up to the profiling interrupt handler (if profiling
// is enabled).
//
if (g_pProfilerISR) {
sysIntr = g_pProfilerISR(ra);
}
}
// Board-level interrupts
else
{
UINT32 irqNum,origIrqNum;
UINT32 mask = INTC_RTCALARM;
// Determine the IRQ of the highest priority pending interrupt
for (irqNum=IRQ_RTCALARM;irqNum>0;irqNum--)
{
if (mask & irq)
break;
else
mask >>= 1;
}
origIrqNum = irqNum;
if (irqNum == IRQ_GPIO0 || irqNum == IRQ_GPIO1 || irqNum == IRQ_GPIO84_2)
{
// Give BSP chance to translate IRQ -- if there is subordinate
// interrupt controller in BSP it give chance to decode its status
// and change IRQ
irqNum = BSPIntrActiveIrq(irqNum);
}
else
{
// Mask the interrupt
CLRREG32(&g_pINTCRegs->ICMR, mask);
}
// First find if IRQ is claimed by chain
sysIntr = (UINT16)NKCallIntChain((UCHAR)irqNum);
if (sysIntr == (UINT16)SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr))
{
// IRQ wasn't claimed, use static mapping
sysIntr = OALIntrTranslateIrq(irqNum);
}
// unmask interrupts in case it's NOP or invalid
if (SYSINTR_NOP == sysIntr)
{
if (origIrqNum != irqNum)
{
// BSP specific irq
BSPIntrEnableIrq (irqNum);
}
else
{
// Unmask the interrupt
SETREG32(&g_pINTCRegs->ICMR, mask);
}
}
}
return (sysIntr);
}
//------------------------------------------------------------------------------
//
// Function: OEMInterruptHandlerFIQ
//
void OEMInterruptHandlerFIQ()
{
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -