/** * * This function receives a CAN Frame. This function first checks if RX FIFO is * empty, if not, it then reads a frame from the RX FIFO into the given buffer. * This function returns error code immediately if there is no frame in the RX * FIFO. * * @param InstancePtr is a pointer to the XCan instance to be worked on. * @param FramePtr is a pointer to a 32-bit aligned buffer where the CAN * frame to be written. * * @return * - XST_SUCCESS if RX FIFO was not empty and a frame was read from * RX FIFO successfully and written into the given buffer; * - XST_NO_DATA if there is no frame to be received from the FIFO * * @note None. * ******************************************************************************/ int XCan_Recv(XCan *InstancePtr, u32 *FramePtr) { Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Check if RX FIFO has frame(s) sitting in it. If not, return error * code */ if (XCan_IsRxEmpty(InstancePtr) == TRUE) { return XST_NO_DATA; } /* Read IDR */ FramePtr[0] = XCan_ReadReg(InstancePtr->BaseAddress, XCAN_RXFIFO_ID_OFFSET); /* Read DLC */ FramePtr[1] = XCan_ReadReg(InstancePtr->BaseAddress, XCAN_RXFIFO_DLC_OFFSET); /* Read Data Word 1 */ FramePtr[2] = XCan_ReadReg(InstancePtr->BaseAddress, XCAN_RXFIFO_DW1_OFFSET); /* Read Data Word 2 */ FramePtr[3] = XCan_ReadReg(InstancePtr->BaseAddress, XCAN_RXFIFO_DW2_OFFSET); /* * Clear RXNEMP bit in ISR. This allows future XCan_IsRxEmpty() call * returns correct RX FIFO occupancy/empty condition. */ XCan_InterruptClear(InstancePtr, XCAN_IXR_RXNEMP_MASK); return XST_SUCCESS; }
/** * * This routine is the interrupt handler for the CAN driver. * * This handler reads the interrupt status from the ISR, determines the source of * the interrupts, calls according callbacks, and finally clears the interrupts. * * Application beyond this driver is responsible for providing callbacks to * handle interrupts and installing the callbacks using XCan_SetHandler() during * initialization phase. An example delivered with this driver demonstrates how * this could be done. * * @param InstancePtr is a pointer to the XCan instance that just * interrupted. * * @return None. * * @note None. * ******************************************************************************/ void XCan_IntrHandler(void *InstancePtr) { u32 PendingIntr, EventIntr, ErrorStatus; XCan *CanPtr = (XCan *) InstancePtr; Xil_AssertVoid(CanPtr != NULL); Xil_AssertVoid(CanPtr->IsReady == XIL_COMPONENT_IS_READY); /* * Get pending interrupts */ PendingIntr = XCan_InterruptGetStatus(CanPtr); PendingIntr &= XCan_InterruptGetEnabled(CanPtr); /* * An error interrupt is occurring */ if ((PendingIntr & XCAN_IXR_ERROR_MASK)) { ErrorStatus = XCan_GetBusErrorStatus(CanPtr); CanPtr->ErrorHandler(CanPtr->ErrorRef, ErrorStatus); /* Clear Error Status Register */ XCan_ClearBusErrorStatus(CanPtr, ErrorStatus); } /* * Check if any following event interrupt is pending: * - RX FIFO Overflow * - RX FIFO Underflow * - TX High Priority Buffer full * - TX FIFO Full * - Wake up from sleep mode * - Enter sleep mode * - Enter Bus off status * - Arbitration is lost * * If so, call event callback provided by upper level. */ EventIntr = PendingIntr & (XCAN_IXR_RXOFLW_MASK | XCAN_IXR_RXUFLW_MASK | XCAN_IXR_TXBFLL_MASK | XCAN_IXR_TXFLL_MASK | XCAN_IXR_WKUP_MASK | XCAN_IXR_SLP_MASK | XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK); if (EventIntr) { CanPtr->EventHandler(CanPtr->EventRef, EventIntr); if ((EventIntr & XCAN_IXR_BSOFF_MASK)) { /* * Event callback should reset whole device if "Enter * Bus Off Status" interrupt occurred. All pending * interrupts are cleared and no further checking and * handling of other interrupts is needed any more. */ return; } } /* * A frame was received and is sitting in RX FIFO. * * XCAN_IXR_RXOK_MASK is not used because the bit is set just once * even if there are multiple frames sitting in RX FIFO. * * XCAN_IXR_RXNEMP_MASK is used because the bit can be set again and * again automatically as long as there is at least one frame in RX * FIFO. */ if ((PendingIntr & XCAN_IXR_RXNEMP_MASK)) { CanPtr->RecvHandler(CanPtr->RecvRef); } /* * A frame was transmitted successfully */ if ((PendingIntr & XCAN_IXR_TXOK_MASK)) { CanPtr->SendHandler(CanPtr->SendRef); } /* Clear all pending interrupts */ XCan_InterruptClear(CanPtr, PendingIntr); }