]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/canps_v2_0/src/xcanps_intr.c
Preparing for next release...
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo_bsp / ps7_cortexa9_0 / libsrc / canps_v2_0 / src / xcanps_intr.c
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 xcanps_intr.c
36 *
37 * This file contains functions related to CAN interrupt handling.
38 *
39 * <pre>
40 * MODIFICATION HISTORY:
41 *
42 * Ver   Who    Date     Changes
43 * ----- -----  -------- -----------------------------------------------
44 * 1.00a xd/sv  01/12/10 First release
45 * </pre>
46 *
47 ******************************************************************************/
48
49 /***************************** Include Files *********************************/
50
51 #include "xcanps.h"
52
53 /************************** Constant Definitions *****************************/
54
55 /**************************** Type Definitions *******************************/
56
57 /***************** Macros (Inline Functions) Definitions *********************/
58
59 /************************** Variable Definitions *****************************/
60
61 /************************** Function Prototypes ******************************/
62
63 /****************************************************************************/
64 /**
65 *
66 * This routine enables interrupt(s). Use the XCANPS_IXR_* constants defined in
67 * xcanps_hw.h to create the bit-mask to enable interrupts.
68 *
69 * @param        InstancePtr is a pointer to the XCanPs instance.
70 * @param        Mask is the mask to enable. Bit positions of 1 will be enabled.
71 *               Bit positions of 0 will keep the previous setting. This mask is
72 *               formed by OR'ing XCANPS_IXR_* bits defined in xcanps_hw.h.
73 *
74 * @return       None.
75 *
76 * @note         None.
77 *
78 *****************************************************************************/
79 void XCanPs_IntrEnable(XCanPs *InstancePtr, u32 Mask)
80 {
81         u32 IntrValue;
82
83         Xil_AssertVoid(InstancePtr != NULL);
84         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
85
86         /*
87          * Write to the IER to enable the specified interrupts.
88          */
89         IntrValue = XCanPs_IntrGetEnabled(InstancePtr);
90         IntrValue |= Mask & XCANPS_IXR_ALL;
91         XCanPs_WriteReg(InstancePtr->CanConfig.BaseAddr,
92                         XCANPS_IER_OFFSET, IntrValue);
93 }
94
95 /****************************************************************************/
96 /**
97 *
98 * This routine disables interrupt(s). Use the XCANPS_IXR_* constants defined in
99 * xcanps_hw.h to create the bit-mask to disable interrupt(s).
100 *
101 * @param        InstancePtr is a pointer to the XCanPs instance.
102 * @param        Mask is the mask to disable. Bit positions of 1 will be
103 *               disabled. Bit positions of 0 will keep the previous setting.
104 *               This mask is formed by OR'ing XCANPS_IXR_* bits defined in
105 *               xcanps_hw.h.
106 *
107 * @return       None.
108 *
109 * @note         None.
110 *
111 *****************************************************************************/
112 void XCanPs_IntrDisable(XCanPs *InstancePtr, u32 Mask)
113 {
114         u32 IntrValue;
115
116         Xil_AssertVoid(InstancePtr != NULL);
117         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
118
119         /*
120          * Write to the IER to disable the specified interrupts.
121          */
122         IntrValue = XCanPs_IntrGetEnabled(InstancePtr);
123         IntrValue &= ~Mask;
124         XCanPs_WriteReg(InstancePtr->CanConfig.BaseAddr,
125                         XCANPS_IER_OFFSET, IntrValue);
126 }
127
128 /****************************************************************************/
129 /**
130 *
131 * This routine returns enabled interrupt(s). Use the XCANPS_IXR_* constants
132 * defined in xcanps_hw.h to interpret the returned value.
133 *
134 * @param        InstancePtr is a pointer to the XCanPs instance.
135 *
136 * @return       Enabled interrupt(s) in a 32-bit format.
137 *
138 * @note         None.
139 *
140 *****************************************************************************/
141 u32 XCanPs_IntrGetEnabled(XCanPs *InstancePtr)
142 {
143
144         Xil_AssertNonvoid(InstancePtr != NULL);
145         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
146
147         return XCanPs_ReadReg(InstancePtr->CanConfig.BaseAddr,
148                                 XCANPS_IER_OFFSET);
149 }
150
151
152 /****************************************************************************/
153 /**
154 *
155 * This routine returns interrupt status read from Interrupt Status Register.
156 * Use the XCANPS_IXR_* constants defined in xcanps_hw.h to interpret the
157 * returned value.
158 *
159 * @param        InstancePtr is a pointer to the XCanPs instance.
160 *
161 * @return       The value stored in Interrupt Status Register.
162 *
163 * @note         None.
164 *
165 *****************************************************************************/
166 u32 XCanPs_IntrGetStatus(XCanPs *InstancePtr)
167 {
168         Xil_AssertNonvoid(InstancePtr != NULL);
169         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
170
171         return XCanPs_ReadReg(InstancePtr->CanConfig.BaseAddr,
172                                 XCANPS_ISR_OFFSET);
173 }
174
175 /****************************************************************************/
176 /**
177 *
178 * This function clears interrupt(s). Every bit set in Interrupt Status
179 * Register indicates that a specific type of interrupt is occurring, and this
180 * function clears one or more interrupts by writing a bit mask to Interrupt
181 * Clear Register.
182 *
183 * @param        InstancePtr is a pointer to the XCanPs instance.
184 * @param        Mask is the mask to clear. Bit positions of 1 will be cleared.
185 *               Bit positions of 0 will not change the previous interrupt
186 *               status. This mask is formed by OR'ing XCANPS_IXR_* bits defined
187 *               in xcanps_hw.h.
188 *
189 * @note         None.
190 *
191 *****************************************************************************/
192 void XCanPs_IntrClear(XCanPs *InstancePtr, u32 Mask)
193 {
194         u32 IntrValue;
195
196         Xil_AssertVoid(InstancePtr != NULL);
197         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
198
199         /*
200          * Clear the currently pending interrupts.
201          */
202         IntrValue = XCanPs_IntrGetStatus(InstancePtr);
203         IntrValue &= Mask;
204         XCanPs_WriteReg(InstancePtr->CanConfig.BaseAddr, XCANPS_ICR_OFFSET,
205                                 IntrValue);
206 }
207
208 /*****************************************************************************/
209 /**
210 *
211 * This routine is the interrupt handler for the CAN driver.
212 *
213 * This handler reads the interrupt status from the ISR, determines the source of
214 * the interrupts, calls according callbacks, and finally clears the interrupts.
215 *
216 * Application beyond this driver is responsible for providing callbacks to
217 * handle interrupts and installing the callbacks using XCanPs_SetHandler()
218 * during initialization phase. An example delivered with this driver
219 * demonstrates how this could be done.
220 *
221 * @param        InstancePtr is a pointer to the XCanPs instance that just
222 *               interrupted.
223 *
224 * @return       None.
225 *
226 * @note         None.
227 *
228 ******************************************************************************/
229 void XCanPs_IntrHandler(void *InstancePtr)
230 {
231         u32 PendingIntr;
232         u32 EventIntr;
233         u32 ErrorStatus;
234         XCanPs *CanPtr = (XCanPs *) InstancePtr;
235
236         Xil_AssertVoid(CanPtr != NULL);
237         Xil_AssertVoid(CanPtr->IsReady == XIL_COMPONENT_IS_READY);
238
239         PendingIntr = XCanPs_IntrGetStatus(CanPtr);
240         PendingIntr &= XCanPs_IntrGetEnabled(CanPtr);
241
242         /*
243          * Clear all pending interrupts.
244          * Rising Edge interrupt
245          */
246         XCanPs_IntrClear(CanPtr, PendingIntr);
247
248         /*
249          * An error interrupt is occurring.
250          */
251         if ((PendingIntr & XCANPS_IXR_ERROR_MASK)) {
252                 ErrorStatus = XCanPs_GetBusErrorStatus(CanPtr);
253                 CanPtr->ErrorHandler(CanPtr->ErrorRef, ErrorStatus);
254
255                 /*
256                  * Clear Error Status Register.
257                  */
258                 XCanPs_ClearBusErrorStatus(CanPtr, ErrorStatus);
259         }
260
261         /*
262          * Check if any following event interrupt is pending:
263          *        - RX FIFO Overflow
264          *        - RX FIFO Underflow
265          *        - TX High Priority Buffer full
266          *        - TX FIFO Full
267          *        - Wake up from sleep mode
268          *        - Enter sleep mode
269          *        - Enter Bus off status
270          *        - Arbitration is lost
271          *
272          * If so, call event callback provided by upper level.
273          */
274         EventIntr = PendingIntr & (XCANPS_IXR_RXOFLW_MASK |
275                                 XCANPS_IXR_RXUFLW_MASK |
276                                 XCANPS_IXR_TXBFLL_MASK |
277                                 XCANPS_IXR_TXFLL_MASK |
278                                 XCANPS_IXR_WKUP_MASK |
279                                 XCANPS_IXR_SLP_MASK |
280                                 XCANPS_IXR_BSOFF_MASK |
281                                 XCANPS_IXR_ARBLST_MASK);
282         if (EventIntr) {
283                 CanPtr->EventHandler(CanPtr->EventRef, EventIntr);
284
285                 if ((EventIntr & XCANPS_IXR_BSOFF_MASK)) {
286                         /*
287                          * Event callback should reset whole device if "Enter
288                          * Bus Off Status" interrupt occurred. All pending
289                          * interrupts are cleared and no further checking and
290                          * handling of other interrupts is needed any more.
291                          */
292                         return;
293                 }
294         }
295
296
297         if ((PendingIntr & (XCANPS_IXR_RXFWMFLL_MASK |
298                         XCANPS_IXR_RXNEMP_MASK))) {
299
300                 /*
301                  * This case happens when
302                  * A number of frames depending on the Rx FIFO Watermark
303                  * threshold are received.
304                  * And  also when frame was received and is sitting in RX FIFO.
305                  *
306                  * XCANPS_IXR_RXOK_MASK is not used because the bit is set
307                  * just once even if there are multiple frames sitting
308                  * in the RX FIFO.
309                  *
310                  * XCANPS_IXR_RXNEMP_MASK is used because the bit can be
311                  * set again and again automatically as long as there is
312                  * at least one frame in RX FIFO.
313                  */
314                 CanPtr->RecvHandler(CanPtr->RecvRef);
315         }
316
317         /*
318          * A frame was transmitted successfully.
319          */
320         if ((PendingIntr & XCANPS_IXR_TXOK_MASK)) {
321                 CanPtr->SendHandler(CanPtr->SendRef);
322         }
323 }
324
325
326 /*****************************************************************************/
327 /**
328 *
329 * This routine installs an asynchronous callback function for the given
330 * HandlerType:
331 *
332 * <pre>
333 * HandlerType                   Callback Function Type
334 * -----------------------       ------------------------
335 * XCANPS_HANDLER_SEND           XCanPs_SendRecvHandler
336 * XCANPS_HANDLER_RECV           XCanPs_SendRecvHandler
337 * XCANPS_HANDLER_ERROR          XCanPs_ErrorHandler
338 * XCANPS_HANDLER_EVENT          XCanPs_EventHandler
339 *
340 * HandlerType                   Invoked by this driver when:
341 * -------------------------------------------------------------------------
342 * XCANPS_HANDLER_SEND           A frame transmitted by a call to
343 *                               XCanPs_Send() has been sent successfully.
344 *
345 * XCANPS_HANDLER_RECV           A frame(s) has been received and is sitting in
346 *                               the RX FIFO.
347 *
348 * XCANPS_HANDLER_ERROR          An error interrupt is occurring.
349 *
350 * XCANPS_HANDLER_EVENT          Any other kind of interrupt is occurring.
351 * </pre>
352 *
353 * @param        InstancePtr is a pointer to the XCanPs instance.
354 * @param        HandlerType specifies which handler is to be attached.
355 * @param        CallBackFunc is the address of the callback function.
356 * @param        CallBackRef is a user data item that will be passed to the
357 *               callback function when it is invoked.
358 *
359 * @return
360 *               - XST_SUCCESS when handler is installed.
361 *               - XST_INVALID_PARAM when HandlerType is invalid.
362 *
363 * @note
364 * Invoking this function for a handler that already has been installed replaces
365 * it with the new handler.
366 *
367 ******************************************************************************/
368 int XCanPs_SetHandler(XCanPs *InstancePtr, u32 HandlerType,
369                         void *CallBackFunc, void *CallBackRef)
370 {
371         Xil_AssertNonvoid(InstancePtr != NULL);
372         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
373
374         switch (HandlerType) {
375         case XCANPS_HANDLER_SEND:
376                 InstancePtr->SendHandler =
377                         (XCanPs_SendRecvHandler) CallBackFunc;
378                 InstancePtr->SendRef = CallBackRef;
379                 break;
380
381         case XCANPS_HANDLER_RECV:
382                 InstancePtr->RecvHandler =
383                         (XCanPs_SendRecvHandler) CallBackFunc;
384                 InstancePtr->RecvRef = CallBackRef;
385                 break;
386
387         case XCANPS_HANDLER_ERROR:
388                 InstancePtr->ErrorHandler = (XCanPs_ErrorHandler) CallBackFunc;
389                 InstancePtr->ErrorRef = CallBackRef;
390                 break;
391
392         case XCANPS_HANDLER_EVENT:
393                 InstancePtr->EventHandler = (XCanPs_EventHandler) CallBackFunc;
394                 InstancePtr->EventRef = CallBackRef;
395                 break;
396
397         default:
398                 return (XST_INVALID_PARAM);
399
400         }
401         return (XST_SUCCESS);
402 }
403