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

📄 xuartns550_intr.c

📁 powerpc405下linux的串口驱动程序
💻 C
字号:
/* $Id: xuartns550_intr.c,v 1.1 2006/02/17 22:43:40 moleres Exp $ *//*******************************************************************************       XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"*       AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND*       SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,*       OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,*       APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION*       THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,*       AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE*       FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY*       WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE*       IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR*       REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF*       INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS*       FOR A PARTICULAR PURPOSE.**       (c) Copyright 2002 Xilinx Inc.*       All rights reserved.******************************************************************************//****************************************************************************//**** @file xuartns550_intr.c** This file contains the functions that are related to interrupt processing* for the 16450/16550 UART driver.** <pre>* MODIFICATION HISTORY:** Ver   Who  Date     Changes* ----- ---- -------- -----------------------------------------------* 1.00b jhl  03/11/02 Repartitioned driver for smaller files.* </pre>******************************************************************************//***************************** Include Files ********************************/#include "xuartns550.h"#include "xuartns550_i.h"#include "xio.h"/************************** Constant Definitions ****************************//**************************** Type Definitions ******************************//***************** Macros (Inline Functions) Definitions ********************//************************** Function Prototypes *****************************/static void NoInterruptHandler(XUartNs550 *InstancePtr);static void ReceiveStatusHandler(XUartNs550 *InstancePtr);static void ReceiveTimeoutHandler(XUartNs550 *InstancePtr);static void ReceiveDataHandler(XUartNs550 *InstancePtr);static void SendDataHandler(XUartNs550 *InstancePtr);static void ModemHandler(XUartNs550 *InstancePtr);/************************** Variable Definitions ****************************/typedef void (*Handler)(XUartNs550 *InstancePtr);/* The following tables is a function pointer table that contains pointers * to each of the handlers for specific kinds of interrupts. The table is * indexed by the value read from the interrupt ID register. */static Handler HandlerTable[13] ={    ModemHandler,           /* 0 */    NoInterruptHandler,     /* 1 */    SendDataHandler,        /* 2 */    XNULL,                  /* 3 */    ReceiveDataHandler,     /* 4 */    XNULL,                  /* 5 */    ReceiveStatusHandler,   /* 6 */    XNULL,                  /* 7 */    XNULL,                  /* 8 */    XNULL,                  /* 9 */    XNULL,                  /* 10 */    XNULL,                  /* 11 */    ReceiveTimeoutHandler   /* 12 */};/****************************************************************************//**** This function sets the handler that will be called when an event (interrupt)* occurs in the driver. The purpose of the handler is to allow application* specific processing to be performed.** @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.* @param    FuncPtr is the pointer to the callback function.* @param    CallBackRef is the upper layer callback reference passed back when*           the callback function is invoked.** @return** None.** @notes** There is no assert on the CallBackRef since the driver doesn't know what it* is (nor should it)******************************************************************************/void XUartNs550_SetHandler(XUartNs550 *InstancePtr,                           XUartNs550_Handler FuncPtr, void *CallBackRef){    /*     * Assert validates the input arguments     * CallBackRef not checked, no way to know what is valid     */    XASSERT_VOID(InstancePtr != XNULL);    XASSERT_VOID(FuncPtr != XNULL);    XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);    InstancePtr->Handler = FuncPtr;    InstancePtr->CallBackRef = CallBackRef;}/****************************************************************************//**** This function is the interrupt handler for the 16450/16550 UART driver.* It must be connected to an interrupt system by the user such that it is* called when an interrupt for any 16450/16550 UART occurs. This function* does not save or restore the processor context such that the user must* ensure this occurs.** @param    InstancePtr contains a pointer to the instance of the UART that*           the interrupt is for.** @return** None.** @note** None.*******************************************************************************/void XUartNs550_InterruptHandler(XUartNs550 *InstancePtr){    Xuint8 IsrStatus;    XASSERT_VOID(InstancePtr != XNULL);    /* Read the interrupt ID register to determine which, only one,     * interrupt is active     */    IsrStatus = XIo_In8(InstancePtr->BaseAddress + XUN_IIR_OFFSET) &                        XUN_INT_ID_MASK;    /* Make sure the handler table has a handler defined for the interrupt     * that is active, and then call the handler     */    XASSERT_VOID(HandlerTable[IsrStatus] != XNULL);    HandlerTable[IsrStatus](InstancePtr);}/****************************************************************************//**** This function handles the case when the value read from the interrupt ID* register indicates no interrupt is to be serviced.** @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.** @return** None.** @note** None.** @internal** The LsrRegister is volatile to ensure that optimization will not cause the* statement to be optimized away.******************************************************************************/static void NoInterruptHandler(XUartNs550 *InstancePtr){    volatile Xuint8 LsrRegister;    /*     * Reading the ID register clears the currently asserted interrupts     */    LsrRegister = XIo_In8(InstancePtr->BaseAddress + XUN_LSR_OFFSET);    /* Update the stats to reflect any errors that might be read */    XUartNs550_mUpdateStats(InstancePtr, LsrRegister);}/****************************************************************************//**** This function handles interrupts for receive status updates which include* overrun errors, framing errors, parity errors, and the break interrupt.** @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.** @return** None.** @note** If this handler executes and data is not supposed to be received, then* this probably means data is being received that contains errors and the* the user may need to clear the receive FIFOs to dump the data.******************************************************************************/static void ReceiveStatusHandler(XUartNs550 *InstancePtr){    Xuint8 LsrRegister;    /*     * If there are bytes still to be received in the specified buffer     * go ahead and receive them     */    if (InstancePtr->ReceiveBuffer.RemainingBytes != 0)    {        XUartNs550_ReceiveBuffer(InstancePtr);    }    else    {        /*         * Reading the ID register clears the currently asserted interrupts         * and this must be done since there was no data to receive, update         * the status for the status read         */        LsrRegister = XIo_In8(InstancePtr->BaseAddress + XUN_LSR_OFFSET);        XUartNs550_mUpdateStats(InstancePtr, LsrRegister);    }    /*     * Call the application handler to indicate that there is a receive     * error or a break interrupt, if the application cares about the     * error it call a function to get the last errors     */    InstancePtr->Handler(InstancePtr->CallBackRef, XUN_EVENT_RECV_ERROR,                         InstancePtr->ReceiveBuffer.RequestedBytes -                         InstancePtr->ReceiveBuffer.RemainingBytes);    /* Update the receive stats to reflect the receive interrupt */    InstancePtr->Stats.StatusInterrupts++;}/****************************************************************************//**** This function handles the receive timeout interrupt. This interrupt occurs* whenever a number of bytes have been present in the FIFO for 4 character* times, the receiver is not receiving any data, and the number of bytes* present is less than the FIFO threshold.** @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.** @return** None.** @note** None.******************************************************************************/static void ReceiveTimeoutHandler(XUartNs550 *InstancePtr){    Xuint32 Event;    /*     * If there are bytes still to be received in the specified buffer     * go ahead and receive them     */    if (InstancePtr->ReceiveBuffer.RemainingBytes != 0)    {        XUartNs550_ReceiveBuffer(InstancePtr);    }    /*     * If there are no more bytes to receive then indicate that this is     * not a receive timeout but the end of the buffer reached, a timeout     * normally occurs if # of bytes is not divisible by FIFO threshold,     * don't rely on previous test of remaining bytes since receive function     * updates it     */    if (InstancePtr->ReceiveBuffer.RemainingBytes != 0)    {        Event = XUN_EVENT_RECV_TIMEOUT;    }    else    {        Event = XUN_EVENT_RECV_DATA;    }    /*     * Call the application handler to indicate that there is a receive     * timeout or data event     */    InstancePtr->Handler(InstancePtr->CallBackRef, Event,                         InstancePtr->ReceiveBuffer.RequestedBytes -                         InstancePtr->ReceiveBuffer.RemainingBytes);    /* Update the receive stats to reflect the receive interrupt */    InstancePtr->Stats.ReceiveInterrupts++;}/****************************************************************************//**** This function handles the interrupt when data is received, either a single* byte when FIFOs are not enabled, or multiple bytes with the FIFO.** @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.** @return** None.** @note** None.******************************************************************************/static void ReceiveDataHandler(XUartNs550 *InstancePtr){    /*     * If there are bytes still to be received in the specified buffer     * go ahead and receive them     */     if (InstancePtr->ReceiveBuffer.RemainingBytes != 0)    {        XUartNs550_ReceiveBuffer(InstancePtr);    }    /* If the last byte of a message was received then call the application     * handler, this code should not use an else from the previous check of     * the number of bytes to receive because the call to receive the buffer     * updates the bytes to receive     */    if (InstancePtr->ReceiveBuffer.RemainingBytes == 0)    {        InstancePtr->Handler(InstancePtr->CallBackRef, XUN_EVENT_RECV_DATA,                             InstancePtr->ReceiveBuffer.RequestedBytes -                             InstancePtr->ReceiveBuffer.RemainingBytes);    }    /* Update the receive stats to reflect the receive interrupt */    InstancePtr->Stats.ReceiveInterrupts++;}/****************************************************************************//**** This function handles the interrupt when data has been sent, the transmit* FIFO is empty (transmitter holding register).** @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.** @return** None.** @note** None.******************************************************************************/static void SendDataHandler(XUartNs550 *InstancePtr){   Xuint8 IerRegister;    /*     * If there are not bytes to be sent from the specified buffer then disable     * the transmit interrupt so it will stop interrupting as it interrupts     * any time the FIFO is empty     */    if (InstancePtr->SendBuffer.RemainingBytes == 0)    {        IerRegister = XIo_In8(InstancePtr->BaseAddress + XUN_IER_OFFSET);        XIo_Out8(InstancePtr->BaseAddress + XUN_IER_OFFSET,                 IerRegister & ~XUN_IER_TX_EMPTY);        /* Call the application handler to indicate the data has been sent */        InstancePtr->Handler(InstancePtr->CallBackRef, XUN_EVENT_SENT_DATA,                             InstancePtr->SendBuffer.RequestedBytes -                             InstancePtr->SendBuffer.RemainingBytes);    }    /*     * Otherwise there is still more data to send in the specified buffer     * so go ahead and send it     */    else    {        XUartNs550_SendBuffer(InstancePtr);    }    /* Update the transmit stats to reflect the transmit interrupt */    InstancePtr->Stats.TransmitInterrupts++;}/****************************************************************************//**** This function handles modem interrupts.  It does not do any processing* except to call the application handler to indicate a modem event.** @param    InstancePtr is a pointer to the XUartNs550 instance to be worked on.** @return** None.** @note** None.******************************************************************************/static void ModemHandler(XUartNs550 *InstancePtr){    Xuint8 MsrRegister;    /* Read the modem status register so that the interrupt is acknowledged     * and so that it can be passed to the callback handler with the event     */    MsrRegister = XIo_In8(InstancePtr->BaseAddress + XUN_MSR_OFFSET);    /* Call the application handler to indicate the modem status changed,     * passing the modem status and the event data in the call     */    InstancePtr->Handler(InstancePtr->CallBackRef, XUN_EVENT_MODEM,                         MsrRegister);    /* Update the modem stats to reflect the modem interrupt */    InstancePtr->Stats.ModemInterrupts++;}

⌨️ 快捷键说明

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