AXI CDMA研究 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki
这是一个2个master的axi interconnect。zynq和cdma都是master。另外,由于cdma本身需要通过S_AXI_LITE接口进行配置,因此cdma也是总线matrix的从机。
自己创建一个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;
}
用AXI CDMA去写这个IP的Memory。将LEN长度设置为256,结果发现超出256地址的Memory也全部被填充了数据,按照256循环。
原因很清楚,AXI4 Full的外设Memory深度目前是256.
地址的变化是以64变化一次。16x4=64
每个burst期间,数据一共变化了16次,WVALID产生了8个脉冲。因此每个WAVLID脉冲发送2次数据。
最后一次发的数据是0x10d=269。因此发送的270个数据是0...269,符合预期。因此dma发的内容是没有问题的。 但是AXI4 Full IP收到的数据存入ram,不是按这个来的。原因上面已经说了,ip内部实际的地址深度只有256。