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

📄 at91intrctl.c

📁 ARM7开发板 AT91EB01 BSP源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
* interrupt.  It should be called after initialisation of the driver and
* must be called before enabling the level.
*
* The return value ERROR indicates that the parameters were invalid.
*
* RETURNS: OK or ERROR if parameters invalid.
*/

STATUS at91IntLvlConfigure
    (
    int level,		/* level to configure */
    int features	/* edge/level/positive/negative */
    )
    {
    int bits;

    if (level < 0 ||
	level >= AT91_INT_NUM_LEVELS)
	return ERROR;

    /*
     * Configure polarity:
     *
     * Bits to be written to configuration register are:
     * 00 = level, active low
     * 01 = edge,  negative edge
     * 10 = level, active high
     * 11 = edge,  positive edge
     */

    bits = features << 5;	/* set priority zero */

    AT91_INT_REG_WRITE ((AT91_INT_CSR_MODE + (level * 4)), bits);


    /* put level number into the source vector reg to read back on interrupt*/

    AT91_INT_REG_WRITE ((AT91_INT_CSR_SVEC + (level * 4)), level);

    return OK;
    }

/*******************************************************************************
*
* at91IntLvlVecChk - 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.
*
* This routine must be called with CPU interrupts disabled.
*
* 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 */
    )
    {
    int newLevel;
#ifdef AT91_INT_SOFT_PRIORITY_MAP
    UINT32 *priPtr;
    int bitNum;
    UINT32 ipr;
    UINT32 imr;
    UINT32 dummy;
#endif


#ifdef AT91_INT_SOFT_PRIORITY_MAP
    /*
     * Read pending interrupt register before reading vector register,
     * which we must do anyway, as early as possible.
     */

    AT91_INT_REG_READ (AT91_INT_CSR_PEND, ipr);
    AT91_INT_REG_READ (AT91_INT_CSR_VECT, dummy);

#ifdef AT91_INT_USE_PROTECT_MODE
    AT91_INT_REG_WRITE (AT91_INT_CSR_VECT, dummy);
#endif /* AT91_INT_USE_PROTECT_MODE */

    /* read enabled interrupts and mask pending interrupts with that */

    AT91_INT_REG_READ (AT91_INT_CSR_IMR, imr);
    ipr &= imr;

    /* If no interrupt is pending, return ERROR */

    if (ipr == 0)
#else /* AT91_INT_SOFT_PRIORITY_MAP */
    AT91_INT_REG_READ (AT91_INT_CSR_VECT, newLevel);

#ifdef AT91_INT_USE_PROTECT_MODE
    AT91_INT_REG_WRITE (AT91_INT_CSR_VECT, newLevel);
#endif /* AT91_INT_USE_PROTECT_MODE */

    /* If no interrupt is pending, return ERROR */

    if (newLevel == 0)
#endif /* AT91_INT_SOFT_PRIORITY_MAP */
    	{
	/*
	 * If there is no interrupt pending, then the architecture code
	 * will not call the intLvlVecAck routine, leading to an
	 * imbalance in the interrupt controller hardware stack.  So, we
	 * need to issue the End Of Interrupt command here.  Depending
	 * upon how we have been called by the architecture code, this
	 * may or may not indicate that there has been a spurious
	 * interrupt.
	 */

	AT91_INT_REG_WRITE (AT91_INT_CSR_EOIC, 0);    /* issue End-of-Int cmd */
	return ERROR;
	}


#ifdef AT91_INT_SOFT_PRIORITY_MAP
    if (priPtr = at91IntLvlPriMap, priPtr == 0)
	bitNum = -1;
    else
	{
	/* service interrupts according to priority specifed in map */

	while (bitNum = *priPtr++, bitNum != -1)
	    {
	    /* bitNum = interrupt bit from priority map */

	    if (ipr & (1 << bitNum))
		{
		break;
		}
	    }
	}


    /*
     * if priority scan didn't find anything, look for any bit set,
     * starting with the lowest-numbered bit
     */

    if (bitNum == -1)
	bitNum = ffsLsb (ipr) - 1; /* ffsLsb returns numbers from 1, not 0 */


    /* if no interrupt is pending, return ERROR */

    if (bitNum == -1)
	return ERROR;


    /* map the interrupting device to an interrupt level number */

    newLevel = at91IntLvlMap[bitNum];
#else /* ifdef AT91_INT_SOFT_PRIORITY_MAP */
    if (newLevel > AT91_INT_NUM_LEVELS)
    	return ERROR;

    /* map the interrupting device to an interrupt level number */

    AT91_INT_PEND_LVL_MAP (newLevel, newLevel);
#endif /* ifdef AT91_INT_SOFT_PRIORITY_MAP */


    /* change to new interrupt level, returning previous level to caller */

    *pLevel = at91IntLvlChg (newLevel);


    /* fetch, or compute the interrupt vector number */

#ifdef AT91_INT_SOFT_PRIORITY_MAP
    AT91_INT_LVL_VEC_MAP (bitNum, *pVector);
#else
    AT91_INT_LVL_VEC_MAP (newLevel, *pVector);
#endif

    return OK;
    }

/*******************************************************************************
*
* at91IntLvlVecAck - acknowledge the current interrupt
*
* Acknowledge the current interrupt cycle.  The level and vector values are
* those generated during the at91IntLvlVecChk() routine for this interrupt
* cycle.  The basic action is to reset the current interrupt and return
* the interrupt level to its previous setting.
*
* 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 */
    )
    {
    /* acknowledge end of interrupt cycle */

    AT91_INT_REG_WRITE (AT91_INT_CSR_EOIC, 0);	/* Write of any value will do */

    /* restore the previous interrupt level */

    at91IntLvlChg (level);

    return OK;
    }

/*******************************************************************************
*
* at91IntLvlChg - change the interrupt level value
*
* This routine implements the overall interrupt setting.  All levels
* up to and including the specifed level are disabled.  All levels above
* the specified level will be enabled, but only if they were specifically
* enabled by the at91IntLvlEnable() routine.
*
* The specific priority level AT91_INT_NUM_LEVELS is valid and represents
* all levels enabled.
*
* RETURNS: Previous interrupt level.
*/

int  at91IntLvlChg
    (
    int level	/* new interrupt level */
    )
    {
    int oldLevel;

    oldLevel = at91IntLvlCurrent;

    if (level >= 0 &&
        level <= AT91_INT_NUM_LEVELS)
	{
	/* change current interrupt level */

	at91IntLvlCurrent = level;
	}

    /* Switch off all interrupts */

    AT91_INT_REG_WRITE (AT91_INT_CSR_DIS, -1);

    /* Activate the enabled interrupts */

    AT91_INT_REG_WRITE (AT91_INT_CSR_ENB,
		(at91IntLvlMask[at91IntLvlCurrent] & at91IntLvlEnabled));

    return oldLevel;
    }

/*******************************************************************************
*
* at91IntLvlEnable - 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 to
* enable interrupts of this priority (as configured by at91IntLvlPriMap,
* if appropriate).  When not enabled, the interrupt is blocked
* regardless of the overall interrupt level setting.
*
* The interrupt level must have been configured by a call to
* at91IntLvlConfigure() before it is enabled by a call to this routine.
*
* RETURNS: OK or ERROR if the specified level cannot be enabled.
*/

STATUS  at91IntLvlEnable
    (
    int level  /* level to be enabled */
    )
    {
    int key;

    if (level < 0 ||
	level >= AT91_INT_NUM_LEVELS)
	return ERROR;


    /* set bit in enable mask */

    key = intLock ();
    at91IntLvlEnabled |= (1 << level);
    intUnlock (key);

    at91IntLvlChg (-1);	/* reset current mask */

    return OK;
    }

/*******************************************************************************
*
* at91IntLvlDisable - 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 to enable interrupts of this priority (as configured by
* at91IntLvlPriMap, if appropriate).
*
* RETURNS: OK or ERROR, if the specified interrupt level cannot be disabled.
*/

STATUS  at91IntLvlDisable
    (
    int level  /* level to be disabled */
    )
    {
    int key;

    if (level < 0 ||
	level >= AT91_INT_NUM_LEVELS)
	return ERROR;


    /* clear bit in enable mask */

    key = intLock ();
    at91IntLvlEnabled &= ~(1 << level);
    intUnlock (key);

    at91IntLvlChg (-1);	/* reset current mask */

    return OK;
    }

⌨️ 快捷键说明

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