1 /*****************************************************************************
3 * (c) Copyright 2010-13 Xilinx, Inc. All rights reserved.
5 * This file contains confidential and proprietary information of Xilinx, Inc.
6 * and is protected under U.S. and international copyright and other
7 * intellectual property laws.
10 * This disclaimer is not a license and does not grant any rights to the
11 * materials distributed herewith. Except as otherwise provided in a valid
12 * license issued to you by Xilinx, and to the maximum extent permitted by
13 * applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL
14 * FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,
15 * IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
16 * MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;
17 * and (2) Xilinx shall not be liable (whether in contract or tort, including
18 * negligence, or under any other theory of liability) for any loss or damage
19 * of any kind or nature related to, arising under or in connection with these
20 * materials, including for any direct, or any indirect, special, incidental,
21 * or consequential loss or damage (including loss of data, profits, goodwill,
22 * or any type of loss or damage suffered as a result of any action brought by
23 * a third party) even if such damage or loss was reasonably foreseeable or
24 * Xilinx had been advised of the possibility of the same.
26 * CRITICAL APPLICATIONS
27 * Xilinx products are not designed or intended to be fail-safe, or for use in
28 * any application requiring fail-safe performance, such as life-support or
29 * safety devices or systems, Class III medical devices, nuclear facilities,
30 * applications related to the deployment of airbags, or any other applications
31 * that could lead to death, personal injury, or severe property or
32 * environmental damage (individually and collectively, "Critical
33 * Applications"). Customer assumes the sole risk and liability of any use of
34 * Xilinx products in Critical Applications, subject only to applicable laws
35 * and regulations governing limitations on product liability.
37 * THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE
40 *****************************************************************************/
41 /****************************************************************************/
44 * @file xuartps_intr.c
46 * This file contains the functions for interrupt handling
49 * MODIFICATION HISTORY:
51 * Ver Who Date Changes
52 * ----- ------ -------- -----------------------------------------------
53 * 1.00 drg/jz 01/13/10 First Release
56 *****************************************************************************/
58 /***************************** Include Files ********************************/
62 /************************** Constant Definitions ****************************/
64 /**************************** Type Definitions ******************************/
66 /***************** Macros (Inline Functions) Definitions ********************/
68 /************************** Function Prototypes *****************************/
70 static void ReceiveDataHandler(XUartPs *InstancePtr);
71 static void SendDataHandler(XUartPs *InstancePtr, u32 isrstatus);
72 static void ReceiveErrorHandler(XUartPs *InstancePtr);
73 static void ReceiveTimeoutHandler(XUartPs *InstancePtr);
74 static void ModemHandler(XUartPs *InstancePtr);
77 /* Internal function prototypes implemented in xuartps.c */
78 extern unsigned int XUartPs_ReceiveBuffer(XUartPs *InstancePtr);
79 extern unsigned int XUartPs_SendBuffer(XUartPs *InstancePtr);
81 /************************** Variable Definitions ****************************/
83 typedef void (*Handler)(XUartPs *InstancePtr);
85 /****************************************************************************/
88 * This function gets the interrupt mask
90 * @param InstancePtr is a pointer to the XUartPs instance.
93 * The current interrupt mask. The mask indicates which interupts
98 *****************************************************************************/
99 u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr)
102 * Assert validates the input argument
104 Xil_AssertNonvoid(InstancePtr != NULL);
107 * Read the Interrupt Mask register
109 return (XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
110 XUARTPS_IMR_OFFSET));
113 /****************************************************************************/
116 * This function sets the interrupt mask.
118 * @param InstancePtr is a pointer to the XUartPs instance
119 * @param Mask contains the interrupts to be enabled or disabled.
120 * A '1' enables an interupt, and a '0' disables.
126 *****************************************************************************/
127 void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask)
130 * Assert validates the input arguments
132 Xil_AssertVoid(InstancePtr != NULL);
134 Mask &= XUARTPS_IXR_MASK;
137 * Write the mask to the IER Register
139 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
140 XUARTPS_IER_OFFSET, Mask);
143 * Write the inverse of the Mask to the IDR register
145 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
146 XUARTPS_IDR_OFFSET, (~Mask));
150 /****************************************************************************/
153 * This function sets the handler that will be called when an event (interrupt)
154 * occurs that needs application's attention.
156 * @param InstancePtr is a pointer to the XUartPs instance
157 * @param FuncPtr is the pointer to the callback function.
158 * @param CallBackRef is the upper layer callback reference passed back
159 * when the callback function is invoked.
165 * There is no assert on the CallBackRef since the driver doesn't know what it
168 *****************************************************************************/
169 void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr,
173 * Asserts validate the input arguments
174 * CallBackRef not checked, no way to know what is valid
176 Xil_AssertVoid(InstancePtr != NULL);
177 Xil_AssertVoid(FuncPtr != NULL);
178 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
180 InstancePtr->Handler = FuncPtr;
181 InstancePtr->CallBackRef = CallBackRef;
184 /****************************************************************************/
187 * This function is the interrupt handler for the driver.
188 * It must be connected to an interrupt system by the application such that it
189 * can be called when an interrupt occurs.
191 * @param InstancePtr contains a pointer to the driver instance
197 ******************************************************************************/
198 void XUartPs_InterruptHandler(XUartPs *InstancePtr)
202 Xil_AssertVoid(InstancePtr != NULL);
203 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
206 * Read the interrupt ID register to determine which
207 * interrupt is active
209 IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
212 IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
216 * Dispatch an appropiate handler.
218 if(0 != (IsrStatus & (XUARTPS_IXR_RXOVR | XUARTPS_IXR_RXEMPTY |
219 XUARTPS_IXR_RXFULL))) {
220 /* Recieved data interrupt */
221 ReceiveDataHandler(InstancePtr);
224 if(0 != (IsrStatus & (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL))) {
225 /* Transmit data interrupt */
226 SendDataHandler(InstancePtr, IsrStatus);
229 if(0 != (IsrStatus & (XUARTPS_IXR_OVER | XUARTPS_IXR_FRAMING |
230 XUARTPS_IXR_PARITY))) {
231 /* Recieved Error Status interrupt */
232 ReceiveErrorHandler(InstancePtr);
235 if(0 != (IsrStatus & XUARTPS_IXR_TOUT )) {
236 /* Recieved Timeout interrupt */
237 ReceiveTimeoutHandler(InstancePtr);
240 if(0 != (IsrStatus & XUARTPS_IXR_DMS)) {
241 /* Modem status interrupt */
242 ModemHandler(InstancePtr);
246 * Clear the interrupt status.
248 XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
253 /****************************************************************************/
256 * This function handles interrupts for receive errors which include
257 * overrun errors, framing errors, parity errors, and the break interrupt.
259 * @param InstancePtr is a pointer to the XUartPs instance.
265 *****************************************************************************/
266 static void ReceiveErrorHandler(XUartPs *InstancePtr)
269 * If there are bytes still to be received in the specified buffer
270 * go ahead and receive them. Removing bytes from the RX FIFO will
271 * clear the interrupt.
273 if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
274 XUartPs_ReceiveBuffer(InstancePtr);
278 * Call the application handler to indicate that there is a receive
279 * error or a break interrupt, if the application cares about the
280 * error it call a function to get the last errors.
282 InstancePtr->Handler(InstancePtr->CallBackRef,
283 XUARTPS_EVENT_RECV_ERROR,
284 (InstancePtr->ReceiveBuffer.RequestedBytes -
285 InstancePtr->ReceiveBuffer.RemainingBytes));
288 /****************************************************************************/
291 * This function handles the receive timeout interrupt. This interrupt occurs
292 * whenever a number of bytes have been present in the RX FIFO and the receive
293 * data line has been idle for at lease 4 or more character times, (the timeout
294 * is set using XUartPs_SetrecvTimeout() function).
296 * @param InstancePtr is a pointer to the XUartPs instance
302 *****************************************************************************/
303 static void ReceiveTimeoutHandler(XUartPs *InstancePtr)
308 * If there are bytes still to be received in the specified buffer
309 * go ahead and receive them. Removing bytes from the RX FIFO will
310 * clear the interrupt.
312 if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
313 XUartPs_ReceiveBuffer(InstancePtr);
317 * If there are no more bytes to receive then indicate that this is
318 * not a receive timeout but the end of the buffer reached, a timeout
319 * normally occurs if # of bytes is not divisible by FIFO threshold,
320 * don't rely on previous test of remaining bytes since receive
321 * function updates it
323 if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
324 Event = XUARTPS_EVENT_RECV_TOUT;
326 Event = XUARTPS_EVENT_RECV_DATA;
330 * Call the application handler to indicate that there is a receive
331 * timeout or data event
333 InstancePtr->Handler(InstancePtr->CallBackRef, Event,
334 InstancePtr->ReceiveBuffer.RequestedBytes -
335 InstancePtr->ReceiveBuffer.RemainingBytes);
338 /****************************************************************************/
341 * This function handles the interrupt when data is in RX FIFO.
343 * @param InstancePtr is a pointer to the XUartPs instance
349 *****************************************************************************/
350 static void ReceiveDataHandler(XUartPs *InstancePtr)
353 * If there are bytes still to be received in the specified buffer
354 * go ahead and receive them. Removing bytes from the RX FIFO will
355 * clear the interrupt.
357 if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
358 XUartPs_ReceiveBuffer(InstancePtr);
362 /* If the last byte of a message was received then call the application
363 * handler, this code should not use an else from the previous check of
364 * the number of bytes to receive because the call to receive the buffer
365 * updates the bytes ramained
367 if (InstancePtr->ReceiveBuffer.RemainingBytes == 0) {
368 InstancePtr->Handler(InstancePtr->CallBackRef,
369 XUARTPS_EVENT_RECV_DATA,
370 (InstancePtr->ReceiveBuffer.RequestedBytes -
371 InstancePtr->ReceiveBuffer.RemainingBytes));
376 /****************************************************************************/
379 * This function handles the interrupt when data has been sent, the transmit
380 * FIFO is empty (transmitter holding register).
382 * @param InstancePtr is a pointer to the XUartPs instance
383 * @param IsrStatus is the register value for channel status register
389 *****************************************************************************/
390 static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus)
394 * If there are not bytes to be sent from the specified buffer then disable
395 * the transmit interrupt so it will stop interrupting as it interrupts
396 * any time the FIFO is empty
398 if (InstancePtr->SendBuffer.RemainingBytes == 0) {
399 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
401 (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL));
403 /* Call the application handler to indicate the sending is done */
404 InstancePtr->Handler(InstancePtr->CallBackRef,
405 XUARTPS_EVENT_SENT_DATA,
406 InstancePtr->SendBuffer.RequestedBytes -
407 InstancePtr->SendBuffer.RemainingBytes);
411 * If TX FIFO is empty, send more.
413 else if(IsrStatus & XUARTPS_IXR_TXEMPTY) {
414 XUartPs_SendBuffer(InstancePtr);
419 /****************************************************************************/
422 * This function handles modem interrupts. It does not do any processing
423 * except to call the application handler to indicate a modem event.
425 * @param InstancePtr is a pointer to the XUartPs instance
431 *****************************************************************************/
432 static void ModemHandler(XUartPs *InstancePtr)
437 * Read the modem status register so that the interrupt is acknowledged
438 * and it can be passed to the callback handler with the event
440 MsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
441 XUARTPS_MODEMSR_OFFSET);
444 * Call the application handler to indicate the modem status changed,
445 * passing the modem status and the event data in the call
447 InstancePtr->Handler(InstancePtr->CallBackRef,