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()的主要内容,如果未能解决你的问题,请参考以下文章