/** * * This function clears interrupt(s). Every bit set in Interrupt Status * Register indicates that a specific type of interrupt is occurring, and this * function clears one or more interrupts by writing a bit mask to Interrupt * Clear Register. * * @param InstancePtr is a pointer to the XCanPs instance. * @param Mask is the mask to clear. Bit positions of 1 will be cleared. * Bit positions of 0 will not change the previous interrupt * status. This mask is formed by OR'ing XCANPS_IXR_* bits defined * in xcanps_hw.h. * * @note None. * *****************************************************************************/ void XCanPs_IntrClear(XCanPs *InstancePtr, u32 Mask) { u32 IntrValue; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Clear the currently pending interrupts. */ IntrValue = XCanPs_IntrGetStatus(InstancePtr); IntrValue &= Mask; XCanPs_WriteReg(InstancePtr->CanConfig.BaseAddr, XCANPS_ICR_OFFSET, IntrValue); }
/** * * 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 XCanPs_SetHandler() * during initialization phase. An example delivered with this driver * demonstrates how this could be done. * * @param InstancePtr is a pointer to the XCanPs instance that just * interrupted. * * @return None. * * @note None. * ******************************************************************************/ void XCanPs_IntrHandler(void *InstancePtr) { u32 PendingIntr; u32 EventIntr; u32 ErrorStatus; XCanPs *CanPtr = (XCanPs *) InstancePtr; Xil_AssertVoid(CanPtr != NULL); Xil_AssertVoid(CanPtr->IsReady == XIL_COMPONENT_IS_READY); PendingIntr = XCanPs_IntrGetStatus(CanPtr); PendingIntr &= XCanPs_IntrGetEnabled(CanPtr); /* * Clear all pending interrupts. * Rising Edge interrupt */ XCanPs_IntrClear(CanPtr, PendingIntr); /* * An error interrupt is occurring. */ if ((PendingIntr & XCANPS_IXR_ERROR_MASK)) { ErrorStatus = XCanPs_GetBusErrorStatus(CanPtr); CanPtr->ErrorHandler(CanPtr->ErrorRef, ErrorStatus); /* * Clear Error Status Register. */ XCanPs_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 & (XCANPS_IXR_RXOFLW_MASK | XCANPS_IXR_RXUFLW_MASK | XCANPS_IXR_TXBFLL_MASK | XCANPS_IXR_TXFLL_MASK | XCANPS_IXR_WKUP_MASK | XCANPS_IXR_SLP_MASK | XCANPS_IXR_BSOFF_MASK | XCANPS_IXR_ARBLST_MASK); if (EventIntr) { CanPtr->EventHandler(CanPtr->EventRef, EventIntr); if ((EventIntr & XCANPS_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; } } if ((PendingIntr & (XCANPS_IXR_RXFWMFLL_MASK | XCANPS_IXR_RXNEMP_MASK))) { /* * This case happens when * A number of frames depending on the Rx FIFO Watermark * threshold are received. * And also when frame was received and is sitting in RX FIFO. * * XCANPS_IXR_RXOK_MASK is not used because the bit is set * just once even if there are multiple frames sitting * in the RX FIFO. * * XCANPS_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. */ CanPtr->RecvHandler(CanPtr->RecvRef); } /* * A frame was transmitted successfully. */ if ((PendingIntr & XCANPS_IXR_TXOK_MASK)) { CanPtr->SendHandler(CanPtr->SendRef); } }
/** * * Read the Received CAN frames from the FIFO. * * @param InstancePtr is a pointer to the driver instance. * * @return * - XST_SUCCESS if all the CAN Frames are received and the * data is the same as that was sent. * - XST_FAILURE if the required number of CAN frames have not * been received or if the Received Data is not the same as the * data that was sent. * * @note None. * ******************************************************************************/ static int ReceiveData(XCanPs *InstancePtr) { int Status; int Index; u8 *FramePtr; u8 NumRxFrames; /* * Initialize the number of received frames to Zero. */ NumRxFrames = 0; /* * Read the received CAN Frames from the FIFO till the FIFO is Empty. */ while (XCanPs_IntrGetStatus(InstancePtr) & XCANPS_IXR_RXNEMP_MASK) { Status = XCanPs_Recv(InstancePtr, RxFrame); if (Status != XST_SUCCESS) { LoopbackError = TRUE; return XST_FAILURE; } /* * Verify Identifier and Data Length Code. */ if (RxFrame[0] != (u32)XCanPs_CreateIdValue((u32)TEST_MESSAGE_ID, 0, 0, 0, 0)) { LoopbackError = TRUE; return XST_FAILURE; } if ((RxFrame[1] & ~XCANPS_DLCR_TIMESTAMP_MASK) != TxFrame[1]) { LoopbackError = TRUE; return XST_FAILURE; } /* * Verify Data field contents. */ FramePtr = (u8 *)(&RxFrame[2]); for (Index = 0; Index < FRAME_DATA_LENGTH; Index++) { if (*FramePtr++ != ((u8)Index + TestDataOffset)) { LoopbackError = TRUE; return XST_FAILURE; } } /* * Increment the number of frames received. */ TestDataOffset++; NumRxFrames++; } if (NumRxFrames == TEST_THRESHOLD) { LoopbackError = FALSE; return XST_SUCCESS; } return XST_FAILURE; }