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