-
Notifications
You must be signed in to change notification settings - Fork 0
AXI DMA研究
minichao9901 edited this page Feb 27, 2024
·
6 revisions
可以清楚看到,读memory期间,一次性读了256个bytes,共64个word。在整个读数据期间,tvalid一直有效,读完之后tlast信号变为1,产生了mm2s_introut中断信号。
对比寄存器手册知道:
MM2S_DMA_CR的RS=1, IOC_IrqEn=1, Dly_IrqEn=1, Err_IrqEn=1。 IRQThreshold=0x1(默认值) MM2S_SA=0x12000000 S2MM_DMA_CR的RS=1, IOC_IrqEn=1, Dly_IrqEn=1, Err_IrqEn=1。 IRQThreshold=0x1(默认值) S2MM_SA=0x14000000
源寄存器和目的寄存器的内容:
从这里看,src的内容没有被正确写入dest,因此print failed了。后来发现,如果我们把ILA去掉就可以正确读写了。看样子ILA影响了数据传输。原因不清楚。
XAxiDma_SimpleTransfer(&AxiDma0,(UINTPTR) TxBufferPtr,
256, XAXIDMA_DMA_TO_DEVICE);
XAxiDma_SimpleTransfer(&AxiDma0,(UINTPTR) RxBufferPtr,
256, XAXIDMA_DEVICE_TO_DMA);
usleep(1000);
Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, 1024);
u32 base=0x40400000;
Xil_Out32(base, 0x00010003);
Xil_Out32(base+0x30, 0x00010003);
Xil_Out32(base+0x18, TX_BUFFER_BASE);
Xil_Out32(base+0x48, RX_BUFFER_BASE);
Xil_Out32(base+0x28, 1024);
Xil_Out32(base+0x58, 1024);
sleep(1);
Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, 1024);
connect
tar
tar 2
bpadd -file main.c -line 65
mrd 0x40400000 20
mrd 0x12000000 64
mrd 0x14000000 64
nxt 10000
经过xsct分析后,我们才知道,小梅哥的程序读写数量>256会报错。修改后,结果正确。
//如果发生错误,则打印失败提示
if (Error) {
printf("DMA Transfer Failed!\n");
} else {
//测试完成,检查数据
for(Index = 0; Index < 1024; Index++)
{
//原始程序是这一句:if(RxBufferPtr[Index] != Index) {
//导致当Index数据量>256时,比较结果会出错。实际内存是对的。原因不清楚。
if(RxBufferPtr[Index] != TxBufferPtr[Index]) {
Error_Cnt++;
}
}
if(Error_Cnt > 0)
printf("Test Failed! %d\n", Error_Cnt);
else
printf("Test Successfully!\n");
}
return 0;
}
- 与TxBuffer, RxBuffer数组的定义类型有关系。DMA传输和CacheClean操作,都是以bytes为单位。长度上要留意,要匹配。
- 如果TxBuffer, RxBuffer数组是u8类型,那么DMA传输和CacheClean操作的长度与TxBuffer, RxBuffer数组保持一致即可。
- 如果TxBuffer, RxBuffer数组是u16类型,那么DMA传输和CacheClean操作的长度是TxBuffer, RxBuffer数组长度的2倍。
- 如果TxBuffer, RxBuffer数组是u32类型,那么DMA传输和CacheClean操作的长度是TxBuffer, RxBuffer数组长度的4倍。
u32类型
uint32_t *TxBufferPtr; //传输数据的指针
uint32_t *RxBufferPtr; //接收数据的指针
//将指针TxBufferPtr指向TX_BUFFER_BASE
TxBufferPtr = (uint32_t *)TX_BUFFER_BASE;
//将指针RxBufferPtr指向RX_BUFFER_BASE
RxBufferPtr = (uint32_t *)RX_BUFFER_BASE;
//初始化AXI DMA
AXI_DMA_Init(&AxiDma0, XPAR_AXIDMA_0_DEVICE_ID);
//给TxBufferPtr赋值为0~255
for(Index = 0; Index < 1024; Index ++) {
TxBufferPtr[Index] = Index;
}
//在DMA传输之前刷新Buffer
Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, 1024*4);
//开启数据传输
XAxiDma_SimpleTransfer(&AxiDma0,(UINTPTR) TxBufferPtr,
1024*4, XAXIDMA_DMA_TO_DEVICE);
XAxiDma_SimpleTransfer(&AxiDma0,(UINTPTR) RxBufferPtr,
1024*4, XAXIDMA_DEVICE_TO_DMA);
sleep(1);
Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, 1024*4);
u16类型
uint16_t *TxBufferPtr; //传输数据的指针
uint16_t *RxBufferPtr; //接收数据的指针
//将指针TxBufferPtr指向TX_BUFFER_BASE
TxBufferPtr = (uint16_t *)TX_BUFFER_BASE;
//将指针RxBufferPtr指向RX_BUFFER_BASE
RxBufferPtr = (uint16_t *)RX_BUFFER_BASE;
//初始化AXI DMA
AXI_DMA_Init(&AxiDma0, XPAR_AXIDMA_0_DEVICE_ID);
//给TxBufferPtr赋值为0~255
for(Index = 0; Index < 1024; Index ++) {
TxBufferPtr[Index] = Index;
}
//在DMA传输之前刷新Buffer
Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, 1024*2);
//开启数据传输
XAxiDma_SimpleTransfer(&AxiDma0,(UINTPTR) TxBufferPtr,
1024*2, XAXIDMA_DMA_TO_DEVICE);
XAxiDma_SimpleTransfer(&AxiDma0,(UINTPTR) RxBufferPtr,
1024*2, XAXIDMA_DEVICE_TO_DMA);
sleep(1);
Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, 1024*2);
u8类型
uint8_t *TxBufferPtr; //传输数据的指针
uint8_t *RxBufferPtr; //接收数据的指针
//将指针TxBufferPtr指向TX_BUFFER_BASE
TxBufferPtr = (uint8_t *)TX_BUFFER_BASE;
//将指针RxBufferPtr指向RX_BUFFER_BASE
RxBufferPtr = (uint8_t *)RX_BUFFER_BASE;
//初始化AXI DMA
AXI_DMA_Init(&AxiDma0, XPAR_AXIDMA_0_DEVICE_ID);
//给TxBufferPtr赋值为0~255
for(Index = 0; Index < 1024; Index ++) {
TxBufferPtr[Index] = Index;
}
//在DMA传输之前刷新Buffer
Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, 1024);
//开启数据传输
XAxiDma_SimpleTransfer(&AxiDma0,(UINTPTR) TxBufferPtr,
1024, XAXIDMA_DMA_TO_DEVICE);
XAxiDma_SimpleTransfer(&AxiDma0,(UINTPTR) RxBufferPtr,
1024, XAXIDMA_DEVICE_TO_DMA);
sleep(1);
Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, 1024);