⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intr.c

📁 老外的一个开源项目
💻 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 + -