1 /******************************************************************************
3 * Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
31 ******************************************************************************/
32 /*****************************************************************************/
37 * This file contains functions related to CAN interrupt handling.
40 * MODIFICATION HISTORY:
42 * Ver Who Date Changes
43 * ----- ----- -------- -----------------------------------------------
44 * 1.00a xd/sv 01/12/10 First release
47 ******************************************************************************/
49 /***************************** Include Files *********************************/
53 /************************** Constant Definitions *****************************/
55 /**************************** Type Definitions *******************************/
57 /***************** Macros (Inline Functions) Definitions *********************/
59 /************************** Variable Definitions *****************************/
61 /************************** Function Prototypes ******************************/
63 /****************************************************************************/
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.
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.
78 *****************************************************************************/
79 void XCanPs_IntrEnable(XCanPs *InstancePtr, u32 Mask)
83 Xil_AssertVoid(InstancePtr != NULL);
84 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
87 * Write to the IER to enable the specified interrupts.
89 IntrValue = XCanPs_IntrGetEnabled(InstancePtr);
90 IntrValue |= Mask & XCANPS_IXR_ALL;
91 XCanPs_WriteReg(InstancePtr->CanConfig.BaseAddr,
92 XCANPS_IER_OFFSET, IntrValue);
95 /****************************************************************************/
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).
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
111 *****************************************************************************/
112 void XCanPs_IntrDisable(XCanPs *InstancePtr, u32 Mask)
116 Xil_AssertVoid(InstancePtr != NULL);
117 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
120 * Write to the IER to disable the specified interrupts.
122 IntrValue = XCanPs_IntrGetEnabled(InstancePtr);
124 XCanPs_WriteReg(InstancePtr->CanConfig.BaseAddr,
125 XCANPS_IER_OFFSET, IntrValue);
128 /****************************************************************************/
131 * This routine returns enabled interrupt(s). Use the XCANPS_IXR_* constants
132 * defined in xcanps_hw.h to interpret the returned value.
134 * @param InstancePtr is a pointer to the XCanPs instance.
136 * @return Enabled interrupt(s) in a 32-bit format.
140 *****************************************************************************/
141 u32 XCanPs_IntrGetEnabled(XCanPs *InstancePtr)
144 Xil_AssertNonvoid(InstancePtr != NULL);
145 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
147 return XCanPs_ReadReg(InstancePtr->CanConfig.BaseAddr,
152 /****************************************************************************/
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
159 * @param InstancePtr is a pointer to the XCanPs instance.
161 * @return The value stored in Interrupt Status Register.
165 *****************************************************************************/
166 u32 XCanPs_IntrGetStatus(XCanPs *InstancePtr)
168 Xil_AssertNonvoid(InstancePtr != NULL);
169 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
171 return XCanPs_ReadReg(InstancePtr->CanConfig.BaseAddr,
175 /****************************************************************************/
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
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
191 *****************************************************************************/
192 void XCanPs_IntrClear(XCanPs *InstancePtr, u32 Mask)
196 Xil_AssertVoid(InstancePtr != NULL);
197 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
200 * Clear the currently pending interrupts.
202 IntrValue = XCanPs_IntrGetStatus(InstancePtr);
204 XCanPs_WriteReg(InstancePtr->CanConfig.BaseAddr, XCANPS_ICR_OFFSET,
208 /*****************************************************************************/
211 * This routine is the interrupt handler for the CAN driver.
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.
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.
221 * @param InstancePtr is a pointer to the XCanPs instance that just
228 ******************************************************************************/
229 void XCanPs_IntrHandler(void *InstancePtr)
234 XCanPs *CanPtr = (XCanPs *) InstancePtr;
236 Xil_AssertVoid(CanPtr != NULL);
237 Xil_AssertVoid(CanPtr->IsReady == XIL_COMPONENT_IS_READY);
239 PendingIntr = XCanPs_IntrGetStatus(CanPtr);
240 PendingIntr &= XCanPs_IntrGetEnabled(CanPtr);
243 * Clear all pending interrupts.
244 * Rising Edge interrupt
246 XCanPs_IntrClear(CanPtr, PendingIntr);
249 * An error interrupt is occurring.
251 if ((PendingIntr & XCANPS_IXR_ERROR_MASK)) {
252 ErrorStatus = XCanPs_GetBusErrorStatus(CanPtr);
253 CanPtr->ErrorHandler(CanPtr->ErrorRef, ErrorStatus);
256 * Clear Error Status Register.
258 XCanPs_ClearBusErrorStatus(CanPtr, ErrorStatus);
262 * Check if any following event interrupt is pending:
264 * - RX FIFO Underflow
265 * - TX High Priority Buffer full
267 * - Wake up from sleep mode
269 * - Enter Bus off status
270 * - Arbitration is lost
272 * If so, call event callback provided by upper level.
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);
283 CanPtr->EventHandler(CanPtr->EventRef, EventIntr);
285 if ((EventIntr & XCANPS_IXR_BSOFF_MASK)) {
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.
297 if ((PendingIntr & (XCANPS_IXR_RXFWMFLL_MASK |
298 XCANPS_IXR_RXNEMP_MASK))) {
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.
306 * XCANPS_IXR_RXOK_MASK is not used because the bit is set
307 * just once even if there are multiple frames sitting
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.
314 CanPtr->RecvHandler(CanPtr->RecvRef);
318 * A frame was transmitted successfully.
320 if ((PendingIntr & XCANPS_IXR_TXOK_MASK)) {
321 CanPtr->SendHandler(CanPtr->SendRef);
326 /*****************************************************************************/
329 * This routine installs an asynchronous callback function for the given
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
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.
345 * XCANPS_HANDLER_RECV A frame(s) has been received and is sitting in
348 * XCANPS_HANDLER_ERROR An error interrupt is occurring.
350 * XCANPS_HANDLER_EVENT Any other kind of interrupt is occurring.
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.
360 * - XST_SUCCESS when handler is installed.
361 * - XST_INVALID_PARAM when HandlerType is invalid.
364 * Invoking this function for a handler that already has been installed replaces
365 * it with the new handler.
367 ******************************************************************************/
368 int XCanPs_SetHandler(XCanPs *InstancePtr, u32 HandlerType,
369 void *CallBackFunc, void *CallBackRef)
371 Xil_AssertNonvoid(InstancePtr != NULL);
372 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
374 switch (HandlerType) {
375 case XCANPS_HANDLER_SEND:
376 InstancePtr->SendHandler =
377 (XCanPs_SendRecvHandler) CallBackFunc;
378 InstancePtr->SendRef = CallBackRef;
381 case XCANPS_HANDLER_RECV:
382 InstancePtr->RecvHandler =
383 (XCanPs_SendRecvHandler) CallBackFunc;
384 InstancePtr->RecvRef = CallBackRef;
387 case XCANPS_HANDLER_ERROR:
388 InstancePtr->ErrorHandler = (XCanPs_ErrorHandler) CallBackFunc;
389 InstancePtr->ErrorRef = CallBackRef;
392 case XCANPS_HANDLER_EVENT:
393 InstancePtr->EventHandler = (XCanPs_EventHandler) CallBackFunc;
394 InstancePtr->EventRef = CallBackRef;
398 return (XST_INVALID_PARAM);
401 return (XST_SUCCESS);