AXI DMA用于传输的函数XAxiDma_SimpleTransfer()

Posted 只是有点小怂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AXI DMA用于传输的函数XAxiDma_SimpleTransfer()相关的知识,希望对你有一定的参考价值。

/*****************************************************************************/
/**
 * This function does one simple transfer submission
 *
 * It checks in the following sequence:
 *	- if engine is busy, cannot submit
 *	- if engine is in SG mode , cannot submit
 *
 * @param	InstancePtr is the pointer to the driver instance
 * @param	BuffAddr is the address of the source/destination buffer
 * @param	Length is the length of the transfer
 * @param	Direction is DMA transfer direction, valid values are
 *			- XAXIDMA_DMA_TO_DEVICE.
 *			- XAXIDMA_DEVICE_TO_DMA.

 * @return
 *		- XST_SUCCESS for success of submission
 *		- XST_FAILURE for submission failure, maybe caused by:
 *		Another simple transfer is still going
 *		- XST_INVALID_PARAM if:Length out of valid range [1:8M]
 *		Or, address not aligned when DRE is not built in
 *
 * @note	This function is used only when system is configured as
 *		Simple mode.
 *
 *****************************************************************************/
u32 XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, UINTPTR BuffAddr, u32 Length,
	int Direction)
{
	u32 WordBits;
	int RingIndex = 0;

	/* If Scatter Gather is included then, cannot submit
	 */
	if (XAxiDma_HasSg(InstancePtr)) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Simple DMA mode is not"
							" supported\\r\\n");

		return XST_FAILURE;
	}

	if(Direction == XAXIDMA_DMA_TO_DEVICE){
		if ((Length < 1) ||
			(Length > InstancePtr->TxBdRing.MaxTransferLen)) {
			return XST_INVALID_PARAM;
		}

		if (!InstancePtr->HasMm2S) {
			xdbg_printf(XDBG_DEBUG_ERROR, "MM2S channel is not"
							"supported\\r\\n");

			return XST_FAILURE;
		}

		/* If the engine is doing transfer, cannot submit
		 */

		if(!(XAxiDma_ReadReg(InstancePtr->TxBdRing.ChanBase,
				XAXIDMA_SR_OFFSET) & XAXIDMA_HALTED_MASK)) {
			if (XAxiDma_Busy(InstancePtr,Direction)) {
				xdbg_printf(XDBG_DEBUG_ERROR,
							"Engine is busy\\r\\n");
				return XST_FAILURE;
			}
		}

		if (!InstancePtr->MicroDmaMode) {
			WordBits = (u32)((InstancePtr->TxBdRing.DataWidth) - 1);
		}
		else {
			WordBits = XAXIDMA_MICROMODE_MIN_BUF_ALIGN;
		}

		if ((BuffAddr & WordBits)) {

			if (!InstancePtr->TxBdRing.HasDRE) {
				xdbg_printf(XDBG_DEBUG_ERROR,
					"Unaligned transfer without"
					" DRE %x\\r\\n",(unsigned int)BuffAddr);

				return XST_INVALID_PARAM;
			}
		}


		XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase,
				 XAXIDMA_SRCADDR_OFFSET, LOWER_32_BITS(BuffAddr));
		if (InstancePtr->AddrWidth > 32)
			XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase,
					 XAXIDMA_SRCADDR_MSB_OFFSET,
					 UPPER_32_BITS(BuffAddr));

		XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase,
				XAXIDMA_CR_OFFSET,
				XAxiDma_ReadReg(
				InstancePtr->TxBdRing.ChanBase,
				XAXIDMA_CR_OFFSET)| XAXIDMA_CR_RUNSTOP_MASK);

		/* Writing to the BTT register starts the transfer
		 */
		XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase,
					XAXIDMA_BUFFLEN_OFFSET, Length);
	}
	else if(Direction == XAXIDMA_DEVICE_TO_DMA){
		if ((Length < 1) ||
			(Length >
			InstancePtr->RxBdRing[RingIndex].MaxTransferLen)) {
			return XST_INVALID_PARAM;
		}


		if (!InstancePtr->HasS2Mm) {
			xdbg_printf(XDBG_DEBUG_ERROR, "S2MM channel is not"
							" supported\\r\\n");

			return XST_FAILURE;
		}

		if(!(XAxiDma_ReadReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
				XAXIDMA_SR_OFFSET) & XAXIDMA_HALTED_MASK)) {
			if (XAxiDma_Busy(InstancePtr,Direction)) {
				xdbg_printf(XDBG_DEBUG_ERROR,
							"Engine is busy\\r\\n");
				return XST_FAILURE;
			}
		}

		if (!InstancePtr->MicroDmaMode) {
			WordBits =
			 (u32)((InstancePtr->RxBdRing[RingIndex].DataWidth) - 1);
		}
		else {
			WordBits = XAXIDMA_MICROMODE_MIN_BUF_ALIGN;
		}

		if ((BuffAddr & WordBits)) {

			if (!InstancePtr->RxBdRing[RingIndex].HasDRE) {
				xdbg_printf(XDBG_DEBUG_ERROR,
					"Unaligned transfer without"
				" DRE %x\\r\\n", (unsigned int)BuffAddr);

				return XST_INVALID_PARAM;
			}
		}


		XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
				 XAXIDMA_DESTADDR_OFFSET, LOWER_32_BITS(BuffAddr));
		if (InstancePtr->AddrWidth > 32)
			XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
					 XAXIDMA_DESTADDR_MSB_OFFSET,
					 UPPER_32_BITS(BuffAddr));

		XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
				XAXIDMA_CR_OFFSET,
			XAxiDma_ReadReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
			XAXIDMA_CR_OFFSET)| XAXIDMA_CR_RUNSTOP_MASK);
		/* Writing to the BTT register starts the transfer
		 */
		XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
					XAXIDMA_BUFFLEN_OFFSET, Length);

	}

	return XST_SUCCESS;
}

以上是关于AXI DMA用于传输的函数XAxiDma_SimpleTransfer()的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Linux 访问 Xilinx Axi DMA?

axisarm接口时序

ARM DMA Controller PL330 使用经验分享

AXI协议:AXI协议的burst机制

AXI协议:AXI协议的burst机制

AXI协议:AXI协议的burst机制