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

📄 isr.c

📁 IAR 开发环境的Cirrus Logic的例程
💻 C
字号:
//****************************************************************************
//
// ISR.C - Routines to handle the IRQ and FIQ interrupts
//
// Copyright (c) 1998-1999 Cirrus Logic, Inc.
//
//****************************************************************************
#include "ep7312.h"
#include "lib7312.h"

//****************************************************************************
//
// The following four functions are Angel SWIs which are used to get and set
// the address of the handler for the IRQ and FIQ events.
//
//****************************************************************************
#ifdef __IAR_SYSTEMS_ICC__
#pragma swi_number=0x123456
__swi __arm PFNISR Angel_GetIRQ(int iSWINum);
#pragma swi_number=0x123456
__swi __arm long Angel_SetIRQ(int iSWINum, PFNISR pfnIsr);
#pragma swi_number=0x123456
__swi __arm PFNISR Angel_GetFIQ(int iSWINum);
#pragma swi_number=0x123456
__swi __arm long Angel_SetFIQ(int iSWINum, PFNISR pfnIsr);
#else
__swi(0x123456) PFNISR Angel_GetIRQ(int iSWINum);
__swi(0x123456) long Angel_SetIRQ(int iSWINum, PFNISR pfnIsr);
__swi(0x123456) PFNISR Angel_GetFIQ(int iSWINum);
__swi(0x123456) long Angel_SetFIQ(int iSWINum, PFNISR pfnIsr);
#endif

//****************************************************************************
//
// IRQShell is the assembly language IRQ handler which takes care of saving
// the registers which can be destroyed by C code according to the APCS.
//
//****************************************************************************
extern void IRQShell(void);

//****************************************************************************
//
// FIQShell is the assembly language FIQ handler which takes care of saving
// the registers which can be destroyed by C code according to the APCS.
//
//****************************************************************************
extern void FIQShell(void);

//****************************************************************************
//
// The following variables are used by the IRQ handler.  They contain a
// pointer to the original IRQ handler, the number of times the IRQ interrupt
// has been hooked (and therefore the number of times it must be unhooked
// before it is actually removed from the system), and pointers to the
// handlers for the various interrupt sources.
//
//****************************************************************************
PFNISR pfnOldIRQ = 0;
static int iIRQRefCount = 0;
static PFNISR pfnCodecHandler = 0;
static PFNISR pfnADCHandler = 0;
static PFNISR pfnUART1Handler = 0;
static PFNISR pfnUART2Handler = 0;
static PFNISR pfnKbdHandler = 0;
static PFNISR pfnSSI2Handler = 0;
static PFNISR pfnParallelHandler = 0;

//****************************************************************************
//
// The following variables are used by the FIQ handler.  They contain a
// pointer to the original FIQ handler, the number of times the FIQ interrupt
// has been hooked (and therefore the number of times it must be unhooked
// before it is actually removed from the system), and pointers to the
// handlers for the various interrupt sources.
//
//****************************************************************************
PFNISR pfnOldFIQ = 0;
static int iFIQRefCount = 0;
static PFNISR pfnDAIHandler = 0;

//****************************************************************************
//
// IRQHandler is the routine which handles the actual IRQ interrupts.  It
// will call the specific handler for each interrupt source (if it has been
// registered) and will clear the interrupt source.
//
//****************************************************************************
void
IRQHandler(void)
{
    unsigned long * volatile pulPtr = (unsigned long *)HwBaseAddress;
    long lIntStatus, lData;

    //
    // Retrieve the value of the interrupt status register so that we can find
    // out why this interrupt was triggered.
    //
    lIntStatus = pulPtr[HwIntStatus >> 2] & pulPtr[HwIntMask >> 2];

    //
    // See if the codec triggered the interrupt.
    //
    if(lIntStatus & HwIrqCodec)
    {
        //
        // If there is a handler function for the codec interrupt, then call it
        // now.
        //
        if(pfnCodecHandler)
        {
            (*pfnCodecHandler)();
        }

        //
        // We've handled the codec interrupt, so issue a codec EOI.
        //
        pulPtr[HwCodecEOI >> 2] = 0;
    }

    //
    // See if the ADC triggered the interrupt.
    //
    if(lIntStatus & HwIrqSpi)
    {
        //
        // If there is a handler function for the ADC interrupt, then call it
        // now.
        //
        if(pfnADCHandler)
        {
            (*pfnADCHandler)();
        }

        //
        // Otherwise, read the data sample from the ADC to clear the interrupt.
        //
        else
        {
            lData = pulPtr[HwSpiData >> 2];
        }
    }

    //
    // See if UART1 triggered the interrupt.
    //
    if((lIntStatus & HwIrqUartRx) || (lIntStatus & HwIrqUartTx))
    {
        //
        // If there is a handler function for the UART1 interrupt, then call it
        // now.
        //
        if(pfnUART1Handler)
        {
            (*pfnUART1Handler)();
        }
    }

    //
    // See if the RTC triggered the interrupt.
    //
    if(lIntStatus & HwIrqRtcMatch)
    {
        //
        // We've handled the RTC interrupt, so issue a RTC EOI.
        //
        pulPtr[HwRtcMatchEOI >> 2] = 0;
    }

    //
    // See if the parallel port triggered the interrupt.
    //
    if(lIntStatus & HwIrqExt3)
    {
        //
        // If there is a handler function for the parallel interrupt, then call
        // it now.
        //
        if(pfnParallelHandler)
        {
            (*pfnParallelHandler)();
        }
    }

    //
    // Retrieve the value of the second interrupt status register.
    //
    lIntStatus = pulPtr[HwIntStatus2 >> 2] & pulPtr[HwIntMask2 >> 2];

    //
    // See if the keyboard triggered the interrupt.
    //
    if(lIntStatus & HwIrqKeyboard)
    {
        //
        // If there is a handler function for the keyboard interrupt, then call
        // it now.
        //
        if(pfnKbdHandler)
        {
            (*pfnKbdHandler)();
        }

        //
        // Clear the keyboard interrupt.
        //
        pulPtr[HwKeyboardEOI >> 2] = 0;
    }

    //
    // See if UART2 triggered the interrupt.
    //
    if((lIntStatus & HwIrqUartRx) || (lIntStatus & HwIrqUartTx))
    {
        //
        // If there is a handler function for the UART2 interrupt, then call it
        // now.
        //
        if(pfnUART2Handler)
        {
            (*pfnUART2Handler)();
        }
    }

    //
    // See if the SSI2 triggered the interrupt.
    //
    if((lIntStatus & HwIrqSSI2Rx) || (lIntStatus & HwIrqSSI2Tx))
    {
        //
        // If there is a handler function for the SSI2 interrupt, then call it
        // now.
        //
        if(pfnSSI2Handler)
        {
            (*pfnSSI2Handler)();
        }
    }
}

//****************************************************************************
//
// FIQHandler is the routine which handles the actual FIQ interrupts.  It
// will call the specific handler for each interrupt source (if it has been
// registered) and will clear the interrupt source.
//
//****************************************************************************
void
FIQHandler(void)
{
    unsigned long * volatile pulPtr = (unsigned long *)HwBaseAddress;
    long lIntStatus;

    //
    // Retrieve the value of the interrupt status register so that we can find
    // out why this interrupt was triggered.
    //
    lIntStatus = pulPtr[HwIntStatus3 >> 2] & pulPtr[HwIntMask3 >> 2];

    //
    // See if the DAI triggered the interrupt.
    //
    if(lIntStatus & HwFiqDAI)
    {
        //
        // If there is a handler function for the DAI interrupt, then call it
        // now.
        //
        if(pfnDAIHandler)
        {
            (*pfnDAIHandler)();
        }
    }
}

//****************************************************************************
//
// InterruptInstallIRQ will install the global IRQ handler.
//
//****************************************************************************
void
InterruptInstallIRQ(void)
{
    //
    // Do not install the IRQ handler if it has already been installed.
    //
    if(!pfnOldIRQ)
    {
        //
        // Get the address of the current IRQ handler from Angel.
        //
        pfnOldIRQ = Angel_GetIRQ(0xFD);

        //
        // Tell Angel to call our IRQ handler instead.  We will chain to the
        // original IRQ handler.
        //
        Angel_SetIRQ(0xFC, IRQShell);
    }

    //
    // Increment the reference count of the number of times we were requested
    // to install the IRQ handler.
    //
    iIRQRefCount++;
}

//****************************************************************************
//
// InterruptRemoveIRQ removes the global IRQ handler.
//
//****************************************************************************
void
InterruptRemoveIRQ(void)
{
    //
    // If we have installed our IRQ handler and the reference count is not
    // being decremented to zero, then remove our IRQ handler.
    //
    if(pfnOldIRQ && !(--iIRQRefCount))
    {
        //
        // Set the original IRQ handler as the IRQ handler, thereby removing
        // ourself from the chain.
        //
        Angel_SetIRQ(0xFC, pfnOldIRQ);

        //
        // Forget the address of the original IRQ handler.
        //
        pfnOldIRQ = 0;
    }
}

//****************************************************************************
//
// InterruptInstallFIQ will install the global FIQ handler.
//
//****************************************************************************
void
InterruptInstallFIQ(void)
{
    //
    // Do not install the FIQ handler if it has already been installed.
    //
    if(!pfnOldFIQ)
    {
        //
        // Get the address of the current FIQ handler from Angel.
        //
        pfnOldFIQ = Angel_GetFIQ(0xFF);

        //
        // Tell Angel to call our FIQ handler instead.  We will chain to the
        // original FIQ handler.
        //
        Angel_SetFIQ(0xFE, FIQShell);
    }

    //
    // Increment the reference count of the number of times we were requested
    // to install the FIQ handler.
    //
    iFIQRefCount++;
}

//****************************************************************************
//
// InterruptRemoveFIQ removes the global FIQ handler.
//
//****************************************************************************
void
InterruptRemoveFIQ(void)
{
    //
    // If we have installed our FIQ handler and the reference count is not
    // being decremented to zero, then remove our FIQ handler.
    //
    if(pfnOldFIQ && !(--iFIQRefCount))
    {
        //
        // Set the original FIQ handler as the FIQ handler, thereby removing
        // ourself from the chain.
        //
        Angel_SetFIQ(0xFE, pfnOldFIQ);

        //
        // Forget the address of the original FIQ handler.
        //
        pfnOldFIQ = 0;
    }
}

//****************************************************************************
//
// InterruptSetCodecHandler sets the address of the routine that handles the
// codec interrupt source.
//
//****************************************************************************
void
InterruptSetCodecHandler(PFNISR pfnCodec)
{
    //
    // Remember the address of the codec handler routine.
    //
    pfnCodecHandler = pfnCodec;
}

//****************************************************************************
//
// InterruptSetADCHandler sets the address of the routine that handles the
// ADC interrupt source.
//
//****************************************************************************
void
InterruptSetADCHandler(PFNISR pfnADC)
{
    //
    // Remember the address of the ADC handler routine.
    //
    pfnADCHandler = pfnADC;
}

//****************************************************************************
//
// InterruptSetDAIHandler sets the address of the routine that handles the
// DAI interrupt source.
//
//****************************************************************************
void
InterruptSetDAIHandler(PFNISR pfnDAI)
{
    //
    // Remember the address of the DAI handler routine.
    //
    pfnDAIHandler = pfnDAI;
}

//****************************************************************************
//
// InterruptSetUART1Handler sets the address of the routine that handles the
// UART1 interrupt source.
//
//****************************************************************************
void
InterruptSetUART1Handler(PFNISR pfnUART1)
{
    //
    // Remember the address of the UART1 handler routine.
    //
    pfnUART1Handler = pfnUART1;
}

//****************************************************************************
//
// InteruptSetUART2Handler sets the address of the routine that handles the
// UART2 interrupt source.
//
//****************************************************************************
void
InterruptSetUART2Handler(PFNISR pfnUART2)
{
    //
    // Remember the address of the UART2 handler routine.
    //
    pfnUART2Handler = pfnUART2;
}

//****************************************************************************
//
// InterruptSetKbdHandler sets the address of the routine that handles the
// keyboard interrupt source.
//
//****************************************************************************
void
InterruptSetKbdHandler(PFNISR pfnKbd)
{
    //
    // Remember the address of the keyboard handler routine.
    //
    pfnKbdHandler = pfnKbd;
}

//****************************************************************************
//
// InterruptSetSSI2Handler sets the address of the routine that handles the
// SSI2 interrupt sources.
//
//****************************************************************************
void
InterruptSetSSI2Handler(PFNISR pfnSSI2)
{
    //
    // Remember the address of the SSI2 handler routine.
    //
    pfnSSI2Handler = pfnSSI2;
}

//****************************************************************************
//
// InterruptSetParallelHandler sets the address of the routine that handles
// the parallel port interrupt source.
//
//****************************************************************************
void
InterruptSetParallelHandler(PFNISR pfnParallel)
{
    //
    // Remember the address of the parallel handler routine.
    //
    pfnParallelHandler = pfnParallel;
}

⌨️ 快捷键说明

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