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

posted on 2010-06-08 19:47  金瑞  阅读(1474)  评论(3编辑  收藏  举报

导航