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

📄 mpc8240epic.c

📁 MPC8241:本程序是freescale的824*系列的BSP源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* mpc8240Epic.c - EPIC Interrupt Controller driver */

/* Copyright 1984-2000 Wind River Systems, Inc. */
/* Copyright 1996-2000 Motorola, Inc., All Rights Reserved */
#include "copyright_wrs.h"

/*
modification history
--------------------
01a,28feb00,rhk  created from version 01d, MV2100 BSP.
*/

/*
DESCRIPTION

This module implements the EPIC interrupt controller functionality.
*/


/* includes */

#include "mpc8240.h"
#include "mpc8240Epic.h"

/* defines */

/* globals */

IMPORT STATUS	      (*_func_intConnectRtn) (VOIDFUNCPTR *, VOIDFUNCPTR, int);
IMPORT int	      (*_func_intEnableRtn) (int);
IMPORT int	      (*_func_intDisableRtn) (int);
IMPORT UINT32 		sysPciInLong (UINT32);
IMPORT void   		sysPciOutLong (UINT32, UINT32);
IMPORT STATUS		excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);
IMPORT UINT		sysGetMpuSpd(void);
IMPORT void		sysDecDelay (UINT usDelay);
void			sysEpicIntHandler (void);

/* system interrupt table */

#define SYSTEM_INTERRUPT_TABLE_SIZE     256

INT_HANDLER_DESC * sysIntTbl [SYSTEM_INTERRUPT_TABLE_SIZE];

#ifdef INCLUDE_INSTRUMENTATION
IMPORT	int             evtTimeStamp;
#endif

/* forward declarations */

LOCAL int       getEpicVecAddr (int);
LOCAL STATUS	sysEpicIntConnect (VOIDFUNCPTR * vector, VOIDFUNCPTR routine,
                                   int parameter);
LOCAL int	sysEpicIntEnable (int);
LOCAL int	sysEpicIntDisable (int);

LOCAL int 	getEpicPrio(UINT32 vecRegAddr);

#ifndef CPU_INT_LOCK
#   define CPU_INT_LOCK(x) \
	(*x = intLock ())
#endif

#ifndef CPU_INT_UNLOCK
#   define CPU_INT_UNLOCK(data) \
	(intUnlock (data))
#endif


/*******************************************************************************
*
* epicCurTaskPrioSet - set the priority of the current task.
*
* NOTES
*
* epicCurTaskPrioSet sets the priority of the Processor Current Task
* Priority register to the value of the prioNum parameter.  This function
* should be called after sysEpicInit() to lower the priority of the processor
* current task. Note that valid priority values are 0 through 15 (15 being
* the highest priority)
*
* NOMANUAL
* 
* RETURNS: previous priority of the task.
*
* This function added by xdg, 00.10.13
*/

ULONG epicCurTaskPrioSet
    (
    int prioNum
    )
    {
    ULONG oldPrio;

    if ((prioNum < 0) || (prioNum > 15))
    {
        return (EPIC_INV_PRIO_ERROR);
	}

	oldPrio = sysPciInLong ((UINT32)EPIC_CUR_TASK_PRI_REG);
    
    sysPciOutLong ((UINT32)EPIC_CUR_TASK_PRI_REG, (UINT32)prioNum);

    return (oldPrio);
    }


/******************************************************************************
*
* sysEpicInit - initialize the EPIC
*
* This function initializes the Embedded Programmable Interrupt Controller 
* (EPIC) contained in the Mpc8240 chip.
*
* It first initializes the system vector table, connects the EPIC interrupt
* handler to the PPC external interrupt and attaches the local EPIC routines
* for interrupt connecting, enabling and disabling to the corresponding system
* routine pointers.
*
* It then initializes the EPIC registers, clears any pending EPIC interrupts,
* and enables interrupt handling by the EPIC.
*
* RETURNS: OK always
*/
STATUS sysEpicInit (void)
    {
    int			i;
    UINT32 temp = 0;

    /* Initialize the interrupt table */

    for (i = 0; i < SYSTEM_INTERRUPT_TABLE_SIZE; i++)
        sysIntTbl[i] = NULL;
    
    /*reset the EPIC unit*/
	sysPciOutLong((UINT32)EPIC_GLOBAL_CONFIG_REG, 0x80000000);
	
	/* wait for the reset sequence to be completed */
	while(sysPciInLong((UINT32)EPIC_GLOBAL_CONFIG_REG)&0x80000000)
		{
		;
		}
	

    /* Initialze the global timer frequency to the MPU speed. */
#if(0)
    sysPciOutLong((UINT32)EPIC_TIMER_FREQ_REG, sysGetMpuSpd());
#endif
    /* Initialze the 4 global timer interrupt sources */

    sysPciOutLong((UINT32)EPIC_TIMER0_VEC_PRI_REG, INIT_TMR_SRC0);
    sysPciOutLong((UINT32)EPIC_TIMER1_VEC_PRI_REG, INIT_TMR_SRC0);
    sysPciOutLong((UINT32)EPIC_TIMER2_VEC_PRI_REG, INIT_TMR_SRC0);
    sysPciOutLong((UINT32)EPIC_TIMER3_VEC_PRI_REG, INIT_TMR_SRC0);
    
#if(0)
    /* Initialize the 16 serial interrupt sources */

    sysPciOutLong((UINT32)EPIC_SER_SRC0_VEC_PRI_REG, INIT_SER_SRC0);
    sysPciOutLong((UINT32)EPIC_SER_SRC1_VEC_PRI_REG, INIT_SER_SRC1);
    sysPciOutLong((UINT32)EPIC_SER_SRC2_VEC_PRI_REG, INIT_SER_SRC2);
    sysPciOutLong((UINT32)EPIC_SER_SRC3_VEC_PRI_REG, INIT_SER_SRC3);
    sysPciOutLong((UINT32)EPIC_SER_SRC4_VEC_PRI_REG, INIT_SER_SRC4);
    sysPciOutLong((UINT32)EPIC_SER_SRC5_VEC_PRI_REG, INIT_SER_SRC5);
    sysPciOutLong((UINT32)EPIC_SER_SRC6_VEC_PRI_REG, INIT_SER_SRC6);
    sysPciOutLong((UINT32)EPIC_SER_SRC7_VEC_PRI_REG, INIT_SER_SRC7);
    sysPciOutLong((UINT32)EPIC_SER_SRC8_VEC_PRI_REG, INIT_SER_SRC8);
    sysPciOutLong((UINT32)EPIC_SER_SRC9_VEC_PRI_REG, INIT_SER_SRC9);
    sysPciOutLong((UINT32)EPIC_SER_SRC10_VEC_PRI_REG, INIT_SER_SRC10);
    sysPciOutLong((UINT32)EPIC_SER_SRC11_VEC_PRI_REG, INIT_SER_SRC11);
    sysPciOutLong((UINT32)EPIC_SER_SRC12_VEC_PRI_REG, INIT_SER_SRC12);
    sysPciOutLong((UINT32)EPIC_SER_SRC13_VEC_PRI_REG, INIT_SER_SRC13);
    sysPciOutLong((UINT32)EPIC_SER_SRC14_VEC_PRI_REG, INIT_SER_SRC14);
    sysPciOutLong((UINT32)EPIC_SER_SRC15_VEC_PRI_REG, INIT_SER_SRC15);
#else
    /* Initialize the 4 external interrupt sources */
    sysPciOutLong((UINT32)EPIC_EXT_SRC0_VEC_PRI_REG, INIT_EXT_SRC0);
    sysPciOutLong((UINT32)EPIC_EXT_SRC1_VEC_PRI_REG, INIT_EXT_SRC1);
    sysPciOutLong((UINT32)EPIC_EXT_SRC2_VEC_PRI_REG, INIT_EXT_SRC2);
    sysPciOutLong((UINT32)EPIC_EXT_SRC3_VEC_PRI_REG, INIT_EXT_SRC3);            
    sysPciOutLong((UINT32)EPIC_EXT_SRC4_VEC_PRI_REG, INIT_EXT_SRC4);
    
#endif

    /* Initialize the 2 DMA interrupt sources */

    sysPciOutLong((UINT32)EPIC_DMA_CHAN0_INTR_VEC_SRC, INIT_DMA_SRC0);
    sysPciOutLong((UINT32)EPIC_DMA_CHAN1_INTR_VEC_SRC, INIT_DMA_SRC1);

    /* Initialize the I2C unit interrupt source */

    sysPciOutLong((UINT32)EPIC_I2C_INTR_VEC_SRC, INIT_I2C_SRC);

    /* Initialize the message unit interrupt source. */

    sysPciOutLong((UINT32)EPIC_MSG_UNIT_INTR_VEC_SRC, INIT_MSGUNIT_SRC);

    sysPciOutLong((UINT32)EPIC_DUART_CHAN1_INTR_VEC_SRC, INIT_DUART_SRC1);
    sysPciOutLong((UINT32)EPIC_DUART_CHAN2_INTR_VEC_SRC, INIT_DUART_SRC2);
    /* Setup the EPIC to mixed mode. */

    temp = sysPciInLong((UINT32)EPIC_GLOBAL_CONFIG_REG );
    sysPciOutLong((UINT32)EPIC_GLOBAL_CONFIG_REG, (temp | EPIC_GC_MIXED));

    /* Set to direct-interrupt mode (5 extern int  sources) and clock ratio to 4. */

    temp = sysPciInLong((UINT32)EPIC_INTR_CONFIG_REG);
    temp = temp & (~EPIC_IC_R_MASK); 
    sysPciOutLong((UINT32)EPIC_INTR_CONFIG_REG, (temp | 
                                      (EPIC_IC_R_VALUE << EPIC_IC_R_SHFT)));

	/* Clear all pending interrupt */
	while(sysPciInLong((UINT32)EPIC_IACK_REG)!=0xff)
	{
		;
	}

    /* connect the interrupt demultiplexer to the PowerPC external interrupt */
#if(1)
    excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, sysEpicIntHandler);

    /* attach the BSP specific routines to the operating system.  */

    _func_intConnectRtn = sysEpicIntConnect;
    _func_intEnableRtn = sysEpicIntEnable;
    _func_intDisableRtn = sysEpicIntDisable;
#endif

    /* Enable interrupts for this processor (1 and above). */

	epicCurTaskPrioSet( EPIC_TASK_PRI_0 );
    
    return(OK);
    }


/******************************************************************************
*
* sysEpicIntConnect - connect an interrupt handler to the system vector table
*
* This function connects an interrupt handler to the system vector table.
*
* RETURNS: OK/ERROR.
*/

LOCAL STATUS sysEpicIntConnect
    (
    VOIDFUNCPTR *      vector,         /* interrupt vector to attach */
    VOIDFUNCPTR        routine,        /* routine to be called */
    int                parameter       /* parameter to be passed to routine */
    )
    {
    INT_HANDLER_DESC * newHandler;
    INT_HANDLER_DESC * currHandler;
    LOCAL_INT_DATA     connect;
    BOOL		sharing = FALSE;

    /* validate the vector */

    if (((int)vector < 0) || ((int)vector > (SYSTEM_INTERRUPT_TABLE_SIZE - 1)))
        return (ERROR);
 
    /* create a new interrupt handler */

    if ((newHandler = (INT_HANDLER_DESC *)calloc (1, sizeof (INT_HANDLER_DESC)))
	 == NULL)
        return (ERROR);
 
    /* initialize the new handler */

    newHandler->vec  = routine;
    newHandler->arg  = parameter;
    newHandler->next = NULL;

    /* install the handler in the system interrupt table */

    if (sysIntTbl[(int)vector] == NULL)
        {
        sysIntTbl[(int)vector] = newHandler; /* single int. handler case */
        }
    else
        {
        currHandler = sysIntTbl[(int)vector]; /* multiple int. handler case */
        while (currHandler->next != NULL)
            {
            currHandler = currHandler->next;
            }
        currHandler->next = newHandler;
        sharing = TRUE;
        }

    /* 
     * if the connect is for an EPIC interrupt, 
     * then store the vector into the appropriate EPIC vector register
     */

	if (!sharing)
	{
    connect.regAddr = getEpicVecAddr((int)vector);

    if (connect.regAddr > 0)
        {
        /* read the vector register */

        connect.regVal = sysPciInLong((UINT32)(connect.regAddr));

        /* store the interrupt vector number */

        connect.regVal |= (int)vector;

        /* write the contents of the vector register back */

        sysPciOutLong((UINT32)(connect.regAddr), connect.regVal);
        }
       	else
       	{
       		return ERROR;	
       	}
	}
    return (OK);
    }


/******************************************************************************
*
* sysEpicIntEnable - enable an Epic interrupt level
*
* This routine enables a specified Epic interrupt level.
*
* RETURNS: OK or ERROR if interrupt level not supported
*/

LOCAL int sysEpicIntEnable
    (

⌨️ 快捷键说明

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