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

📄 at91intrctl.c

📁 ARM7开发板 AT91EB01 BSP源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* at91IntrCtl.c - AT91 interrupt controller driver */

/* Copyright 1999 ARM Limited */

/*
modification history
--------------------
01b,27aug99,jpd  add use of Protect Mode and Spurious Vector; doc'n updated.
01a,29jun99,jpd  created.
*/



#include "vxWorks.h"
#include "config.h"
#include "intLib.h"

IMPORT int ffsLsb (UINT32);


/* Defines from config.h, or <bsp>.h */

#if !defined (AT91_INT_CSR_PEND) || !defined (AT91_INT_CSR_ENB) || \
    !defined (AT91_INT_NUM_LEVELS) || !defined (AT91_INT_CSR_DIS)
#   error missing AT91 interrupt definitions
#endif

#define AT91_INT_VEC_BASE	(0x0)


/* hardware access methods */

#ifndef AT91_INT_REG_READ
#define AT91_INT_REG_READ(reg,result) \
	((result) = *(volatile UINT32 *)(reg))
#endif /*AT91_INT_REG_READ*/

#ifndef AT91_INT_REG_WRITE
#define AT91_INT_REG_WRITE(reg,data) \
	(*((volatile UINT32 *)(reg)) = (data))
#endif /*AT91_INT_REG_WRITE*/


/* Convert level number to vector number */

#ifndef AT91_INT_LVL_VEC_MAP
#define AT91_INT_LVL_VEC_MAP(level, vector) \
	((vector) = ((level) + AT91_INT_VEC_BASE))
#endif /* AT91_INT_LVL_VEC_MAP */


#ifndef	AT91_INT_SOFT_PRIORITY_MAP
/* Convert pending register value, to a level number */

#ifndef AT91_INT_PEND_LVL_MAP
#define AT91_INT_PEND_LVL_MAP(pendReg, level) \
	((level) = (pendReg))
#endif /* AT91_INT_PEND_LVL_MAP */
#endif /* AT91_INT_SOFT_PRIORITY_MAP */


/* driver constants */

#define AT91_INT_ALL_ENABLED	(AT91_INT_NUM_LEVELS)
#define AT91_INT_ALL_DISABLED	0


/* Local data */

/* Current interrupt level setting (at91IntLvlChg). */

LOCAL UINT32 at91IntLvlCurrent = AT91_INT_ALL_DISABLED; /* all levels disabled*/

/*
 * A mask word.  Bits are set in this word when a specific level
 * is enabled.  It is used to mask off individual levels that have
 * not been explicitly enabled.
 */

LOCAL UINT32 at91IntLvlEnabled;


#ifdef AT91_INT_SOFT_PRIORITY_MAP
/*
 * Controller masks: for each interrupt level, this provides a mask for
 * the controller (see IntLvlChg).
 * Mask is 32 bits * (levels + 1)
 */

LOCAL UINT32 at91IntLvlMask[(1 + AT91_INT_NUM_LEVELS) * sizeof(UINT32)];


/*
 * Map of interrupt bit number to level: if bit n is set, at91IntLvlMap[n]
 * is the interrupt level to change to such that interrupt n and all lower
 * priority ones are disabled.
 */

LOCAL int at91IntLvlMap[AT91_INT_NUM_LEVELS * sizeof(int)];
#endif /* AT91_INT_SOFT_PRIORITY_MAP */


/* forward declarations */

STATUS	at91IntLvlVecChk (int*, int*);
STATUS  at91IntLvlVecAck (int, int);
int	at91IntLvlChg (int);
STATUS	at91IntLvlEnable (int);
STATUS	at91IntLvlDisable (int);

/*******************************************************************************
*
* at91IntDevInit - 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 architecture level routines, it
* should install the pointer to the wrapper routine after calling this
* routine.
*
* By default, the driver is compiled to implement a software-
* controlled, BSP-configurable interrupt priority scheme by #defining
* AT91_INT_SOFT_PRIORITY_MAP.  The order of interrupt level priority is
* undefined at the architecture level: when using software priorities in
* this driver, level 0 is highest and and indicates that all levels are
* disabled; level AT91_INT_NUM_LEVELS is the lowest and indicates that
* all levels are enabled.
*
* Alternatively, if required, this driver can be configured to
* implement a least-significant bit first interrupt priority scheme by
* undefining the symbol AT91_INT_SOFT_PRIORITY_MAP (this is then
* compatible with earlier versions of the AMBA interrupt driver).  The
* driver then requires a definition of at91IntLvlMask[].
*
* If compiled to implement software configurable interrupt
* priorities, the hardware priority scheme is currently unused by this
* driver.  For this model, before this routine is called, the BSP
* should define an array of int called at91IntLvlPriMap[], each element of
* which is a bit number to be polled.  The list should be terminated with
* an entry containing -1.  This list is used in the interrupt handler to
* check bits in the requested order and is also used to generate a map of
* interrupt source to new interrupt level such that whilst servicing an
* interrupt, all interrupts defined by the BSP to be of lower priority
* than that interrupt are disabled.  Interrupt sources not in the list
* are serviced after all others in least-significant bit first priority.
*
* Note that in this priority system, intLevelSet(n) does not necessarily
* disable interrupt bit n and all lower-priority ones but uses
* at91IntLvlPriMap to determine which interrupts should be masked e.g.
* if at91IntLvlPriMap[] contains { 9, 4, 8, 5, -1 }, intLevelSet(0)
* disables all interrupt bits; intLevelSet(1) enables interrupt bit 9 but
* disables interrupts 4, 8, 5 and all others not listed; intLevelSet(3)
* enables interrupt bits 9, 4 and 8 but disables all others.  This
* enabling of interrupts only occurs if the interrupt has been explicitly
* enabled via a call to at91IntLvlEnable().
*
* If the list is empty (contains just a terminator) or at91IntLvlPriMap
* is declared as an int pointer of value 0 (this is more efficient),
* interrupts are handled as least-significant bit is highest priority.
*
* If the symbol AT91_INT_USE_PROTECT_MODE is defined, then the Protect
* mode feature of the AT91 is used: the appropriate bit is set in the
* Special Functions register, and the Interrupt Vector register is
* written to when appropriate, allowing the Interrupt Vector register to
* be read by a debugger.
*
* The Spurious Vector feature is utilised by this driver and spurious
* interrupts will be detected, and reported to the architecture code
* calling this driver.
*
* The BSP will call this routine to initialize this driver in
* sysHwInit2(), after initializing the main interrupt library, usually
* intLibInit().  This routine sets up the interrupt controller device by
* masking off all individual interrupt sources and then setting the
* interrupt level to enable all interrupts.
*
* The return value ERROR indicates that the contents of
* at91IntLvlPriMap (if used) were invalid.
*
* INTERNAL
* The at91IntLvlPriMap list is a list of ints rather than bytes because
* it causes the current compiler to generate faster code.
*
* RETURNS: OK or ERROR if at91IntLvlPriMap invalid.
*/

int at91IntDevInit (void)
    {
#ifdef AT91_INT_SOFT_PRIORITY_MAP
    int i, j;
    int level;
    UINT32 bit;

    /* if priorities are supplied, validate the supplied list */

    if (at91IntLvlPriMap != 0)
	{
	/* first check the list is terminated (VecChk requires this) */

	for (i = 0; i < AT91_INT_NUM_LEVELS; ++i)
	    if (at91IntLvlPriMap[i] == -1)
		break;

	if (!(i < AT91_INT_NUM_LEVELS))
	    return ERROR;	/* no terminator */


	/* now check that all are in range and that there are no duplicates */

	for (i = 0; at91IntLvlPriMap[i] != -1; ++i)
	    if (at91IntLvlPriMap[i] < 0 ||
		at91IntLvlPriMap[i] >= AT91_INT_NUM_LEVELS)
		{
		return ERROR;	/* out of range */
		}
	    else
		for (j = i + 1; at91IntLvlPriMap[j] != -1; ++j)
		    if (at91IntLvlPriMap[j] == at91IntLvlPriMap[i])
			{
			return ERROR;	/* duplicate */
			}
	}


    /*
     * Now initialise the mask array.
     * For each level (in ascending order), the mask is the mask of the
     * previous level with the bit for the current level set to enable it.
     */

    at91IntLvlMask[0] = 0;	/* mask for level 0 = all disabled */


    /* do the levels for which priority has been specified */

    level = 1;
    if (at91IntLvlPriMap != 0)
	{
	for ( ; level <= AT91_INT_NUM_LEVELS &&
		(i = at91IntLvlPriMap[level - 1], i >= 0); ++level)
	    {
	    /* copy previous level's mask to this one's */

	    at91IntLvlMask[level] = at91IntLvlMask[level - 1];


	    /* OR in the bit indicated by the next entry in PriMap[] */

	    at91IntLvlMask[level] |= 1 << i;

	    /*
	     * set index in level map: to disable this interrupt and all
	     * lower-priority ones, select the level one less than this
	     */

	    at91IntLvlMap[i] = level - 1;
	    }
	}


    /* do the rest of the levels */

    i = 0;		/* lowest-numbered interrupt bit */

    for ( ; level <= AT91_INT_NUM_LEVELS; ++level)
	{
	/* copy previous level's mask to this one's */

	at91IntLvlMask[level] = at91IntLvlMask[level - 1];


	/* try to find a bit that has not yet been set */

	for ( ; ; ++i)
	    {
	    bit = 1 << i;

	    if ((at91IntLvlMask[level] & bit) == 0)
		{
		/* this bit not set so put it in the mask */

		at91IntLvlMask[level] |= bit;

		/*
		 * set index in level map: to disable this interrupt and all
		 * lower-priority ones, select the level one less than this
		 */

		at91IntLvlMap[i] = level - 1;
		break;
		}
	    }
	}
#endif /* AT91_INT_SOFT_PRIORITY_MAP */


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

    sysIntLvlVecChkRtn	= at91IntLvlVecChk;
    sysIntLvlVecAckRtn	= at91IntLvlVecAck;
    sysIntLvlChgRtn	= at91IntLvlChg;
    sysIntLvlEnableRtn	= at91IntLvlEnable;
    sysIntLvlDisableRtn	= at91IntLvlDisable;

    at91IntLvlEnabled = 0; 	/* all sources disabled */

    /*
     * Inititalise all source vector registers to zero, which is the
     * same value as the value we will put into the spurious vector
     * register.  Reading zero back from the vector register will then
     * indicate either a spurious interrupt, or an interrupt that was
     * never configured.
     */

    for (i = 0; i < AT91_INT_NUM_LEVELS; ++i)
	AT91_INT_REG_WRITE ((AT91_INT_CSR_SVEC + (level * 4)), 0);

    AT91_INT_REG_WRITE (AT91_INT_CSR_SPU, 0);

#ifdef AT91_INT_USE_PROTECT_MODE
    /* Enable write access and enable protect mode in Special Function Reg */

    AT91_INT_REG_WRITE (AT91_SF_PMR, AT91_PMR_KEY | AT91_PMR_AIC);
#endif /* AT91_INT_USE_PROTECT_MODE */

    at91IntLvlChg (AT91_INT_ALL_ENABLED); /* enable all levels */

    return OK;
    }

/*******************************************************************************
*
* at91IntLvlConfigure - configure polarity and type of interrupt
*
* This routine configures the polarity and type (edge or level) or an

⌨️ 快捷键说明

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