]> git.sur5r.net Git - freertos/blob
a82d68b2ddf6869fa8984b8355adffb8b1ec45b3
[freertos] /
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2014 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /****************************************************************************/
33 /**
34 *
35 * @file xuartps_intr.c
36 * @addtogroup uartps_v2_1
37 * @{
38 *
39 * This file contains the functions for interrupt handling
40 *
41 * <pre>
42 * MODIFICATION HISTORY:
43 *
44 * Ver   Who    Date     Changes
45 * ----- ------ -------- -----------------------------------------------
46 * 1.00  drg/jz 01/13/10 First Release
47 * </pre>
48 *
49 *****************************************************************************/
50
51 /***************************** Include Files ********************************/
52
53 #include "xuartps.h"
54
55 /************************** Constant Definitions ****************************/
56
57 /**************************** Type Definitions ******************************/
58
59 /***************** Macros (Inline Functions) Definitions ********************/
60
61 /************************** Function Prototypes *****************************/
62
63 static void ReceiveDataHandler(XUartPs *InstancePtr);
64 static void SendDataHandler(XUartPs *InstancePtr, u32 isrstatus);
65 static void ReceiveErrorHandler(XUartPs *InstancePtr);
66 static void ReceiveTimeoutHandler(XUartPs *InstancePtr);
67 static void ModemHandler(XUartPs *InstancePtr);
68
69
70 /* Internal function prototypes implemented in xuartps.c */
71 extern unsigned int XUartPs_ReceiveBuffer(XUartPs *InstancePtr);
72 extern unsigned int XUartPs_SendBuffer(XUartPs *InstancePtr);
73
74 /************************** Variable Definitions ****************************/
75
76 typedef void (*Handler)(XUartPs *InstancePtr);
77
78 /****************************************************************************/
79 /**
80 *
81 * This function gets the interrupt mask
82 *
83 * @param        InstancePtr is a pointer to the XUartPs instance.
84 *
85 * @return
86 *               The current interrupt mask. The mask indicates which interupts
87 *               are enabled.
88 *
89 * @note         None.
90 *
91 *****************************************************************************/
92 u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr)
93 {
94         /*
95          * Assert validates the input argument
96          */
97         Xil_AssertNonvoid(InstancePtr != NULL);
98
99         /*
100          * Read the Interrupt Mask register
101          */
102         return (XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
103                          XUARTPS_IMR_OFFSET));
104 }
105
106 /****************************************************************************/
107 /**
108 *
109 * This function sets the interrupt mask.
110 *
111 * @param        InstancePtr is a pointer to the XUartPs instance
112 * @param        Mask contains the interrupts to be enabled or disabled.
113 *               A '1' enables an interupt, and a '0' disables.
114 *
115 * @return       None.
116 *
117 * @note         None.
118 *
119 *****************************************************************************/
120 void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask)
121 {
122         /*
123          * Assert validates the input arguments
124          */
125         Xil_AssertVoid(InstancePtr != NULL);
126
127         Mask &= XUARTPS_IXR_MASK;
128
129         /*
130          * Write the mask to the IER Register
131          */
132         XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
133                  XUARTPS_IER_OFFSET, Mask);
134
135         /*
136          * Write the inverse of the Mask to the IDR register
137          */
138         XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
139                  XUARTPS_IDR_OFFSET, (~Mask));
140
141 }
142
143 /****************************************************************************/
144 /**
145 *
146 * This function sets the handler that will be called when an event (interrupt)
147 * occurs that needs application's attention.
148 *
149 * @param        InstancePtr is a pointer to the XUartPs instance
150 * @param        FuncPtr is the pointer to the callback function.
151 * @param        CallBackRef is the upper layer callback reference passed back
152 *               when the callback function is invoked.
153 *
154 * @return       None.
155 *
156 * @note
157 *
158 * There is no assert on the CallBackRef since the driver doesn't know what it
159 * is (nor should it)
160 *
161 *****************************************************************************/
162 void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr,
163                  void *CallBackRef)
164 {
165         /*
166          * Asserts validate the input arguments
167          * CallBackRef not checked, no way to know what is valid
168          */
169         Xil_AssertVoid(InstancePtr != NULL);
170         Xil_AssertVoid(FuncPtr != NULL);
171         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
172
173         InstancePtr->Handler = FuncPtr;
174         InstancePtr->CallBackRef = CallBackRef;
175 }
176
177 /****************************************************************************/
178 /**
179 *
180 * This function is the interrupt handler for the driver.
181 * It must be connected to an interrupt system by the application such that it
182 * can be called when an interrupt occurs.
183 *
184 * @param        InstancePtr contains a pointer to the driver instance
185 *
186 * @return       None.
187 *
188 * @note         None.
189 *
190 ******************************************************************************/
191 void XUartPs_InterruptHandler(XUartPs *InstancePtr)
192 {
193         u32 IsrStatus;
194
195         Xil_AssertVoid(InstancePtr != NULL);
196         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
197
198         /*
199          * Read the interrupt ID register to determine which
200          * interrupt is active
201          */
202         IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
203                                    XUARTPS_IMR_OFFSET);
204
205         IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
206                                    XUARTPS_ISR_OFFSET);
207
208         /*
209          * Dispatch an appropiate handler.
210          */
211         if(0 != (IsrStatus & (XUARTPS_IXR_RXOVR | XUARTPS_IXR_RXEMPTY |
212                                  XUARTPS_IXR_RXFULL))) {
213                 /* Recieved data interrupt */
214                 ReceiveDataHandler(InstancePtr);
215         }
216
217         if(0 != (IsrStatus & (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL))) {
218                 /* Transmit data interrupt */
219                 SendDataHandler(InstancePtr, IsrStatus);
220         }
221
222         if(0 != (IsrStatus & (XUARTPS_IXR_OVER | XUARTPS_IXR_FRAMING |
223                                 XUARTPS_IXR_PARITY))) {
224                 /* Recieved Error Status interrupt */
225                 ReceiveErrorHandler(InstancePtr);
226         }
227
228         if(0 != (IsrStatus & XUARTPS_IXR_TOUT )) {
229                 /* Recieved Timeout interrupt */
230                 ReceiveTimeoutHandler(InstancePtr);
231         }
232
233         if(0 != (IsrStatus & XUARTPS_IXR_DMS)) {
234                 /* Modem status interrupt */
235                 ModemHandler(InstancePtr);
236         }
237
238         /*
239          * Clear the interrupt status.
240          */
241         XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
242                 IsrStatus);
243
244 }
245
246 /****************************************************************************/
247 /*
248 *
249 * This function handles interrupts for receive errors which include
250 * overrun errors, framing errors, parity errors, and the break interrupt.
251 *
252 * @param        InstancePtr is a pointer to the XUartPs instance.
253 *
254 * @return       None.
255 *
256 * @note         None.
257 *
258 *****************************************************************************/
259 static void ReceiveErrorHandler(XUartPs *InstancePtr)
260 {
261         /*
262          * If there are bytes still to be received in the specified buffer
263          * go ahead and receive them. Removing bytes from the RX FIFO will
264          * clear the interrupt.
265          */
266         if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
267                 XUartPs_ReceiveBuffer(InstancePtr);
268         }
269
270         /*
271          * Call the application handler to indicate that there is a receive
272          * error or a break interrupt, if the application cares about the
273          * error it call a function to get the last errors.
274          */
275         InstancePtr->Handler(InstancePtr->CallBackRef,
276                                 XUARTPS_EVENT_RECV_ERROR,
277                                 (InstancePtr->ReceiveBuffer.RequestedBytes -
278                                 InstancePtr->ReceiveBuffer.RemainingBytes));
279
280 }
281 /****************************************************************************/
282 /**
283 *
284 * This function handles the receive timeout interrupt. This interrupt occurs
285 * whenever a number of bytes have been present in the RX FIFO and the receive
286 * data line has been idle for at lease 4 or more character times, (the timeout
287 * is set using XUartPs_SetrecvTimeout() function).
288 *
289 * @param        InstancePtr is a pointer to the XUartPs instance
290 *
291 * @return       None.
292 *
293 * @note         None.
294 *
295 *****************************************************************************/
296 static void ReceiveTimeoutHandler(XUartPs *InstancePtr)
297 {
298         u32 Event;
299
300         /*
301          * If there are bytes still to be received in the specified buffer
302          * go ahead and receive them. Removing bytes from the RX FIFO will
303          * clear the interrupt.
304          */
305         if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
306                 XUartPs_ReceiveBuffer(InstancePtr);
307         }
308
309         /*
310          * If there are no more bytes to receive then indicate that this is
311          * not a receive timeout but the end of the buffer reached, a timeout
312          * normally occurs if # of bytes is not divisible by FIFO threshold,
313          * don't rely on previous test of remaining bytes since receive
314          * function updates it
315          */
316         if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
317                 Event = XUARTPS_EVENT_RECV_TOUT;
318         } else {
319                 Event = XUARTPS_EVENT_RECV_DATA;
320         }
321
322         /*
323          * Call the application handler to indicate that there is a receive
324          * timeout or data event
325          */
326         InstancePtr->Handler(InstancePtr->CallBackRef, Event,
327                                  InstancePtr->ReceiveBuffer.RequestedBytes -
328                                  InstancePtr->ReceiveBuffer.RemainingBytes);
329
330 }
331 /****************************************************************************/
332 /**
333 *
334 * This function handles the interrupt when data is in RX FIFO.
335 *
336 * @param        InstancePtr is a pointer to the XUartPs instance
337 *
338 * @return       None.
339 *
340 * @note         None.
341 *
342 *****************************************************************************/
343 static void ReceiveDataHandler(XUartPs *InstancePtr)
344 {
345         /*
346          * If there are bytes still to be received in the specified buffer
347          * go ahead and receive them. Removing bytes from the RX FIFO will
348          * clear the interrupt.
349          */
350          if (InstancePtr->ReceiveBuffer.RemainingBytes != 0) {
351                 XUartPs_ReceiveBuffer(InstancePtr);
352         }
353
354
355         /* If the last byte of a message was received then call the application
356          * handler, this code should not use an else from the previous check of
357          * the number of bytes to receive because the call to receive the buffer
358          * updates the bytes ramained
359          */
360         if (InstancePtr->ReceiveBuffer.RemainingBytes == 0) {
361                 InstancePtr->Handler(InstancePtr->CallBackRef,
362                                 XUARTPS_EVENT_RECV_DATA,
363                                 (InstancePtr->ReceiveBuffer.RequestedBytes -
364                                 InstancePtr->ReceiveBuffer.RemainingBytes));
365         }
366
367 }
368
369 /****************************************************************************/
370 /**
371 *
372 * This function handles the interrupt when data has been sent, the transmit
373 * FIFO is empty (transmitter holding register).
374 *
375 * @param        InstancePtr is a pointer to the XUartPs instance
376 * @param        IsrStatus is the register value for channel status register
377 *
378 * @return       None.
379 *
380 * @note         None.
381 *
382 *****************************************************************************/
383 static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus)
384 {
385
386         /*
387          * If there are not bytes to be sent from the specified buffer then disable
388          * the transmit interrupt so it will stop interrupting as it interrupts
389          * any time the FIFO is empty
390          */
391         if (InstancePtr->SendBuffer.RemainingBytes == 0) {
392                 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
393                                 XUARTPS_IDR_OFFSET,
394                                 (XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TXFULL));
395
396                 /* Call the application handler to indicate the sending is done */
397                 InstancePtr->Handler(InstancePtr->CallBackRef,
398                                         XUARTPS_EVENT_SENT_DATA,
399                                         InstancePtr->SendBuffer.RequestedBytes -
400                                         InstancePtr->SendBuffer.RemainingBytes);
401         }
402
403         /*
404          * If TX FIFO is empty, send more.
405          */
406         else if(IsrStatus & XUARTPS_IXR_TXEMPTY) {
407                 XUartPs_SendBuffer(InstancePtr);
408         }
409
410 }
411
412 /****************************************************************************/
413 /**
414 *
415 * This function handles modem interrupts.  It does not do any processing
416 * except to call the application handler to indicate a modem event.
417 *
418 * @param        InstancePtr is a pointer to the XUartPs instance
419 *
420 * @return       None.
421 *
422 * @note         None.
423 *
424 *****************************************************************************/
425 static void ModemHandler(XUartPs *InstancePtr)
426 {
427         u32 MsrRegister;
428
429         /*
430          * Read the modem status register so that the interrupt is acknowledged
431          * and it can be passed to the callback handler with the event
432          */
433         MsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
434                           XUARTPS_MODEMSR_OFFSET);
435
436         /*
437          * Call the application handler to indicate the modem status changed,
438          * passing the modem status and the event data in the call
439          */
440         InstancePtr->Handler(InstancePtr->CallBackRef,
441                                   XUARTPS_EVENT_MODEM,
442                                   MsrRegister);
443
444 }
445
446 /** @} */