?? isr.c
字號(hào):
//****************************************************************************
//
// 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.
//
//****************************************************************************
PFNISR Angel_GetIRQ(int iSWINum) __attribute__ ((interrupt ("SWI")));
long Angel_SetIRQ(int iSWINum, PFNISR pfnIsr)__attribute__ ((interrupt ("SWI")));
PFNISR Angel_GetFIQ(int iSWINum)__attribute__ ((interrupt ("SWI")));
long Angel_SetFIQ(int iSWINum, PFNISR pfnIsr)__attribute__ ((interrupt ("SWI")));
PFNISR Angel_GetIRQ(int iSWINum){}
long Angel_SetIRQ(int iSWINum, PFNISR pfnIsr){return 0;}
PFNISR Angel_GetFIQ(int iSWINum){}
long Angel_SetFIQ(int iSWINum, PFNISR pfnIsr){return 0;}
//****************************************************************************
//
// 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;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -