]> git.sur5r.net Git - freertos/blob
849cb48dbff166a78e1069a3bc187716b5944641
[freertos] /
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2015 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_v3_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 * 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
48 * 3.1   kvn    04/10/15 Modified code for latest RTL changes.
49 * </pre>
50 *
51 *****************************************************************************/
52
53 /***************************** Include Files ********************************/
54
55 #include "xuartps.h"
56
57 /************************** Constant Definitions ****************************/
58
59 /**************************** Type Definitions ******************************/
60
61 /***************** Macros (Inline Functions) Definitions ********************/
62
63 /************************** Function Prototypes *****************************/
64
65 static void ReceiveDataHandler(XUartPs *InstancePtr);
66 static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus);
67 static void ReceiveErrorHandler(XUartPs *InstancePtr, u32 IsrStatus);
68 static void ReceiveTimeoutHandler(XUartPs *InstancePtr);
69 static void ModemHandler(XUartPs *InstancePtr);
70
71
72 /* Internal function prototypes implemented in xuartps.c */
73 extern u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr);
74 extern u32 XUartPs_SendBuffer(XUartPs *InstancePtr);
75
76 /************************** Variable Definitions ****************************/
77
78 typedef void (*Handler)(XUartPs *InstancePtr);
79
80 /****************************************************************************/
81 /**
82 *
83 * This function gets the interrupt mask
84 *
85 * @param        InstancePtr is a pointer to the XUartPs instance.
86 *
87 * @return
88 *               The current interrupt mask. The mask indicates which interupts
89 *               are enabled.
90 *
91 * @note         None.
92 *
93 *****************************************************************************/
94 u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr)
95 {
96         /* Assert validates the input argument */
97         Xil_AssertNonvoid(InstancePtr != NULL);
98
99         /* Read the Interrupt Mask register */
100         return (XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
101                          XUARTPS_IMR_OFFSET));
102 }
103
104 /****************************************************************************/
105 /**
106 *
107 * This function sets the interrupt mask.
108 *
109 * @param        InstancePtr is a pointer to the XUartPs instance
110 * @param        Mask contains the interrupts to be enabled or disabled.
111 *               A '1' enables an interupt, and a '0' disables.
112 *
113 * @return       None.
114 *
115 * @note         None.
116 *
117 *****************************************************************************/
118 void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask)
119 {
120         u32 TempMask = Mask;
121         /* Assert validates the input arguments */
122         Xil_AssertVoid(InstancePtr != NULL);
123
124         TempMask &= (u32)XUARTPS_IXR_MASK;
125
126         /* Write the mask to the IER Register */
127         XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
128                  XUARTPS_IER_OFFSET, TempMask);
129
130         /* Write the inverse of the Mask to the IDR register */
131         XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
132                  XUARTPS_IDR_OFFSET, (~TempMask));
133
134 }
135
136 /****************************************************************************/
137 /**
138 *
139 * This function sets the handler that will be called when an event (interrupt)
140 * occurs that needs application's attention.
141 *
142 * @param        InstancePtr is a pointer to the XUartPs instance
143 * @param        FuncPtr is the pointer to the callback function.
144 * @param        CallBackRef is the upper layer callback reference passed back
145 *               when the callback function is invoked.
146 *
147 * @return       None.
148 *
149 * @note
150 *
151 * There is no assert on the CallBackRef since the driver doesn't know what it
152 * is (nor should it)
153 *
154 *****************************************************************************/
155 void XUartPs_SetHandler(XUartPs *InstancePtr, XUartPs_Handler FuncPtr,
156                  void *CallBackRef)
157 {
158         /*
159          * Asserts validate the input arguments
160          * CallBackRef not checked, no way to know what is valid
161          */
162         Xil_AssertVoid(InstancePtr != NULL);
163         Xil_AssertVoid(FuncPtr != NULL);
164         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
165
166         InstancePtr->Handler = FuncPtr;
167         InstancePtr->CallBackRef = CallBackRef;
168 }
169
170 /****************************************************************************/
171 /**
172 *
173 * This function is the interrupt handler for the driver.
174 * It must be connected to an interrupt system by the application such that it
175 * can be called when an interrupt occurs.
176 *
177 * @param        InstancePtr contains a pointer to the driver instance
178 *
179 * @return       None.
180 *
181 * @note         None.
182 *
183 ******************************************************************************/
184 void XUartPs_InterruptHandler(XUartPs *InstancePtr)
185 {
186         u32 IsrStatus;
187
188         Xil_AssertVoid(InstancePtr != NULL);
189         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
190
191         /*
192          * Read the interrupt ID register to determine which
193          * interrupt is active
194          */
195         IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
196                                    XUARTPS_IMR_OFFSET);
197
198         IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
199                                    XUARTPS_ISR_OFFSET);
200
201         /* Dispatch an appropriate handler. */
202         if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |
203                         (u32)XUARTPS_IXR_RXFULL)) != (u32)0) {
204                 /* Received data interrupt */
205                 ReceiveDataHandler(InstancePtr);
206         }
207
208         if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL))
209                                                                          != (u32)0) {
210                 /* Transmit data interrupt */
211                 SendDataHandler(InstancePtr, IsrStatus);
212         }
213
214         /* XUARTPS_IXR_RBRK is applicable only for Zynq Ultrascale+ MP */
215         if ((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING |
216                         (u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK)) != (u32)0) {
217                 /* Received Error Status interrupt */
218                 ReceiveErrorHandler(InstancePtr, IsrStatus);
219         }
220
221         if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) {
222                 /* Received Timeout interrupt */
223                 ReceiveTimeoutHandler(InstancePtr);
224         }
225
226         if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) {
227                 /* Modem status interrupt */
228                 ModemHandler(InstancePtr);
229         }
230
231         /* Clear the interrupt status. */
232         XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
233                 IsrStatus);
234
235 }
236
237 /****************************************************************************/
238 /*
239 *
240 * This function handles interrupts for receive errors which include
241 * overrun errors, framing errors, parity errors, and the break interrupt.
242 *
243 * @param        InstancePtr is a pointer to the XUartPs instance.
244 *
245 * @return       None.
246 *
247 * @note         None.
248 *
249 *****************************************************************************/
250 static void ReceiveErrorHandler(XUartPs *InstancePtr, u32 IsrStatus)
251 {
252         u32 ByteStatusValue, EventData;
253         u32 Event;
254
255         InstancePtr->is_rxbs_error = 0;
256
257         if ((InstancePtr->Platform == XPLAT_ZYNQ_ULTRA_MP) &&
258                 (IsrStatus & ((u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK
259                                         | (u32)XUARTPS_IXR_FRAMING))) {
260                 InstancePtr->is_rxbs_error = 1;
261         }
262         /*
263          * If there are bytes still to be received in the specified buffer
264          * go ahead and receive them. Removing bytes from the RX FIFO will
265          * clear the interrupt.
266          */
267
268         (void)XUartPs_ReceiveBuffer(InstancePtr);
269
270         if (!(InstancePtr->is_rxbs_error)) {
271                 Event = XUARTPS_EVENT_RECV_ERROR;
272                 EventData = InstancePtr->ReceiveBuffer.RequestedBytes -
273                         InstancePtr->ReceiveBuffer.RemainingBytes;
274
275                 /*
276                  * Call the application handler to indicate that there is a receive
277                  * error or a break interrupt, if the application cares about the
278                  * error it call a function to get the last errors.
279                  */
280                 InstancePtr->Handler(InstancePtr->CallBackRef,
281                                         Event,
282                                         EventData);
283         }
284 }
285
286 /****************************************************************************/
287 /**
288 *
289 * This function handles the receive timeout interrupt. This interrupt occurs
290 * whenever a number of bytes have been present in the RX FIFO and the receive
291 * data line has been idle for at lease 4 or more character times, (the timeout
292 * is set using XUartPs_SetrecvTimeout() function).
293 *
294 * @param        InstancePtr is a pointer to the XUartPs instance
295 *
296 * @return       None.
297 *
298 * @note         None.
299 *
300 *****************************************************************************/
301 static void ReceiveTimeoutHandler(XUartPs *InstancePtr)
302 {
303         u32 Event;
304
305         /*
306          * If there are bytes still to be received in the specified buffer
307          * go ahead and receive them. Removing bytes from the RX FIFO will
308          * clear the interrupt.
309          */
310         if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) {
311                 (void)XUartPs_ReceiveBuffer(InstancePtr);
312         }
313
314         /*
315          * If there are no more bytes to receive then indicate that this is
316          * not a receive timeout but the end of the buffer reached, a timeout
317          * normally occurs if # of bytes is not divisible by FIFO threshold,
318          * don't rely on previous test of remaining bytes since receive
319          * function updates it
320          */
321         if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) {
322                 Event = XUARTPS_EVENT_RECV_TOUT;
323         } else {
324                 Event = XUARTPS_EVENT_RECV_DATA;
325         }
326
327         /*
328          * Call the application handler to indicate that there is a receive
329          * timeout or data event
330          */
331         InstancePtr->Handler(InstancePtr->CallBackRef, Event,
332                                  InstancePtr->ReceiveBuffer.RequestedBytes -
333                                  InstancePtr->ReceiveBuffer.RemainingBytes);
334
335 }
336 /****************************************************************************/
337 /**
338 *
339 * This function handles the interrupt when data is in RX FIFO.
340 *
341 * @param        InstancePtr is a pointer to the XUartPs instance
342 *
343 * @return       None.
344 *
345 * @note         None.
346 *
347 *****************************************************************************/
348 static void ReceiveDataHandler(XUartPs *InstancePtr)
349 {
350         /*
351          * If there are bytes still to be received in the specified buffer
352          * go ahead and receive them. Removing bytes from the RX FIFO will
353          * clear the interrupt.
354          */
355          if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) {
356                 (void)XUartPs_ReceiveBuffer(InstancePtr);
357         }
358
359          /* If the last byte of a message was received then call the application
360          * handler, this code should not use an else from the previous check of
361          * the number of bytes to receive because the call to receive the buffer
362          * updates the bytes ramained
363          */
364         if (InstancePtr->ReceiveBuffer.RemainingBytes == (u32)0) {
365                 InstancePtr->Handler(InstancePtr->CallBackRef,
366                                 XUARTPS_EVENT_RECV_DATA,
367                                 (InstancePtr->ReceiveBuffer.RequestedBytes -
368                                 InstancePtr->ReceiveBuffer.RemainingBytes));
369         }
370
371 }
372
373 /****************************************************************************/
374 /**
375 *
376 * This function handles the interrupt when data has been sent, the transmit
377 * FIFO is empty (transmitter holding register).
378 *
379 * @param        InstancePtr is a pointer to the XUartPs instance
380 * @param        IsrStatus is the register value for channel status register
381 *
382 * @return       None.
383 *
384 * @note         None.
385 *
386 *****************************************************************************/
387 static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus)
388 {
389
390         /*
391          * If there are not bytes to be sent from the specified buffer then disable
392          * the transmit interrupt so it will stop interrupting as it interrupts
393          * any time the FIFO is empty
394          */
395         if (InstancePtr->SendBuffer.RemainingBytes == (u32)0) {
396                 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
397                                 XUARTPS_IDR_OFFSET,
398                                 ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL));
399
400                 /* Call the application handler to indicate the sending is done */
401                 InstancePtr->Handler(InstancePtr->CallBackRef,
402                                         XUARTPS_EVENT_SENT_DATA,
403                                         InstancePtr->SendBuffer.RequestedBytes -
404                                         InstancePtr->SendBuffer.RemainingBytes);
405         }
406
407         /* If TX FIFO is empty, send more. */
408         else if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY)) != (u32)0) {
409                 (void)XUartPs_SendBuffer(InstancePtr);
410         }
411         else {
412                 /* Else with dummy entry for MISRA-C Compliance.*/
413                 ;
414         }
415 }
416
417 /****************************************************************************/
418 /**
419 *
420 * This function handles modem interrupts.  It does not do any processing
421 * except to call the application handler to indicate a modem event.
422 *
423 * @param        InstancePtr is a pointer to the XUartPs instance
424 *
425 * @return       None.
426 *
427 * @note         None.
428 *
429 *****************************************************************************/
430 static void ModemHandler(XUartPs *InstancePtr)
431 {
432         u32 MsrRegister;
433
434         /*
435          * Read the modem status register so that the interrupt is acknowledged
436          * and it can be passed to the callback handler with the event
437          */
438         MsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
439                           XUARTPS_MODEMSR_OFFSET);
440
441         /*
442          * Call the application handler to indicate the modem status changed,
443          * passing the modem status and the event data in the call
444          */
445         InstancePtr->Handler(InstancePtr->CallBackRef,
446                                   XUARTPS_EVENT_MODEM,
447                                   MsrRegister);
448
449 }
450 /** @} */