www.pudn.com > at91rm9200bsp.rar > at91IntrCtl.c


/* AT91IntrCtl.c - AT91RM9200 AIC driver */

/*
modification history
--------------------
2004/10/25 this file is modified form VxWorks demo bsp integrator920t
*/

/*

DESCRIPTION

*/

#include "intLib.h"

/* forward declarations */

STATUS	AT91IntLvlVecChk (int*, int*);
/*STATUS  AT91IntLvlVecAck (int, int);*/

STATUS	AT91IntLvlEnable (int);
STATUS	AT91IntLvlDisable (int);

/*******************************************************************************
*
* sndsIntDevInit - initialize the interrupt controller
*
* This routine will initialize the interrupt controller device, disabling all
* interrupt sources.  It will also connect the device driver specific routines
* into the architecture level hooks.  If the BSP needs to create a wrapper
* routine around any of the arhitecture level routines, it should install the
* pointer to the wrapper routine after calling this routine.
*
* RETURNS: N/A
*/

void At91IntDevInit (void)
{
	int i;
	AIC_S* paic = (AIC_S*)AIC_BASE_ADDR;

	/* dummy read result nIRQ, nFIQ to deassert state */
	i = paic ->AIC_IVR;
	i = paic ->AIC_FVR;
	
	/*
	 *	setup the mode and vector for each interrupt
	 *	because we can not use the AIC automatic vector branch, we set
	 *	each vector to it's interrupt number, and we are easy to get interrupt number
	 *	when sndsIntLvlVecChk called.
	 *	set each interrupt mode to priority 0( lowest level ), edge trig mode
	 */
	for( i = 0; iAIC_SMR[i] = ( 7<<(AIC_SMR_PRIO_BIT) );
		paic ->AIC_SVR[i] = (AT91_REG)(i|0x20000000);
	}
	
	/* SUPRISE  INTERRUPT VECTOR, WE SET TO A LARGE VALUE */
	paic ->AIC_SPU = (AIC_INT_NUM_LEVELS+10)|0x20000000;
	
	/* CURRENT WE  USE PROTECT MODE, if used, IVR must be writed just after it readed */
	paic ->AIC_DCR = 1;
	
	/* faster forceing, we do not use any interrupt routed to FIRQ */
	paic ->AIC_FFER = 0;
	paic ->AIC_FFDR = 0xFFFFFFFE; /* leave last bit to 0, It's FIQ */
	
	
	for( i = 0; i<8; i++ )
		paic ->AIC_EOICR = 0;
	
	paic ->AIC_ICCR = 0xFFFFFFFF;

	/* install the driver routines in the architecture hooks */

	
    sysIntLvlVecChkRtn	= AT91IntLvlVecChk;
    sysIntLvlEnableRtn	= AT91IntLvlEnable;
    sysIntLvlDisableRtn	= AT91IntLvlDisable;
/* 
    sysIntLvlVecAckRtn	= AT91IntLvlVecAck; 
*/ 
	
}

/*******************************************************************************
*
* sndsIntLvlVecChk - check for and return any pending interrupts
*
* This routine interrogates the hardware to determine the highest priority
* interrupt pending.  It returns the vector associated with that interrupt, and
* also the interrupt priority level prior to the interrupt (not the
* level of the interrupt).  The current interrupt priority level is then
* raised to the level of the current interrupt so that only higher priority
* interrupts will be accepted until this interrupt is finished.
*
* The return value ERROR indicates that no pending interrupt was found and
* that the level and vector values were not returned.
*
* RETURNS: OK or ERROR if no interrupt is pending.
*/

STATUS  AT91IntLvlVecChk
    (
    int* pLevel,  /* ptr to receive old interrupt level */
    int* pVector  /* ptr to receive current interrupt vector */
    )
{

	AIC_S* paic = (AIC_S*)AIC_BASE_ADDR;
	UINT32 newLevel;
	newLevel = paic ->AIC_IVR;
	paic ->AIC_IVR = newLevel;
	newLevel &= 0xFF;
	paic ->AIC_EOICR = 0xFFFFFFFF;

	if( newLevel >= AIC_INT_NUM_LEVELS )
		return ERROR;
	newLevel &= (AIC_INT_NUM_LEVELS-1);
	*pVector = newLevel;
	return OK;
}

/*******************************************************************************
*
* sndsIntLvlEnable - enable a single interrupt level
*
* Enable a specific interrupt level.  The enabled level will be allowed to
* generate an interrupt, when the overall interrupt level is set below the
* specified level.  Without being enabled, the interrupt is blocked regardless
* of the overall interrupt level setting.
*
* RETURNS: OK or ERROR if the specified level cannot be enabled.
*/

STATUS  AT91IntLvlEnable
    (
    int level  /* level to be enabled */
    )
{
    if ( ((UINT32)level) >= AIC_INT_NUM_LEVELS )
		return ERROR;
	((AIC_S*)AIC_BASE_ADDR)->AIC_IECR = (1 << level);

	return OK;
}

/*******************************************************************************
*
* sndsIntLvlDisable - disable a single interrupt level
*
* Disable a specific interrupt level.  The disabled level is prevented
* from generating an interrupt even if the overall interrupt level is set
* below the specified level.
*
* RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.
*/

STATUS  AT91IntLvlDisable
    (
    int level  /* level to be disabled */
    )
{
    if ( ((UINT32)level) >= AIC_INT_NUM_LEVELS )
		return ERROR;
	((AIC_S*)AIC_BASE_ADDR)->AIC_IDCR = (1 << level);
}


/*******************************************************************************
*
* IntLvlVecAck - acknowledge the current interrupt
*
* Acknowledge the current interrupt cycle.  The level and vector values are
* those generated during the IntLvlVecChk() routine for this interrupt
* cycle.  The basic action is to reset the current interrupt and return
* the interrupt level to its previous setting.  Note that the AMBA interrupt
* controller does not need an acknowledge cycle.
*
* RETURNS: OK or ERROR if a hardware fault is detected.
* ARGSUSED
*/

/* 
STATUS  AT91IntLvlVecAck 
    ( 
    int level,	/ * old interrupt level to be restored * / 
    int vector	/ * current interrupt vector, if needed * / 
    ) 
{ 
 
	/ *((AIC_S*)AIC_BASE_ADDR) ->AIC_EOICR = 0xFFFFFFFF;* /	/ * ack interrupt, int LEVEL stack adjuested * / 
    return OK; 
} 
*/