📄 xuartns550_intr.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 + -