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

📄 intr.c

📁 NXP LPC3000系列 wince BSP包
💻 C
📖 第 1 页 / 共 2 页
字号:
//*********************************************************************
//* Software that is described herein is for illustrative purposes only  
//* which provides customers with programming information regarding the  
//* products. This software is supplied "AS IS" without any warranties.  
//* NXP Semiconductors assumes no responsibility or liability for the 
//* use of the software, conveys no license or title under any patent, 
//* copyright, or mask work right to the product. NXP Semiconductors 
//* reserves the right to make changes in the software without 
//* notification. NXP Semiconductors also make no representation or 
//* warranty that such application will be suitable for the specified 
//* use without further testing or modification. 
//*
//* Copyright NXP Semiconductors
//*********************************************************************
//
// intr.h
//
// This file implements LPC32xx interrupt functions.
//
#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include <nkexport.h>
#include "oal_log.h"
#include "oal_memory.h"
#include "oal_io.h"
#include "oal_timer.h"
#include "oal_intr.h"
#include <oal_ilt.h>

#include "bsp.h"
#include "dma.h"
#include "lpc32xx_intc.h"
#include "lpc32xx_dmac.h"

#define VIRTINTR 0xFFFFFFFF

// IRQ support list for SYSINTR mapping, not all interrupts are
// supported, as there is a limit of about 56 user interrupts in
// WinCE 6.0. The order of this list should match the OAL_INTR_IRQ_xxx
// order as specified in bsp.h to work correctly. This list does not
// control priority.
typedef struct {
	UINT32             oal_intr_irq_num;
	INTERRUPT_SOURCE_T lpc32xx_irq_num;
} OAL_TO_HW_IRQ_T;
static const OAL_TO_HW_IRQ_T lp32xx_ierqsupp[OAL_INTR_IRQ_LAST + 1] = {
	{OAL_INTR_IRQ_UART5,       IRQ_UART_IIR5},
	{OAL_INTR_IRQ_UART3,       IRQ_UART_IIR3},
    {OAL_INTR_IRQ_NAND,        IRQ_FLASH},
	{OAL_INTR_IRQ_SD0,         IRQ_SD0},
    {OAL_INTR_IRQ_SD1,         IRQ_SD1},
    {OAL_INTR_IRQ_MSTIMER,     IRQ_MSTIMER},
	{OAL_INTR_IRQ_TIMER0,      IRQ_TIMER0},
	{OAL_INTR_IRQ_SSP0,        IRQ_SSP0},
	{OAL_INTR_IRQ_SSP1,        IRQ_SSP1},
	{OAL_INTR_IRQ_I2S1,        IRQ_I2S1},
    {OAL_INTR_IRQ_ETHERNET,    IRQ_ETHERNET},
    {OAL_INTR_IRQ_TS_P,        IRQ_TS_P},
    {OAL_INTR_IRQ_TS,          IRQ_TS_IRQ},
    {OAL_INTR_IRQ_I2C_1,       IRQ_I2C_1},
    {OAL_INTR_IRQ_KEY,         IRQ_KEY},
    {OAL_INTR_IRQ_USB_HOST,    IRQ_USB_HOST},
    {OAL_INTR_IRQ_USB_DEV_DMA, IRQ_USB_DEV_DMA},
    {OAL_INTR_IRQ_USB_DEV_LP,  IRQ_USB_DEV_LP},
	{OAL_INTR_IRQ_USB_DEV_HP,  IRQ_USB_DEV_HP},
    {OAL_INTR_IRQ_I2C,         IRQ_USB_I2C},
    {OAL_INTR_IRQ_GPIO_00,     IRQ_GPIO_00},
    {OAL_INTR_IRQ_GPIO_01,     IRQ_GPIO_01},
    {OAL_INTR_IRQ_GPIO_02,     IRQ_GPIO_02},
    {OAL_INTR_IRQ_GPIO_03,     IRQ_GPIO_03},
    {OAL_INTR_IRQ_GPIO_04,     IRQ_GPIO_04},
    {OAL_INTR_IRQ_GPIO_05,     IRQ_GPIO_05},
    {OAL_INTR_IRQ_P0_P1_IRQ,   IRQ_P0_P1_IRQ},
	{OAL_INTR_IRQ_OTG_TIMER,   IRQ_USB_OTG_TIMER},
    {OAL_INTR_IRQ_OTG_ATC,     IRQ_USB_OTG_ATX},
    {OAL_INTR_IRQ_OTG_I2C,     IRQ_USB_I2C},
    {OAL_INTR_IRQ_GPI_07,      IRQ_GPI_07},
    {OAL_INTR_IRQ_GPI_00,      IRQ_GPI_00},
    {OAL_INTR_IRQ_GPI_01,      IRQ_GPI_01},
    {OAL_INTR_IRQ_GPI_02,      IRQ_GPI_02},
    {OAL_INTR_IRQ_GPI_03,      IRQ_GPI_03},
    {OAL_INTR_IRQ_GPI_04,      IRQ_GPI_04},
    {OAL_INTR_IRQ_GPI_05,      IRQ_GPI_05},
    {OAL_INTR_IRQ_GPI_06,      IRQ_GPI_06},
    {OAL_INTR_IRQ_I2C_2,       IRQ_I2C_2},

	// Required system interrupts
	{OAL_INTR_IRQ_RTC,         IRQ_RTC},
    {OAL_INTR_IRQ_TICK,        IRQ_TIMER3},
    {OAL_INTR_IRQ_PROFILER,    IRQ_TIMER2},

	// Virtual interrupts are not mapped
    {OAL_INTR_DMACH_0,         VIRTINTR},
    {OAL_INTR_DMACH_1,         VIRTINTR},
    {OAL_INTR_DMACH_2,         VIRTINTR},
    {OAL_INTR_DMACH_3,         VIRTINTR},
    {OAL_INTR_DMACH_4,         VIRTINTR},
    {OAL_INTR_DMACH_5,         VIRTINTR},
    {OAL_INTR_DMACH_6,         VIRTINTR}
};

// Map list for LPC32xx IRQ to BSP IRQ. This is used to convert a LPC32xx
// interrupt ID (0..95) to a WinCE IRQ ID of type OAL_INTR_IRQ_xxxx.
static UINT32 lp32xxToBSPIRQ[IRQ_END_OF_INTERRUPTS];

// Pointers to interrupt controller registers
static INTC_REGS_T *pMIC, *pSIC1, *pSIC2;

// Pointer to DMA registers (for virtual DMA mapping)
static DMAC_REGS_T *pDMARegs;

#ifdef IMGPROFILFER
#if IMGPROFILFER==1
//  Function pointer to profiling timer ISR routine
extern PFN_PROFILER_ISR g_pProfilerISR;
#endif
#endif

//------------------------------------------------------------------------------
//
// int_get_controller
//
// Returns the controller ID and mask based on the interrupt source
//
static BOOL int_get_controller(INTERRUPT_SOURCE_T source, 
							   INTC_REGS_T **pIntc_base,
							   UINT32 *pBit_pos)
{
	BOOL ret_value = TRUE;

	/* Determine the interrupt controller */
	if (source < IRQ_SIC1_BASE)
	{
		*pIntc_base = pMIC;
		*pBit_pos = (UINT32) source;
	}
	else if ((source >= IRQ_SIC1_BASE) && (source < IRQ_SIC2_BASE))
	{
		*pIntc_base = pSIC1;
		*pBit_pos = ((UINT32) source - IRQ_SIC1_BASE);
	}
	else if (source <= IRQ_END_OF_INTERRUPTS)
	{
		*pIntc_base = pSIC2;
		*pBit_pos = ((UINT32) source - IRQ_SIC2_BASE);
	}
	else 
	{
		*pIntc_base = 0;
		*pBit_pos = 0;
		ret_value = FALSE;
	}

	return ret_value;
}

//------------------------------------------------------------------------------
//
// OALIntrInit
//
// This function initializes the interrupt hardware and sets the default IRQ
// to SYSINTR mapping for some static peripherals.
//
BOOL OALIntrInit()
{
	int idx;

	// Save pointers to MIC, SIC1, and SIC2
	pMIC = (INTC_REGS_T *) OALPAtoVA((UINT32) MIC, FALSE);
	pSIC1 = (INTC_REGS_T *) OALPAtoVA((UINT32) SIC1, FALSE);
	pSIC2 = (INTC_REGS_T *) OALPAtoVA((UINT32) SIC2, FALSE);
	pDMARegs = (DMAC_REGS_T *) OALPAtoVA((UINT32) DMA_BASE, FALSE);

    // Initialize interrupt mapping
    OALIntrMapInit();

	// Clear backmapping for LPC32xx to BSP IRQ list
	for (idx = 0; idx < IRQ_END_OF_INTERRUPTS; idx++)
	{
		lp32xxToBSPIRQ [idx] = OAL_INTR_IRQ_UNDEFINED;
	}

	// Setup backmapping for non-virtual interrupts
	for (idx = 0; idx < OAL_INTR_VIRT_FIRST; idx++)
	{
		lp32xxToBSPIRQ [lp32xx_ierqsupp [idx].lpc32xx_irq_num] =
			lp32xx_ierqsupp [idx].oal_intr_irq_num;
	}

    // Setup static interrupt mappings
    OALIntrStaticTranslate(SYSINTR_RESCHED, OAL_INTR_IRQ_TICK);
	lp32xxToBSPIRQ[IRQ_TIMER3] = OAL_INTR_IRQ_TICK;
    OALIntrStaticTranslate(SYSINTR_RTC_ALARM, OAL_INTR_IRQ_RTC);
	lp32xxToBSPIRQ[IRQ_RTC] = OAL_INTR_IRQ_RTC;
#ifdef IMGPROFILFER
#if IMGPROFILFER==1
    OALIntrStaticTranslate(SYSINTR_PROFILE, OAL_INTR_IRQ_PROFILER);
	lp32xxToBSPIRQ[IRQ_TIMER2] = OAL_INTR_IRQ_PROFILER;
#endif
#endif

	// Static map of USB OHCI interrupt makes using the WinCE OHCI
	// HCD driver easier
    OALIntrStaticTranslate(SYSINTR_FIRMWARE, OAL_INTR_IRQ_USB_HOST);
	lp32xxToBSPIRQ[IRQ_USB_HOST] = OAL_INTR_IRQ_USB_HOST;

	// Initialize main interrupt controller
	pMIC->er = 0x00000000;         // disable all interrupt sources
	pMIC->rsr = 0xFFFFFFFF;        // clear all edge triggered interrupts
	pMIC->apr = MIC_APR_DEFAULT;   // set polarity for all internal irqs
	pMIC->atr = MIC_ATR_DEFAULT;   // set act. types for all internal irqs
	pMIC->itr = (_BIT(IRQ_SUB1FIQ) | _BIT(IRQ_SUB2FIQ));

	// Initialize sub interrupt controller 1
	pSIC1->er = 0x00000000;        // disable all interrupt sources
	pSIC1->rsr = 0xFFFFFFFF;       // clear all edge triggered interrupts
	pSIC1->apr = SIC1_APR_DEFAULT; // set polarity for internal irqs
	pSIC1->atr = SIC1_ATR_DEFAULT; // set act-types for internal irqs
	pSIC1->itr = 0x00000000;       // set all interrupts as irqs

	// Initialize sub interrupt controller 2
	pSIC2->er = 0x00000000;        // disable all interrupt sources
	pSIC2->rsr = 0xFFFFFFFF;       // clear all edge triggered interrupts
	pSIC2->apr = SIC2_APR_DEFAULT; // set polarity for internal irqs
	pSIC2->atr = SIC2_ATR_DEFAULT; // set act. types for internal irqs
	pSIC2->itr = 0x00000000;       // set all interrupts as irqs

    // Enable sub-IRQ handlers and DMA on main interrupt controller
	pMIC->er = (_BIT(IRQ_SUB1IRQ) | _BIT(IRQ_SUB2IRQ) | _BIT(IRQ_DMA));

	return TRUE;
}

//------------------------------------------------------------------------------
//
// findfirstbit
//
// Returns the first high bit in a word
//
#if 0
static UINT32 findfirstbit(UINT32 val)
{
	UINT32 msk = 0;

	while ((val & _BIT(msk)) == 0)
	{
		msk++;
	}

	return msk;
}
#else
// Use assembly version, it's much faster
extern UINT32 findfirstbit(UINT32 val);
#endif
//------------------------------------------------------------------------------
//
// IntrEnableVirtual
//
// Used for enabling and disabling virtual interrupts (DMA).
//
static BOOL IntrEnableVirtual(OAL_TO_HW_IRQ_T *pIrqHw,
							  BOOL enable)
{
	UINT32 dmaChan;
	BOOL rc = FALSE;

	// For now, these only apply to DMA
	if ((pIrqHw->oal_intr_irq_num >= OAL_INTR_DMACH_0) &&
		(pIrqHw->oal_intr_irq_num <= OAL_INTR_DMACH_6))
	{
		// Get DMA channel
		dmaChan = (UINT32) pIrqHw->oal_intr_irq_num - OAL_INTR_DMACH_0;

		// Only works when DMA channel has been enabled
		if (enable == FALSE)
		{
			pDMARegs->dma_chan[dmaChan].config_ch &= ~(DMAC_CHAN_ITC | DMAC_CHAN_IE);
		}
		else
		{
			pDMARegs->dma_chan[dmaChan].config_ch |= (DMAC_CHAN_ITC | DMAC_CHAN_IE);
		}

		rc = TRUE;
	}

	return rc;
}

//------------------------------------------------------------------------------
//
// OALIntrEnableIrqs
//
// The IRQ passed in is of a value of type OAL_INTR_IRQ_xxx from bsp.h. This
// needs to be converted to an LPC32XX type (INTERRUPT_SOURCE_T) to be disabled
// in hardware.

⌨️ 快捷键说明

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