AXI CDMA研究 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

系统框图

image image

这是一个2个master的axi interconnect。zynq和cdma都是master。另外,由于cdma本身需要通过S_AXI_LITE接口进行配置,因此cdma也是总线matrix的从机。

image

自己创建一个AXI4的IP,注意是AXI4 Full接口。它不再是寄存器了,它提示设置多少memory。我们给IP分配了1024 bytes的memory,也就是256x32bits。因此地址是8位宽度。

注意CDMA只能memomry->memory,不能memory->外设。好在创建的AXI-Full IP,它内部有一块RAM,是内存映射的ram,可以用来使用CDMA。

程序

#include "xtime_l.h"
#include "xil_io.h"

#include "xparameters.h"
#include <stdio.h>
#include "xaxicdma.h"
#include "xil_cache.h"
#include "xtime_l.h"
#include "xil_io.h"
#include "sleep.h"

XAxiCdma_Config *axi_cdma_cfg;
XAxiCdma axi_cdma;
#define TX_BUFF_BASE 0x10000000
#define RX_BUFF_BASE 0x40000000
#define RX_BUFF_BASE2 0x12000000

#define BUFF_LEN 270


int main()
{
    int Status;

    u32 *rx_buffer = (u32 *) RX_BUFF_BASE;
    u32 *tx_buffer = (u32 *) TX_BUFF_BASE;

	u32 *p=(u32*)RX_BUFF_BASE;
	for(int i=0; i<BUFF_LEN; i++){
		p[i]=i;
//		usleep(20);
	}

	for(int i=0; i<BUFF_LEN; i++){
		printf("%x, %d\n", &p[i], p[i]);
	}

    for(int  i=0; i<BUFF_LEN; i++){
    	tx_buffer[i]=i;
    }

    axi_cdma_cfg = XAxiCdma_LookupConfig(XPAR_AXICDMA_0_DEVICE_ID);
    Status = XAxiCdma_CfgInitialize(&axi_cdma, axi_cdma_cfg, axi_cdma_cfg->BaseAddress);

     XAxiCdma_IntrDisable(&axi_cdma, XAXICDMA_XR_IRQ_ALL_MASK);

     if (XAxiCdma_IsBusy(&axi_cdma)) {
     printf("AXI CDMA is busy...\n\r");
     while (XAxiCdma_IsBusy(&axi_cdma));
     }


    Xil_DCacheFlush();

    u64 t1,t2;
    //XTime_SetTime(0);
    XTime_GetTime(&t1);
    Status = XAxiCdma_SimpleTransfer(
                                     &axi_cdma,
                                     (u32) tx_buffer,
                                     (u32) rx_buffer,
                                     BUFF_LEN*4,
                                     NULL,
                                     NULL);

    Xil_DCacheFlush();
    XTime_GetTime(&t2);

    //注意必须%f才能打印出正确的结果,%d不行。
    printf("DMA Move 32768*32bit Total Time: %f us\n\r", (t2-t1)*1e6/COUNTS_PER_SECOND);

    // Wait until core isn't busy
    if (XAxiCdma_IsBusy(&axi_cdma)) {
    printf("AXI CDMA is busy...\n\r");
    while (XAxiCdma_IsBusy(&axi_cdma));
    }

    Xil_DCacheInvalidateRange((u32)rx_buffer, BUFF_LEN*4);

	//测试完成,检查数据
    int Error_Cnt=0;
	for(int Index = 0; Index < BUFF_LEN; Index++)
	{
		if(rx_buffer[Index] != tx_buffer[Index]) {
			Error_Cnt++;
			printf("%x, %d\n", rx_buffer[Index], Index);
		}
	}
	if(Error_Cnt > 0)
		printf("Test Failed! %d\n", Error_Cnt);
	else
		printf("Test Successfully!\n");


    Xil_DCacheFlush();

// read back from axi-ip
    Status = XAxiCdma_SimpleTransfer(
                                     &axi_cdma,
                                     (u32) RX_BUFF_BASE,
                                     (u32) RX_BUFF_BASE2,
                                     BUFF_LEN*4,
                                     NULL,
                                     NULL);

    Xil_DCacheFlush();

    // Wait until core isn't busy
    if (XAxiCdma_IsBusy(&axi_cdma)) {
    printf("AXI CDMA is busy...\n\r");
    while (XAxiCdma_IsBusy(&axi_cdma));
    }

    Xil_DCacheInvalidateRange(RX_BUFF_BASE2, BUFF_LEN*4);


    return 0;
}

我们通过mrd函数+断点执行程序,观察内存的内容。

用AXI CDMA去写这个IP的Memory。将LEN长度设置为256,结果发现超出256地址的Memory也全部被填充了数据,按照256循环。

image image

原因很清楚,AXI4 Full的外设Memory深度目前是256.

ILA抓取波形

image image

地址的变化是以64变化一次。16x4=64

image

每个burst期间,数据一共变化了16次,WVALID产生了8个脉冲。因此每个WAVLID脉冲发送2次数据。

image

最后一次发的数据是0x10d=269。因此发送的270个数据是0...269,符合预期。因此dma发的内容是没有问题的。 但是AXI4 Full IP收到的数据存入ram,不是按这个来的。原因上面已经说了,ip内部实际的地址深度只有256。

⚠️ **GitHub.com Fallback** ⚠️