]> git.sur5r.net Git - freertos/blob
156d3e263b073f7999a026475ae25cd003ab4285
[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 *
37 * This file contains the functions for interrupt handling
38 *
39 * <pre>
40 * MODIFICATION HISTORY:
41 *
42 * Ver   Who    Date     Changes
43 * ----- ------ -------- -----------------------------------------------
44 * 1.00  drg/jz 01/13/10 First Release
45 * 3.00  kvn    02/13/15 Modified code for MISRA-C:2012 compliance.
46 * </pre>
47 *
48 *****************************************************************************/
49
50 /***************************** Include Files ********************************/
51
52 #include "xuartps.h"
53
54 /************************** Constant Definitions ****************************/
55
56 /**************************** Type Definitions ******************************/
57
58 /***************** Macros (Inline Functions) Definitions ********************/
59
60 /************************** Function Prototypes *****************************/
61
62 static void ReceiveDataHandler(XUartPs *InstancePtr);
63 static void SendDataHandler(XUartPs *InstancePtr, u32 IsrStatus);
64 static void ReceiveErrorHandler(XUartPs *InstancePtr);
65 static void ReceiveTimeoutHandler(XUartPs *InstancePtr);
66 static void ModemHandler(XUartPs *InstancePtr);
67
68
69 /* Internal function prototypes implemented in xuartps.c */
70 extern u32 XUartPs_ReceiveBuffer(XUartPs *InstancePtr);
71 extern u32 XUartPs_SendBuffer(XUartPs *InstancePtr);
72
73 /************************** Variable Definitions ****************************/
74
75 typedef void (*Handler)(XUartPs *InstancePtr);
76
77 /****************************************************************************/
78 /**
79 *
80 * This function gets the interrupt mask
81 *
82 * @param        InstancePtr is a pointer to the XUartPs instance.
83 *
84 * @return
85 *               The current interrupt mask. The mask indicates which interupts
86 *               are enabled.
87 *
88 * @note         None.
89 *
90 *****************************************************************************/
91 u32 XUartPs_GetInterruptMask(XUartPs *InstancePtr)
92 {
93         /*
94          * Assert validates the input argument
95          */
96         Xil_AssertNonvoid(InstancePtr != NULL);
97
98         /*
99          * Read the Interrupt Mask register
100          */
101         return (XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
102                          XUARTPS_IMR_OFFSET));
103 }
104
105 /****************************************************************************/
106 /**
107 *
108 * This function sets the interrupt mask.
109 *
110 * @param        InstancePtr is a pointer to the XUartPs instance
111 * @param        Mask contains the interrupts to be enabled or disabled.
112 *               A '1' enables an interupt, and a '0' disables.
113 *
114 * @return       None.
115 *
116 * @note         None.
117 *
118 *****************************************************************************/
119 void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask)
120 {
121         u32 TempMask = Mask;
122         /*
123          * Assert validates the input arguments
124          */
125         Xil_AssertVoid(InstancePtr != NULL);
126
127         TempMask &= (u32)XUARTPS_IXR_MASK;
128
129         /*
130          * Write the mask to the IER Register
131          */
132         XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
133                  XUARTPS_IER_OFFSET, TempMask);
134
135         /*
136          * Write the inverse of the Mask to the IDR register
137          */
138         XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
139                  XUARTPS_IDR_OFFSET, (~TempMask));
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 appropriate handler.
210          */
211         if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |
212                         (u32)XUARTPS_IXR_RXFULL)) != (u32)0) {
213                 /* Received data interrupt */
214                 ReceiveDataHandler(InstancePtr);
215         }
216
217         if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL))
218                                                                          != (u32)0) {
219                 /* Transmit data interrupt */
220                 SendDataHandler(InstancePtr, IsrStatus);
221         }
222
223         if((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING |
224                         (u32)XUARTPS_IXR_PARITY)) != (u32)0) {
225                 /* Received Error Status interrupt */
226                 ReceiveErrorHandler(InstancePtr);
227         }
228
229         if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) {
230                 /* Received Timeout interrupt */
231                 ReceiveTimeoutHandler(InstancePtr);
232         }
233
234         if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) {
235                 /* Modem status interrupt */
236                 ModemHandler(InstancePtr);
237         }
238
239         /*
240          * Clear the interrupt status.
241          */
242         XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
243                 IsrStatus);
244
245 }
246
247 /****************************************************************************/
248 /*
249 *
250 * This function handles interrupts for receive errors which include
251 * overrun errors, framing errors, parity errors, and the break interrupt.
252 *
253 * @param        InstancePtr is a pointer to the XUartPs instance.
254 *
255 * @return       None.
256 *
257 * @note         None.
258 *
259 *****************************************************************************/
260 static void ReceiveErrorHandler(XUartPs *InstancePtr)
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         if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) {
268                 (void)XUartPs_ReceiveBuffer(InstancePtr);
269         }
270
271         /*
272          * Call the application handler to indicate that there is a receive
273          * error or a break interrupt, if the application cares about the
274          * error it call a function to get the last errors.
275          */
276         InstancePtr->Handler(InstancePtr->CallBackRef,
277                                 XUARTPS_EVENT_RECV_ERROR,
278                                 (InstancePtr->ReceiveBuffer.RequestedBytes -
279                                 InstancePtr->ReceiveBuffer.RemainingBytes));
280
281 }
282 /****************************************************************************/
283 /**
284 *
285 * This function handles the receive timeout interrupt. This interrupt occurs
286 * whenever a number of bytes have been present in the RX FIFO and the receive
287 * data line has been idle for at lease 4 or more character times, (the timeout
288 * is set using XUartPs_SetrecvTimeout() function).
289 *
290 * @param        InstancePtr is a pointer to the XUartPs instance
291 *
292 * @return       None.
293 *
294 * @note         None.
295 *
296 *****************************************************************************/
297 static void ReceiveTimeoutHandler(XUartPs *InstancePtr)
298 {
299         u32 Event;
300
301         /*
302          * If there are bytes still to be received in the specified buffer
303          * go ahead and receive them. Removing bytes from the RX FIFO will
304          * clear the interrupt.
305          */
306         if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) {
307                 (void)XUartPs_ReceiveBuffer(InstancePtr);
308         }
309
310         /*
311          * If there are no more bytes to receive then indicate that this is
312          * not a receive timeout but the end of the buffer reached, a timeout
313          * normally occurs if # of bytes is not divisible by FIFO threshold,
314          * don't rely on previous test of remaining bytes since receive
315          * function updates it
316          */
317         if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) {
318                 Event = XUARTPS_EVENT_RECV_TOUT;
319         } else {
320                 Event = XUARTPS_EVENT_RECV_DATA;
321         }
322
323         /*
324          * Call the application handler to indicate that there is a receive
325          * timeout or data event
326          */
327         InstancePtr->Handler(InstancePtr->CallBackRef, Event,
328                                  InstancePtr->ReceiveBuffer.RequestedBytes -
329                                  InstancePtr->ReceiveBuffer.RemainingBytes);
330
331 }
332 /****************************************************************************/
333 /**
334 *
335 * This function handles the interrupt when data is in RX FIFO.
336 *
337 * @param        InstancePtr is a pointer to the XUartPs instance
338 *
339 * @return       None.
340 *
341 * @note         None.
342 *
343 *****************************************************************************/
344 static void ReceiveDataHandler(XUartPs *InstancePtr)
345 {
346         /*
347          * If there are bytes still to be received in the specified buffer
348          * go ahead and receive them. Removing bytes from the RX FIFO will
349          * clear the interrupt.
350          */
351          if (InstancePtr->ReceiveBuffer.RemainingBytes != (u32)0) {
352                 (void)XUartPs_ReceiveBuffer(InstancePtr);
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 == (u32)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 == (u32)0) {
392                 XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
393                                 XUARTPS_IDR_OFFSET,
394                                 ((u32)XUARTPS_IXR_TXEMPTY | (u32)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 & ((u32)XUARTPS_IXR_TXEMPTY)) != (u32)0) {
407                 (void)XUartPs_SendBuffer(InstancePtr);
408         }
409         else {
410                 /* Else with dummy entry for MISRA-C Compliance.*/
411                 ;
412         }
413 }
414
415 /****************************************************************************/
416 /**
417 *
418 * This function handles modem interrupts.  It does not do any processing
419 * except to call the application handler to indicate a modem event.
420 *
421 * @param        InstancePtr is a pointer to the XUartPs instance
422 *
423 * @return       None.
424 *
425 * @note         None.
426 *
427 *****************************************************************************/
428 static void ModemHandler(XUartPs *InstancePtr)
429 {
430         u32 MsrRegister;
431
432         /*
433          * Read the modem status register so that the interrupt is acknowledged
434          * and it can be passed to the callback handler with the event
435          */
436         MsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
437                           XUARTPS_MODEMSR_OFFSET);
438
439         /*
440          * Call the application handler to indicate the modem status changed,
441          * passing the modem status and the event data in the call
442          */
443         InstancePtr->Handler(InstancePtr->CallBackRef,
444                                   XUARTPS_EVENT_MODEM,
445                                   MsrRegister);
446
447 }