小弟最近在做pcie dma传输的程序,现在碰到一个很奇怪的问题。程序要实现对dma传输
12m的数据。程序轮训传输12m数据,但程序传输了几次12m数据后,dma传输函数会返回ApiDmaInProgress dma。
程序:
int Dma(PLX_DEVICE_OBJECT *pDevice, char *pUserBuffer, int UserBufferLen, int wr_addr)
{
U8 DmaChannel;
U16 ChannelInput;
PLX_STATUS rc;
PLX_DMA_PROP DmaProp;
PLX_DMA_PARAMS DmaParams;
PLX_PHYSICAL_MEM PciBuffer;
int count = 0;
int len = 0;
int cpld_idea = 0;
int data_value = 0;
int dma_count = 0;
int retry_times = 0;
int ret = 0;
char *buffer = NULL;
int j = 0;
int offset = 0;
ChannelInput = 0;
DmaChannel = (U8)ChannelInput;
buffer = (char *)malloc(4096);
if(buffer == NULL)
{
Cons_printf("xbuffer malloc memory err\n");
return ERR_MALLOC_MEM_ERR;
}
count = UserBufferLen / 4096;
offset = UserBufferLen % 4096;
// Get DMA buffer parameters
//ret = Read_Cpld_Idea(pDevice, &cpld_idea);
rc = PlxPci_DeviceReset(pDevice);
if (rc != ApiSuccess)
{
Cons_printf("*ERROR* - API failed to reset\n");
ret = ERR_OPEN_DMA_FAIL;
}
//cpld_idea = 0;
//ret = Read_Cpld_Idea(pDevice, &cpld_idea);
rc = PlxPci_CommonBufferProperties(pDevice,&PciBuffer);
if (rc != ApiSuccess)
{
Cons_printf("*ERROR* - API failed\n");
ret = ERR_OPEN_DMA_FAIL;
}
// Clear DMA structure
memset(&DmaProp, 0, sizeof(PLX_DMA_PROP));
// Initialize the DMA channel
DmaProp.LocalBusWidth = 3; // 32-bit
DmaProp.ReadyInput = 1;
DmaProp.ConstAddrLocal = 1;
rc =PlxPci_DmaChannelOpen(pDevice,DmaChannel,&DmaProp);
if (rc != ApiSuccess)
{
Cons_printf("*ERROR* - API failed\n");
ret = ERR_OPEN_DMA_FAIL;
}
// Clear DMA data
for(j = 0; j < count + 1; j++)
{
Delay_Us(50);
if(j == count)
{
len = offset;
}
else
{
len = 4096;
}
memset(buffer, 0, 4096);
memcpy(buffer, pUserBuffer + j * 4096, 4096);
memset(&DmaParams, 0, sizeof(PLX_DMA_PARAMS));
// Clear DMA data
memset(&DmaParams, 0, sizeof(PLX_DMA_PARAMS));
DmaParams.UserVa = (PLX_UINT_PTR)buffer;
DmaParams.LocalAddr = wr_addr;
DmaParams.ByteCount = len;
DmaParams.Direction = PLX_DMA_PCI_TO_LOC;
// Specify a timeout to let API perform wait
//ASCIIToHex(buffer, len);
rc =PlxPci_DmaTransferUserBuffer(pDevice,DmaChannel,&DmaParams,0);
while(1)
{
do
{
rc = PlxPci_DmaStatus(pDevice, 0);
retry_times++;
}
while (rc == ApiDmaInProgress && retry_times <= 1000000);
switch (rc)
{
case ApiDmaDone:
//Cons_printf("Ok (DMA ApiDmaDone)\n");
ret = 0;
break;
case ApiDmaInProgress:
Cons_printf("*ERROR* -DMA ApiDmaInProgress\n");
ret = ERR_DMA_ALWAYS_INPROGESS;
goto FAIL;
default:
Cons_printf("*ERROR* - API failed\n");
ret = ERR_DMA_OTHER_ERR;
goto FAIL ;
}
break;
}
ret = Read_Dma_Count(pDevice, &dma_count);
if(ret)
{
Cons_printf("Read_Dma_Count\n");
goto FAIL;
}
//cpld_idea = 0;
//ret = Read_Cpld_Idea(pDevice, &cpld_idea);
ret = Read_Dma_To_Fpga_Data(pDevice, &data_value);
if(ret)
{
Cons_printf("Read_Dma_Count\n");
goto FAIL;
}
}
if(UserBufferLen != dma_count)
{
Cons_printf("UserBufferLen = %d, count = %d\n", UserBufferLen, dma_count);
ret = ERR_DMA_TRANSLATE_ERR;
goto FAIL;
}
FAIL:
// Close DMA Channel
//Cons_printf(" Close DMA Channel.............. ");
rc =PlxPci_DmaChannelClose(pDevice,DmaChannel);
if (rc != ApiSuccess)
{
Cons_printf("*ERROR* - API failed\n");
PlxPci_DeviceReset(pDevice);
ret = ERR_CLOSE_DMA_FAIL;
}
PlxPci_DmaChannelClose(pDevice,DmaChannel);
free(buffer);
return ret;
}