Beispiel #1
0
/**
*
* 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;
}
Beispiel #2
0
/**
*
* 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);
}