/**
*
* 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;
}