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