NIOS II的DMA之存储器之间的数据传输
今天一个哥们问我DMA的传输,他用我上一篇关于DMA串口传输的程序,因为他没怎么学过所以我给他讲不通,而且他根本不了解串口怎么连接!所以想做个DMA的存储器之间的传输。
下面的图是SOPC连接图,其中dma_0为上次的串口和SDRAM传输控制,注意上次讲错了——因为DMA是可以双向传输,即读写端口可以同时连载要传输的两个设备上。dma_1为这次要用到的,分别连到SDRAM和ON_CHIP_MEM上,其实可以不用ON_CHIP_MEM的,即DMA可以完成同一存储器之间不同地址的传输。
下面是NIOS II C++源程序
#include <stdio.h> #include <string.h> #include "system.h" #include "sys/alt_dma.h" #include "unistd.h" #include "altera_avalon_uart_regs.h" #include "io.h" #include <sys/alt_cache.h> static volatile int tx_done = 0; //回调函数 static void done (void* handle) { tx_done++; } #define TRANSFER_LENGTH 128 int main(void) { char *source = (void*)(SDRAM_0_BASE+10000); char *dest = (void*)(ON_CHIP_MEM_BASE+256); memset(source,0x54,TRANSFER_LENGTH); alt_dma_txchan tx; //创建DMA发送信道 tx = alt_dma_txchan_open("/dev/dma_1"); //当信道创建成功 if(tx == NULL) { printf("Failed to open transit channel.\n"); } else { printf("Create the transit channel successfully.\n"); } //创建DMA接收通道 alt_dma_rxchan rx; rx = alt_dma_rxchan_open("/dev/dma_1"); //当信道创建成功 if(rx == NULL) { printf("Failed to open receive channel.\n"); } else { printf("Create the receive channel successfully.\n"); } if(alt_dma_txchan_send(tx, source, TRANSFER_LENGTH, NULL, NULL)<0) { printf ("Error: failed to post transmit request\n"); } //提交DMA接收请求 指定接收数据的位置(sdram)以及传输数据量 if(alt_dma_rxchan_prepare(rx, dest, TRANSFER_LENGTH, done, NULL) < 0) { printf ("Error: failed to post receive request\n"); } // 等待发送结束 while (!tx_done); printf("Transmit successful\n"); usleep(5000000); int loop,errorcount=0; for(loop=1;loop<TRANSFER_LENGTH;loop++) { //对比缓冲区数据 if(source[loop]!=dest[loop]) { printf("Verify failed at location: 0x%X\n",loop); errorcount++; } } if(errorcount==0) { printf("Transfer successfully !\n"); } else { printf("Transfer failed !\n"); } while(1); }需要注意的是:DMA传输数据长度必须是2的N次方(2^N),否则会出现错误的,另外可能由于SDRAM数据同步问题,如果接收数据的是SDRAM上的内存空间,结果会打印:Transfer failed !即,在比较两个空间数据时会出现不相等,但是调试的时候是可以,虽然我做了延时5秒钟,但是还是不能解决,希望高手解答!如果接收数据的是ON_CHIP_MEM的话是完全没有问题的。
本人个人主页本文地址:http://jrmen.org.ru/archives/31