]> git.sur5r.net Git - freertos/blob
5cfbd0e6f6fcb5db07a5406188c1005419aae967
[freertos] /
1 /*****************************************************************************
2 *
3 * (c) Copyright 2010-13 Xilinx, Inc. All rights reserved.
4 *
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.
8 *
9 * DISCLAIMER
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.
25 *
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.
36 *
37 * THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE
38 * AT ALL TIMES.
39 *
40 *****************************************************************************/
41 /****************************************************************************/
42 /**
43 *
44 * @file xuartps_intr.c
45 *
46 * This file contains the functions for interrupt handling
47 *
48 * <pre>
49 * MODIFICATION HISTORY:
50 *
51 * Ver   Who    Date     Changes
52 * ----- ------ -------- -----------------------------------------------
53 * 1.00  drg/jz 01/13/10 First Release
54 * </pre>
55 *
56 *****************************************************************************/
57
58 /***************************** Include Files ********************************/
59
60 #include "xuartps.h"
61
62 /************************** Constant Definitions ****************************/
63
64 /**************************** Type Definitions ******************************/
65
66 /***************** Macros (Inline Functions) Definitions ********************/
67
68 /************************** Function Prototypes *****************************/
69
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);
75
76
77 /* Internal function prototypes implemented in xuartps.c */
78 extern unsigned int XUartPs_ReceiveBuffer(XUartPs *InstancePtr);
79 extern unsigned int XUartPs_SendBuffer(XUartPs *InstancePtr);
80
81 /************************** Variable Definitions ****************************/
82
83 typedef void (*Handler)(XUartPs *InstancePtr);
84
85 /****************************************************************************/
86 /**
87 *
88 * This function gets the interrupt mask
89 *
90 * @param        InstancePtr is a pointer to the XUartPs instance.
91 *
92 * @return
93 *               The current interrupt mask. The mask indicates which interupts
94 *               are enabled.
95 *
96 * @note         None.
97 *
98 *****************************************************************************/
99 u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr)
100 {
101         /*
102          * Assert validates the input argument
103          */
104         Xil_AssertNonvoid(InstancePtr != NULL);
105
106         /*
107          * Read the Interrupt Mask register
108          */
109         return (XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
110                          XUARTPS_IMR_OFFSET));
111 }
112
113 /****************************************************************************/
114 /**
115 *
116 * This function sets the interrupt mask.
117 *
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.
121 *
122 * @return       None.
123 *
124 * @note         None.
125 *
126 *****************************************************************************/
127 void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask)
128 {
129         /*
130          * Assert validates the input arguments
131          */
132         Xil_AssertVoid(InstancePtr != NULL);
133
134         Mask &= XUARTPS_IXR_MASK;
135
136         /*
137          * Write the mask to the IER Register
138          */
139         XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
140                  XUARTPS_IER_OFFSET, Mask);
141
142         /*
143          * Write the inverse of the Mask to the IDR register
144          */
145         XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
146                  XUARTPS_IDR_OFFSET, (~Mask));
147
148 }
149
150 /****************************************************************************/
151 /**
152 *
153 * This function sets the handler that will be called when an event (interrupt)
154 * occurs that needs application's attention.
155 *
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.
160 *
161 * @return       None.
162 *
163 * @note
164 *
165 * There is no assert on the CallBackRef since the driver doesn't know what it
166 * is (nor should it)
167 *
168 *****************************************************************************/
169 void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr,
170                  void *CallBackRef)
171 {
172         /*
173          * Asserts validate the input arguments
174          * CallBackRef not checked, no way to know what is valid
175          */
176         Xil_AssertVoid(InstancePtr != NULL);
177         Xil_AssertVoid(FuncPtr != NULL);
178         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
179
180         InstancePtr->Handler = FuncPtr;
181         InstancePtr->CallBackRef = CallBackRef;
182 }
183
184 /****************************************************************************/
185 /**
186 *
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.
190 *
191 * @param        InstancePtr contains a pointer to the driver instance
192 *
193 * @return       None.
194 *
195 * @note         None.
196 *
197 ******************************************************************************/
198 void XUartPs_InterruptHandler(XUartPs *InstancePtr)
199 {
200         u32 IsrStatus;
201
202         Xil_AssertVoid(InstancePtr != NULL);
203         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
204
205         /*
206          * Read the interrupt ID register to determine which
207          * interrupt is active
208          */
209         IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
210                                    XUARTPS_IMR_OFFSET);
211
212         IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
213                                    XUARTPS_ISR_OFFSET);
214
215         /*
216          * Dispatch an appropiate handler.
217          */
218         if(0 != (IsrStatus & (XUARTPS_IXR_RXOVR | XUARTPS_IXR_RXEMPTY |
219                                  XUARTPS_IXR_RXFULL))) {
220                 /* Recieved data interrupt */
221                 ReceiveDataHandler(InstancePtr);
222         }
223
224         if(0 != (IsrStatus & (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL))) {
225                 /* Transmit data interrupt */
226                 SendDataHandler(InstancePtr, IsrStatus);
227         }
228
229         if(0 != (IsrStatus & (XUARTPS_IXR_OVER | XUARTPS_IXR_FRAMING |
230                                 XUARTPS_IXR_PARITY))) {
231                 /* Recieved Error Status interrupt */
232                 ReceiveErrorHandler(InstancePtr);
233         }
234
235         if(0 != (IsrStatus & XUARTPS_IXR_TOUT )) {
236                 /* Recieved Timeout interrupt */
237                 ReceiveTimeoutHandler(InstancePtr);
238         }
239
240         if(0 != (IsrStatus & XUARTPS_IXR_DMS)) {
241                 /* Modem status interrupt */
242                 ModemHandler(InstancePtr);
243         }
244
245         /*
246          * Clear the interrupt status.
247          */
248         XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
249                 IsrStatus);
250
251 }
252
253 /****************************************************************************/
254 /*
255 *
256 * This function handles interrupts for receive errors which include
257 * overrun errors, framing errors, parity errors, and the break interrupt.
258 *
259 * @param        InstancePtr is a pointer to the XUartPs instance.
260 *
261 * @return       None.
262 *
263 * @note         None.
264 *
265 *****************************************************************************/
266 static void ReceiveErrorHandler(XUartPs *InstancePtr)
267 {
268         /*
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.
272          */
273         if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
274                 XUartPs_ReceiveBuffer(InstancePtr);
275         }
276
277         /*
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.
281          */
282         InstancePtr->Handler(InstancePtr->CallBackRef,
283                                 XUARTPS_EVENT_RECV_ERROR,
284                                 (InstancePtr->ReceiveBuffer.RequestedBytes -
285                                 InstancePtr->ReceiveBuffer.RemainingBytes));
286
287 }
288 /****************************************************************************/
289 /**
290 *
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).
295 *
296 * @param        InstancePtr is a pointer to the XUartPs instance
297 *
298 * @return       None.
299 *
300 * @note         None.
301 *
302 *****************************************************************************/
303 static void ReceiveTimeoutHandler(XUartPs *InstancePtr)
304 {
305         u32 Event;
306
307         /*
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.
311          */
312         if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
313                 XUartPs_ReceiveBuffer(InstancePtr);
314         }
315
316         /*
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
322          */
323         if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
324                 Event = XUARTPS_EVENT_RECV_TOUT;
325         } else {
326                 Event = XUARTPS_EVENT_RECV_DATA;
327         }
328
329         /*
330          * Call the application handler to indicate that there is a receive
331          * timeout or data event
332          */
333         InstancePtr->Handler(InstancePtr->CallBackRef, Event,
334                                  InstancePtr->ReceiveBuffer.RequestedBytes -
335                                  InstancePtr->ReceiveBuffer.RemainingBytes);
336
337 }
338 /****************************************************************************/
339 /**
340 *
341 * This function handles the interrupt when data is in RX FIFO.
342 *
343 * @param        InstancePtr is a pointer to the XUartPs instance
344 *
345 * @return       None.
346 *
347 * @note         None.
348 *
349 *****************************************************************************/
350 static void ReceiveDataHandler(XUartPs *InstancePtr)
351 {
352         /*
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.
356          */
357          if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
358                 XUartPs_ReceiveBuffer(InstancePtr);
359         }
360
361
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
366          */
367         if (InstancePtr->ReceiveBuffer.RemainingBytes == 0) {
368                 InstancePtr->Handler(InstancePtr->CallBackRef,
369                                 XUARTPS_EVENT_RECV_DATA,
370                                 (InstancePtr->ReceiveBuffer.RequestedBytes -
371                                 InstancePtr->ReceiveBuffer.RemainingBytes));
372         }
373
374 }
375
376 /****************************************************************************/
377 /**
378 *
379 * This function handles the interrupt when data has been sent, the transmit
380 * FIFO is empty (transmitter holding register).
381 *
382 * @param        InstancePtr is a pointer to the XUartPs instance
383 * @param        IsrStatus is the register value for channel status register
384 *
385 * @return       None.
386 *
387 * @note         None.
388 *
389 *****************************************************************************/
390 static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus)
391 {
392
393         /*
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
397          */
398         if (InstancePtr->SendBuffer.RemainingBytes == 0) {
399                 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
400                                 XUARTPS_IDR_OFFSET,
401                                 (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL));
402
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);
408         }
409
410         /*
411          * If TX FIFO is empty, send more.
412          */
413         else if(IsrStatus & XUARTPS_IXR_TXEMPTY) {
414                 XUartPs_SendBuffer(InstancePtr);
415         }
416
417 }
418
419 /****************************************************************************/
420 /**
421 *
422 * This function handles modem interrupts.  It does not do any processing
423 * except to call the application handler to indicate a modem event.
424 *
425 * @param        InstancePtr is a pointer to the XUartPs instance
426 *
427 * @return       None.
428 *
429 * @note         None.
430 *
431 *****************************************************************************/
432 static void ModemHandler(XUartPs *InstancePtr)
433 {
434         u32 MsrRegister;
435
436         /*
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
439          */
440         MsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
441                           XUARTPS_MODEMSR_OFFSET);
442
443         /*
444          * Call the application handler to indicate the modem status changed,
445          * passing the modem status and the event data in the call
446          */
447         InstancePtr->Handler(InstancePtr->CallBackRef,
448                                   XUARTPS_EVENT_MODEM,
449                                   MsrRegister);
450
451 }
452