AXI DMA数据对齐

来源:互联网 发布:北京九五太维 知乎 编辑:程序博客网 时间:2024/05/16 14:19

    查看PG-021知道,AXI DMA采用小端对齐,即高字节放在高地址,低字节放在低地址。在做AD7989数据采集时,要完成如下要求:

  (1) AD采回的数据打包,一个packet包含1020个采集点(32位),接着用4个字(4Byte)来描述包的信息,包括通道号、块号(相当于packet号)、trig信号的位置(每个packet至多有一个trig信号)、crc校验码。

  (2) 将每个packet的通过AXI DMA传送到DDR3中。

在做各部分时,发现了如下现象,当时没想明白,后来懂了。我们知道,AXI DMA在接收Stream Data时是这样做的(S2MM -- RxSetup()):

  1) 配置DMA      

XAxiDma_Config *Config;Config = XAxiDma_LookupConfig(DMA_DEV_ID);if (!Config) {    xil_printf("No config found for %d\r\n", DMA_DEV_ID);    return XST_FAILURE;}/* Initialize DMA engine */XAxiDma_CfgInitialize(&AxiDma, Config);

  2) 设置DMA接收数据通道,启动DMA接收数据:RxSetup()

XAxiDma_BdRing *RxRingPtr;XAxiDma_Bd *BdPtr;XAxiDma_Bd *BdCurPtr;int BdCount;int FreeBdCount;u32 RxBufferPtr;RxRingPtr = XAxiDma_GetRxRing(&AxiDma); //获取BD ring指针BdCount = XAxiDma_BdRingCntCalc(XAXIDMA_BD_MINIMUM_ALIGNMENT,RX_BD_SPACE_HIGH - RX_BD_SPACE_BASE + 1); //计算RX_BD_SPACE地址区间上BD的个数XAxiDma_BdRingCreate(RxRingPtr, RX_BD_SPACE_BASE,RX_BD_SPACE_BASE,XAXIDMA_BD_MINIMUM_ALIGNMENT, BdCount); //创建Bd ringFreeBdCount = XAxiDma_BdRingGetFreeCnt(RxRingPtr);XAxiDma_BdRingAlloc(RxRingPtr, FreeBdCount, &BdPtr); //设置Free BdBdCurPtr = BdPtr;RxBufferPtr = RX_BUFFER_BASE;XAxiDma_BdSetBufAddr(BdCurPtr, RxBufferPtr); // Bd 与 RX_Buffer绑定XAxiDma_BdSetLength(BdCurPtr, MAX_PKT_LEN,RxRingPtr->MaxTransferLen); //设置每个BD传输的数据长度(Byte)XAxiDma_BdRingToHw(RxRingPtr, FreeBdCount, BdPtr); //将 Free Bd交给硬件处理XAxiDma_BdRingStart(RxRingPtr); //启动DMA RX 通道 
    调试时,准备用AXI DMA传送已打包好的8个packet数据,总共1024*4*8Byte,因为RX_BD_SPACE最多可分配出512个BD,因此MAX_PKT_LEN最小也应大于等于1024*4*8/512。将其设置为256。最后发现,每一个包最后256字节(64个字)有63个数据不是packet中的数据,原因在于:

    在写底层FPGA部分的M_AXIS_S2MM 接口时,没有匹配好与AXI DMA的S_AXIS_S2MM相连的TVALID、TREADY信号(二者同时为高时BD将数据从Stream上写到RX_BUFFER中),每次都多传了一个数据,使得每个packet包含了1025个数据,因此最后一个BD只会传送一个有效数据,其他63个数据都是不确定的。因此出现了packet0: 0x1400000~0x1401000、packet1:0x1401100~0x1402100、packet2:0x1402200~0x03200.....

    解决的办法是去除那个多余的数据:将 assign M_AXIS_TVALID    = (read_pointer == 0) ? axis_tvalid_delay : axis_tvalid_delay && fifo_rd_en_delay; //read_pointer=0时TVALID会保持两个时钟的高电平,TREADY一直为高,直到所有的BD处理完后才会拉低,因此会写入两个数据

                                                                改为:assign M_AXIS_TVALID    =  axis_tvalid_delay : axis_tvalid_delay && fifo_rd_en_delay;

1 0
原创粉丝点击