示例#1
0
void  dma_reset(XAxiCdma * dma)
{
   // Perform reset
   XAxiCdma_Reset(dma);

   // Wait for it to complete
   while (!XAxiCdma_ResetIsDone(dma));
}
示例#2
0
/**
 * This function is the interrupt handler for the driver, it handles all the
 * interrupts. For the completion of a transfer that has a callback function,
 * the callback function is called.
 *
 * @param	HandlerRef is a reference pointer passed to the interrupt
 *			registration function. It will be a pointer to the driver
 *			instance we are working on
 *
 * @return	None
 *
 * @note	If one transfer does not have all its submitted BDs completed
 *		successfully,then a reset is needed to clean up the mess left
 *		by that transfer.Otherwise, the wrong interrupt callback maybe
 *		called for the following transfers. However, if you always use
 *		the same interrupt callback for all the transfers, and you are
 *		the only user of the DMA engine, then you do not have to worry
 *		about this.
 *****************************************************************************/
void XAxiCdma_IntrHandler(void *HandlerRef)
{
	XAxiCdma *InstancePtr;
	u32 Status;
	u32 Irq;
	u32 Error = 0x0;

	InstancePtr = (XAxiCdma *)HandlerRef;
	Status = XAxiCdma_ReadReg(InstancePtr->BaseAddr, XAXICDMA_SR_OFFSET);

	/* Check what interrupts have fired
	 */
	Irq = Status & XAXICDMA_XR_IRQ_ALL_MASK;

	if (Irq == 0x0) {
		xdbg_printf(XDBG_DEBUG_ERROR, "No interrupt for intr handler\r\n");
		return;
	}

	/* Acknowledge the interrupt
	 */
	XAxiCdma_WriteReg(InstancePtr->BaseAddr, XAXICDMA_SR_OFFSET, Irq);

	/* Pass the interrupt and error status to the callback function
	 * if the transfer has one
	 */

	/* If SimpleNotDone flag is set, then it is a simple transfer
	 */
	if (InstancePtr->SimpleNotDone) {
		if (InstancePtr->SimpleCallBackFn) {
			(InstancePtr->SimpleCallBackFn)(
			    InstancePtr->SimpleCallBackRef, Irq, NULL);

			InstancePtr->SimpleCallBackFn = NULL;
		}

		InstancePtr->SimpleNotDone = 0;

		if (InstancePtr->SGWaiting) {
			XAxiCdma_BdRingStartTransfer(InstancePtr);
		}
	}
	else {	/* SG transfer */
		if (InstancePtr->SgHandlerHead != InstancePtr->SgHandlerTail) {
			int Tmp;

			XAxiCdma_IntrHandlerList Handler =
			    InstancePtr->Handlers[InstancePtr->SgHandlerHead];

			Tmp = Handler.NumBds;

			/* Caution: may have race condition here
			 *
			 * If an interrupt for another transfer happens
			 * while in callback function, then the wrong callback
			 * function may be called.
			 */
			Handler.CallBackFn(Handler.CallBackRef, Irq, &(Tmp));

			InstancePtr->Handlers[InstancePtr->SgHandlerHead].NumBds = Tmp;

			/* Update the handler head if this transfer is done
			 */
			if (Tmp == 0) {
				Tmp = InstancePtr->SgHandlerHead + 1;

				if (Tmp == XAXICDMA_MAXIMUM_MAX_HANDLER) {
					Tmp	= 0;
				}

				InstancePtr->SgHandlerHead = Tmp;
			}
		}
		else {
			xdbg_printf(XDBG_DEBUG_ERROR,
			    "ERROR: SG transfer intr without handler\r\n");
		}
	}

	/* If has error interrupt, hardware needs to be reset
	 */
	Error = Status & XAXICDMA_SR_ERR_ALL_MASK;
	if ((Irq & XAXICDMA_XR_IRQ_ERROR_MASK) && Error) {
		int TimeOut;


		TimeOut = XAXICDMA_RESET_LOOP_LIMIT;

		/* Need to reset the hardware to clear the errors
		 */
		XAxiCdma_Reset(InstancePtr);

		while (TimeOut) {

			if (XAxiCdma_ResetIsDone(InstancePtr)) {
				break;
			}

			TimeOut -= 1;
		}

		/* Reset failed
		 */
		if (!TimeOut) {
			/* Mark the driver/engine is not in working state
			 */
			InstancePtr->Initialized = 0;
		}

		/* In case of error, no further handling is needed
		 *
		 * User should check send/receive buffers to see what happened
		 * as well as check the DMA engine registers
		 */
		return;
 	}

	return;
}
示例#3
0
/**
 * This function initializes the driver. It should be called before any other
 * function calls to the driver.
 *
 * It sets up the driver according to the hardware build. It resets the
 * hardware at the end.
 *
 * @param	InstancePtr is the driver instance that is working on
 * @param	CfgPtr is the pointer to the hardware configuration structure
 * @param	EffectiveAddr is the virtual address of the hardware instance.
 *		If address translation is not in use, please use the physical
 *		address
 *
 * @return
 *		- XST_SUCCESS for success
 *		- XST_INVALID_PARAM if word length is less than 4
 *		- XST_FAILURE for reset failure
 *
 * @note	None.
 *
 *****************************************************************************/
u32 XAxiCdma_CfgInitialize(XAxiCdma *InstancePtr, XAxiCdma_Config *CfgPtr,
		u32 EffectiveAddr)
{
	u32 RegValue;
	int TimeOut;

	/* Mark the driver is not in working state yet
	 */
	InstancePtr->Initialized = 0;

	InstancePtr->BaseAddr = EffectiveAddr;
	InstancePtr->HasDRE = CfgPtr->HasDRE;
	InstancePtr->IsLite = CfgPtr->IsLite;
	InstancePtr->WordLength = ((unsigned int)CfgPtr->DataWidth) >> 3;
	InstancePtr->AddrWidth = CfgPtr->AddrWidth;

	/* AXI CDMA supports 32 bits data width and up
	 */
	if (InstancePtr->WordLength < 4) {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Word length too short %d\r\n", InstancePtr->WordLength);

		return XST_INVALID_PARAM;
	}

	RegValue = XAxiCdma_ReadReg(CfgPtr->BaseAddress, XAXICDMA_SR_OFFSET);

	InstancePtr->SimpleOnlyBuild = !(RegValue & XAXICDMA_SR_SGINCLD_MASK);

	/* Lite mode only supports data_width * burst_len
	 *
	 * Lite mode is ignored if SG mode is selected
	 */
	if (InstancePtr->SimpleOnlyBuild && CfgPtr->IsLite) {
		InstancePtr->MaxTransLen = InstancePtr->WordLength *
		      CfgPtr->BurstLen;
	}
	else {
		InstancePtr->MaxTransLen = XAXICDMA_MAX_TRANSFER_LEN;
	}

	TimeOut = XAXICDMA_RESET_LOOP_LIMIT;

	/* Reset the hardware
	 */
	XAxiCdma_Reset(InstancePtr);

	/* The hardware should be pretty quick on reset, the reset is only
	 * slow if there is an active large transfer
	 */
	while (TimeOut) {

		if (XAxiCdma_ResetIsDone(InstancePtr)) {
			break;
		}

		TimeOut -= 1;
	}

	if (!TimeOut) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Reset failed\r\n");

		return XST_FAILURE;
	}

	/* Initialize the BD ring statistics, to prevent BD ring being used
	 * before being created
	 */
	InstancePtr->AllBdCnt = 0;
	InstancePtr->FreeBdCnt = 0;
	InstancePtr->HwBdCnt = 0;
	InstancePtr->PreBdCnt = 0;
	InstancePtr->PostBdCnt = 0;

	/* Mark that the driver/engine is in working state now
	 */
	InstancePtr->Initialized = 1;

	return XST_SUCCESS;
}
/**
* The example to do the scatter gather transfer through polling.
*
* @param	DeviceId is the Device Id of the XAxiCdma instance
*
* @return
* 		- XST_SUCCESS if example finishes successfully
* 		- XST_FAILURE if error occurs
*
* @note		None
*
******************************************************************************/
int XAxiCdma_SgPollExample(u16 DeviceId)
{
	XAxiCdma_Config *CfgPtr;
	int Status;
	u8 *SrcPtr;
	u8 *DstPtr;

	SrcPtr = (u8 *)TransmitBufferPtr;
	DstPtr = (u8 *)ReceiveBufferPtr;

#ifdef __aarch64__
	Xil_SetTlbAttributes(BD_SPACE_BASE, MARK_UNCACHEABLE);
#endif

	/* Initialize the XAxiCdma device.
	 */
	CfgPtr = XAxiCdma_LookupConfig(DeviceId);
	if (!CfgPtr) {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Cannot find config structure for device %d\r\n",
			XPAR_AXICDMA_0_DEVICE_ID);

		return XST_FAILURE;
	}

	Status = XAxiCdma_CfgInitialize(&AxiCdmaInstance, CfgPtr,
		CfgPtr->BaseAddress);
	if (Status != XST_SUCCESS) {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Initialization failed with %d\r\n", Status);

		return XST_FAILURE;
	}

	/* Setup the BD ring
	 */
	Status = SetupTransfer(&AxiCdmaInstance);
	if (Status != XST_SUCCESS) {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Setup BD ring failed with %d\r\n", Status);

		return XST_FAILURE;
	}

	Done = 0;
	Error = 0;

	/* Start the DMA transfer
	 */
	Status = DoTransfer(&AxiCdmaInstance);
	if (Status != XST_SUCCESS) {
		xdbg_printf(XDBG_DEBUG_ERROR,
		    "Do transfer failed with %d\r\n", Status);

		return XST_FAILURE;
	}

	/* Wait until the DMA transfer is done or error occurs
	 */
	while ((CheckCompletion(&AxiCdmaInstance) < NUMBER_OF_BDS_TO_TRANSFER)
		&& !Error) {
		/* Wait */
	}

	if(Error) {
		int TimeOut = RESET_LOOP_COUNT;

		xdbg_printf(XDBG_DEBUG_ERROR, "Transfer has error %x\r\n",
				Error);

		/* Need to reset the hardware to restore to the correct state
		 */
		XAxiCdma_Reset(&AxiCdmaInstance);

		while (TimeOut) {
			if (XAxiCdma_ResetIsDone(&AxiCdmaInstance)) {
				break;
			}
			TimeOut -= 1;
		}

		/* Reset has failed, print a message to notify the user
		 */
		if (!TimeOut) {
			xdbg_printf(XDBG_DEBUG_ERROR,
			    "Reset hardware failed with %d\r\n", Status);

		}

		return XST_FAILURE;
	}

	/* Transfer completed successfully, check data
	 */
	Status = CheckData(SrcPtr, DstPtr,
		MAX_PKT_LEN * NUMBER_OF_BDS_TO_TRANSFER);
	if (Status != XST_SUCCESS) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Check data failed for sg "
		    "transfer\r\n");
		return XST_FAILURE;
	}

	/* Test finishes successfully, return successfully
	 */
	return XST_SUCCESS;
}
/*
* This function does one simple transfer in polled mode
*
* @param	InstancePtr is a pointer to the XAxiCdma instance
* @param	Length is the transfer length
* @param	Retries is how many times to retry on submission
*
* @return
*		- XST_SUCCESS if transfer is successful
*		- XST_FAILURE if either the transfer fails or the data has
*		  error
*
* @note		None
*
******************************************************************************/
static int DoSimplePollTransfer(XAxiCdma *InstancePtr, int Length, int Retries)
{
	int Index;
	u8  *SrcPtr;
	u8  *DestPtr;
	int Status;

	/* Initialize the source buffer bytes with a pattern and the
	 * the destination buffer bytes to zero
	 */
	SrcPtr = (u8 *)SrcBuffer;
	DestPtr = (u8 *)DestBuffer;
	for (Index = 0; Index < BUFFER_BYTESIZE; Index++) {
		SrcPtr[Index] = Index & 0xFF;
		DestPtr[Index] = 0;
	}

	/* Flush the SrcBuffer before the DMA transfer, in case the Data Cache
	 * is enabled
	 */
	Xil_DCacheFlushRange((u32)&SrcBuffer, Length);

	/* Try to start the DMA transfer
	 */
	while (Retries) {
		Retries -= 1;

		Status = XAxiCdma_SimpleTransfer(InstancePtr, (u32)SrcBuffer,
			(u32)DestBuffer, Length, NULL, NULL);
		if (Status == XST_SUCCESS) {
			break;
		}
	}

	/* Return failure if failed to submit the transfer
	 */
	if (!Retries) {
		return XST_FAILURE;
	}

	/* Wait until the DMA transfer is done
	 */
	while (XAxiCdma_IsBusy(InstancePtr)) {
		/* Wait */
	}

	/* If the hardware has errors, this example fails
	 * This is a poll example, no interrupt handler is involved.
	 * Therefore, error conditions are not cleared by the driver.
	 */
	Error = XAxiCdma_GetError(InstancePtr);
	if (Error != 0x0) {
		int TimeOut = RESET_LOOP_COUNT;

		/* Need to reset the hardware to restore to the correct state
		 */
		XAxiCdma_Reset(InstancePtr);

		while (TimeOut) {
			if (XAxiCdma_ResetIsDone(InstancePtr)) {
				break;
			}
			TimeOut -= 1;
		}

		/* Reset has failed, print a message to notify the user
		 */
		return XST_FAILURE;
	}

	/* Transfer completes successfully, check data
	 */
	Status = CheckData(SrcPtr, DestPtr, Length);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}