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

📄 at91intrctl.c

📁 vwworks 在 at91rm9200上的bsp配置
💻 C
📖 第 1 页 / 共 2 页
字号:
/* at91IntrCtl.c - AT91RM9200 interrupt controller driver */

/* Copyright 1999 ARM Limited */
/* Copyright 2002-2004 Wind River Systems, Inc. */

/*
modification history
--------------------
01a,13sep04,pdr  based on release 01c for AT91RM40400.
*/

/*
This module implements the AT91 interrupt controller driver.

The AT91 interrupt controller is an 8-level priority, individually
maskable vectored interrupt controller, described in full in the
AT91RM9200 Data Sheet.  The interrupt controller has status and request
registers, separate enable and disable registers and supports edge- and
level-sensitive interrupts.  This library provides the routines to
manage interrupts multiplexed by the AT91 interrupt controller.

The hardware supports controlling of the priority of interrupts in
hardware, and also supports hardware interrupt vectoring.  The latter
feature cannot be supported by this driver, as the interrupts must, in
the first case be handled by the (hardware-independent) architecture
code, before being handled by this driver.  

The AT91 interrupt controller has a number of registers.  Those used by
this driver are described below under the symbolic names used herein.

AT91_INT_CSR_MODE (read/write): these are the source mode registers.  They
configure the hardware priority (if used, zero otherwise) and the type
of interrupt (level, edge, high, low etc).

AT91_INT_CSR_SVEC (read/write): these are the source vector registers.
If hardware vectoring were used, the address of the interrupt handling
routine for each interrupt source would be written to the register for
each source.  This driver puts the interrupt level into the source
vector register for each source so that when the interrupt vector
register is read when an interrupt occurs, we have the level.

AT91_INT_CSR_ENB (write): this is the "Enable Set" register.  When
this register is written, each data bit that is set (1) causes the
corresponding interrupt to be enabled.  Bits that are clear (0) have no
effect.

AT91_INT_CSR_DIS (write): this is the "Enable Clear" register which has
the opposite effect.  When this register is written, each data bit that
is set (1) causes the corresponding interrupt to be disabled.  Bits
that are clear (0) have no effect.

AT91_INT_CSR_PEND (read): this is the "Interrupt Request" register.
When this register is read, each data bit that is set (1) indicates an
interrupt source that is active but not necessarily enabled i.e. can
interrupt the processor.

AT91_INT_CSR_IMR (read): this is the interrupt mask register.  Each data
bit that is set (1) indicates an interrupt source that is enabled.  When
the contents of AT91_INT_CSR_PEND are 'and'ed together with the
contents of this register, the value obtained shows the interrupt
sources that are active and enabled.

AT91_INT_CSR_VECT (read): this contains the interrupt "vector": a value
that was placed into the hardware when configuring a particular
interrupt source.  If software priority control is used, then the value
read is discarded, but otherwise is used as the current interrupt
level.  When this register is read, the current interrupt level (in
hardware terms) is placed on a hardware stack, NIRQ is deasserted, the
interrupt is cleared (if edge-triggered) and sets the current interrupt
level to be the highest priority pending source.

AT91_INT_CSR_EOIC (write): any value written to this register performs
an End-of-Interrupt command.  This unstacks the current interrupt level
(if any) from the hardware stack, and allows any pending interrupts to
be serviced.

The number of interrupts supported by the device i.e. the number of
bits in the AT91_INT_CSR_PEND register, is specified by
AT91_INT_NUM_LEVELS.

We assume that config.h or <bsp>.h has defined the addresses of the
controller chips registers: AT91_INT_CSR_ENB, AT91_INT_CSR_DIS,
AT91_INT_CSR_VECT, AT91_INT_CSR_IMR and AT91_INT_CSR_PEND and also the
driver constant AT91_INT_NUM_LEVELS.

This driver assumes that the chip is memory-mapped and does direct
memory accesses to the registers which are assumed to be 32 bits wide.
If a different access method is needed, the BSP can redefine the macros
AT91_INT_REG_READ(addr,result) and AT91_INT_REG_WRITE(addr,data).

This driver assumes that interrupt vector numbers (in VxWorks terms)
are calculated and not the result of a special cycle on the bus.
Vector numbers are generated by adding the current interrupt level
number to AT91_INT_VEC_BASE to generate a vector number which the
architecture level will use to invoke the proper handling routine.  If
a different mapping scheme, or a special hardware routine is needed,
then the BSP should redefine the macro AT91_INT_LVL_VEC_MAP(level,vector)
to override the version defined in this file.

This driver was designed to support a single instance of a real
device.  At some point it should be upgraded to operate on an object
model and to support any number of real devices.

All of the functions in this library are global.  This allows them to
be used by the BSP if it is necessary to create wrapper routines or to
incorporate several drivers together as one.
*/

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

#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 */


/* 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 */

/* Local data */

/* 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.
*
* 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 hardware supports controlling of the priority of interrupts in
* hardware, and also supports hardware interrupt vectoring.  The latter
* feature cannot be supported by this driver, as the interrupts must, in
* the first case be handled by the (hardware-independent) architecture
* code, before being handled by this driver.  The interrupt priorities are
* defined in csb337.h.  The priority level can be between 0 (lowest)
* and 7 (highest).
*
* 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.
*
* RETURNS: OK
*/

int at91IntDevInit
    (
    void
    )
    {
    int i;
    
    /* install the driver routines in the architecture hooks */

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

    /*
     * Inititalise all source vector registers, 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 + (i * 4)), i);
        }

    AT91_INT_REG_WRITE ((AT91_INT_CSR_MODE + (INT_LVL_SERIAL_0 * 4)), INT_PRI_SERIAL_0);
    AT91_INT_REG_WRITE ((AT91_INT_CSR_MODE + (INT_LVL_SERIAL_1 * 4)), INT_PRI_SERIAL_1);
    AT91_INT_REG_WRITE ((AT91_INT_CSR_MODE + (INT_LVL_TIMER_0 * 4)), INT_PRI_TIMER_0);
    AT91_INT_REG_WRITE ((AT91_INT_CSR_MODE + (INT_LVL_TIMER_1 * 4)), INT_PRI_TIMER_1);
    AT91_INT_REG_WRITE ((AT91_INT_CSR_MODE + (INT_LVL_TIMER_2 * 4)), INT_PRI_TIMER_2);
    AT91_INT_REG_WRITE ((AT91_INT_CSR_MODE + (INT_LVL_ETH * 4)), INT_PRI_ETH);
    
    /* TODO: add here the other interrupt if BSP is extended for more peripherals */
    
    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 */

⌨️ 快捷键说明

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