Hi,
I facing issue with ADI AXI DMAC - data is lost between two transaction even though the FIFO size is sufficient and writing clock is slow.
I want to continuously stream the data from PL to PS using AXI DMAC, the data will further be sent on Ethernet (1Gbps). For getting acquainted with ADI AXI DMAC I have created a design in Vivado 2019.2.
The design has a 32-bit counter (500KHz), ADI AXI DMAC configured in FIFO-MM mode (scr:FIFO, dest:MM).
| FIFO size | 8192 Bytes |
| FIFO width | 32- bits |
| FIFO write clock | 500KHz |
| AXI Clock | 100MHz |
In C program, the dma is first configured, then in while loop - dma is started, data is read from DDR and stored in internal buffer.
Data of approx. 400 Bytes is observed in between the end of one transaction and start of other transaction.
Am I missing any configuration? is there any limitation on dma? does it require resetting between two transactions ?
Below is the standalone code:
#include <xparameters.h>
#include "xil_cache.h"
#include "axi_dmac.h"
#include "no_os_print_log.h"
#include "no_os_gpio.h"
#include "no_os_delay.h"
#include "xilinx_spi.h"
#include "xilinx_gpio.h"
#include "no_os_error.h"
#include <xil_io.h>
#include <stdio.h>
#include "xtime_l.h"
#include "xil_exception.h"
#define DEV_DDR_BASEADDR 0x00100000
#define ENABLE_BASEADDR XPAR_AXI_GPIO_0_BASEADDR
int main(void)
{
/* Disable the instruction cache. */
Xil_DCacheDisable();
Xil_ICacheDisable();
Xil_Out32(ENABLE_BASEADDR, 0x00000000);
u32 b_DDR_Data = 0;
u32 b_DDR_Addr = 0;
XTime tStart, tEnd;
double elapsed_time_us;
struct axi_dmac *dma_desc;
int ret;
struct axi_dmac_init dma_initial = {
.name = "ad7768_dma",
.base = XPAR_AXI_DMAC_0_BASEADDR,
.irq_option = IRQ_DISABLED
};
/* Initialize AXI DMAC */
ret = axi_dmac_init(&dma_desc, &dma_initial);
if (ret != 0){
xil_printf("Failed - axi_dmac_init!\n\r");
}
struct axi_dma_transfer read_transfer = {
// Number of bytes to write/read
.size = 128,
// Transfer done flag
.transfer_done = 0,
// Signal transfer mode
.cyclic = NO,
// Address of data source
.src_addr = 0,
// Address of data destination
.dest_addr = (uintptr_t)DEV_DDR_BASEADDR
};
Xil_Out32(ENABLE_BASEADDR, 0x00000001);
u32 data_buff[8192] = {0};
int index_buff = 0;
while(1){
ret = axi_dmac_transfer_start(dma_desc, &read_transfer);
if (ret != 0){
xil_printf("Failed - axi_dmac_transfer_start!\n\r");
}
u32 DDR_Data = 0;
u32 DDR_Addr = 0;
for (int k = 0; k < 32; k++) {
DDR_Addr = ( DEV_DDR_BASEADDR + (k*4) );
DDR_Data = Xil_In32(DDR_Addr);
data_buff[index_buff + k] = DDR_Data;
}
index_buff = index_buff + 32;
if(index_buff == 8192)
break;
}
xil_printf("Transfer Done!\n\r");
for (int j = 0; j < 8192; j++){
if( j != data_buff[j]){
xil_printf("data[%d] = %d\n\r", j, data_buff[j]);
}
}
//cleanup
axi_dmac_remove(dma_desc);
}
Below is the vivado block diagram screenshot:
