DMALOOP实验,用来分析axi stream时序,先将原理图和实验ILA所折图展示如下:
dmaloopdemo实验是OK的,ILA中时序发现:
stream data fifo M_AXIS接口(即传给DMA的S2MM):传输时,先将tlast下拉,同时刻tvalid上拉,这两步做完,因tready恒=1,估计下一个时钟周期上升沿时总线就会认为开始传输数据了;结束时,因tvalid从第一次传输开始就一直=1,所以先上拉tlast,一个周期之后tvalid下拉,但要注意:tlast却没有下拉,始终还是=1,具体可以看https://my.oschina.net/u/4583591/blog/4701373中所说:“ master将TLAST拉高,TVALID拉低,传输结束”。
stream data fifo S_AXIS接口(即DMA的MM2S传给fifo),用来接收内存通过DMA下发来的数据,tvalid上拉表示数据开始传输,当DMA需要结束传输数据给stream data fifo时,首先上拉tlast,下个周期上升沿(B)将tvalid和tlast全部都下拉(我分析,应该是B上升沿之前,将数据放到总线上,此时判断出tlast==1,tvalid和tready都==1,所以B之后需要将tvalid和tlast都下拉)。main.c中代码如下:
/*
*
* www.osrc.cn
* www.milinker.com
* copyright by li yang mi lian dian zi www.osrc.cn
* axi dma test
*
*/
#include "dma_intr.h"
#include "sys_intr.h"
static XScuGic Intc; //GIC
static XAxiDma AxiDma;
volatile u32 success;
int Tries = NUMBER_OF_TRANSFERS;
int i;
int Index;
u8 *TxBufferPtr= (u8 *)TX_BUFFER_BASE;
u8 *RxBufferPtr=(u8 *)RX_BUFFER_BASE;
u8 Value;
int axi_dma_test()
{
int Status;
TxDone = 0;
RxDone = 0;
Error = 0;
xil_printf("\r\n----DMA Test----\r\n");
xil_printf("PKT_LEN=%d\r\n",MAX_PKT_LEN);
//while(1)
for(i = 0; i < Tries; i ++)
{
Value = TEST_START_VALUE + (i & 0xFF);
for(Index = 0; Index < MAX_PKT_LEN; Index ++) {
TxBufferPtr[Index] = Value;
Value = (Value + 1) & 0xFF;
}
/* Flush the SrcBuffer before the DMA transfer, in case the Data Cache
* is enabled
*/
Xil_DCacheFlushRange((u32)TxBufferPtr, MAX_PKT_LEN);
Status = XAxiDma_SimpleTransfer(&AxiDma,(u32) RxBufferPtr,
MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = XAxiDma_SimpleTransfer(&AxiDma,(u32) TxBufferPtr,
MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait TX done and RX done
*/
while (!TxDone || !RxDone) {
/* NOP */
}
success++;
TxDone = 0;
RxDone = 0;
if (Error) {
xil_printf("Failed test transmit%s done, "
"receive%s done\r\n", TxDone? "":" not",
RxDone? "":" not");
goto Done;
}
/*
* Test finished, check data
*/
Status = DMA_CheckData(MAX_PKT_LEN, (TEST_START_VALUE + (i & 0xFF)));
if (Status != XST_SUCCESS) {
xil_printf("Data check failed\r\n");
goto Done;
}
}
xil_printf("AXI DMA interrupt example test passed\r\n");
xil_printf("success=%d\r\n",success);
/* Disable TX and RX Ring interrupts and return success */
DMA_DisableIntrSystem(&Intc, TX_INTR_ID, RX_INTR_ID);
Done:
xil_printf("--- Exiting Test --- \r\n");
return XST_SUCCESS;
}
int init_intr_sys(void)
{
DMA_Intr_Init(&AxiDma,0);//initial interrupt system
Init_Intr_System(&Intc); // initial DMA interrupt system
Setup_Intr_Exception(&Intc);
DMA_Setup_Intr_System(&Intc,&AxiDma,TX_INTR_ID,RX_INTR_ID);//setup dma interrpt system
DMA_Intr_Enable(&Intc,&AxiDma);
}
int main(void)
{
init_intr_sys();
axi_dma_test();
}
根据https://wenku.baidu.com/view/a2d9ed1900020740be1e650e52ea551811a6c945.html 中所说,“ready由从设置驱动,表示从设备下一个时钟周期上升沿到来时能够接收数据,注意:是下一个时钟上升沿时接收数据。tlast和数据一起传输。”