首先,来做一个简单的实验,利用DMA来实现on-chip-memory和SRAM之间的传输,同时也在做一个关于SRAM不同地址之间的传输。

一、硬件设计

  1、首先设计自己的SOPC结构,包括CPU、jtag_uart、sram、sysid、onchip-memory,时钟就用50M即可。都不需要任何的设置。如下图所示:

  2、对于QuartusII上顶层文件就不需要有什么可讲的,主要代码如下。

1 Reset_Delay delay1 (.iRST(KEY[0]),.iCLK(CLOCK_50),.oRESET(CPU_RESET));
2
3 dma_system u0 (
4 // 1) global signals:
5   .clk_0(CLOCK_50),
6 .reset_n(CPU_RESET),
7
8 // the_sram_0
9   .SRAM_ADDR_from_the_sram_0(SRAM_ADDR),
10 .SRAM_CE_N_from_the_sram_0(SRAM_CE_N),
11 .SRAM_DQ_to_and_from_the_sram_0(SRAM_DQ),
12 .SRAM_LB_N_from_the_sram_0(SRAM_LB_N),
13 .SRAM_OE_N_from_the_sram_0(SRAM_OE_N),
14 .SRAM_UB_N_from_the_sram_0(SRAM_UB_N),
15 .SRAM_WE_N_from_the_sram_0(SRAM_WE_N)
16 );

二、软件设计

  由于主要是设计到DMA的应用,所以主要就是做一下软件方面的设计。

核心代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#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 rx_done = 0;
//回调函数
static void done (void* handle,void* data)
{
    rx_done++;
}
 
#define TRANSFER_LENGTH 128
int main(void)
{
  char *source = (void*)(SRAM_0_BASE+0x10000);
  char *dest = (void*)(SRAM_0_BASE+0x11000);
     memset(source,0x54,TRANSFER_LENGTH);
    alt_dma_txchan tx;
    //创建DMA发送信道
    tx = alt_dma_txchan_open("/dev/dma_0");
    //当信道创建成功
    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_0");
    //当信道创建成功
    if(rx == NULL)
    {
        printf("Failed to open receive channel.\n");
    }
    else
    {
        printf("Create the receive channel successfully.\n");
    }
 
    int rc;
    if((rc=alt_dma_txchan_send(tx,
                          source,
                          TRANSFER_LENGTH,
                          NULL,
                          NULL))<0)
       {
        printf("Error: failed to post transmit request\n");
        exit(1);
       }
   //提交DMA接收请求 指定接收数据的位置(sram)以及传输数据量
    if((rc=alt_dma_rxchan_prepare(rx,
                            dest,
                            TRANSFER_LENGTH,
                            done,
                            NULL))< 0)
       {
       printf ("Error: failed to post receive request\n");
       exit(1);
       }
// 等待发送结束
while (!rx_done)
    printf("Not Not\n");
    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);
 
}
1
  
1
 

  上面的代码主要是依照说明书上的代码来讲的,首先是分配两个地址空间,一个源地址空间,一个目标地址空间。由于在SOPC里面,DMA连接的时候,我把读写端都连在了SRAM和on-chip-memory上,这样的话,就可以在他们之间传,也可以在任何一个空间的不同地址传。上面演示的是SRAM上不同的地址空间传输,这个实验如果成功的话,那么另外的实验也能成功。

  传输成功之后,我们做了一个小小的测试程序,就是测试两个地址上的数据是否一样,如果一样的话,就输出Transfer successfully!,否则就输出Transfer failed!最后的结果是显示正确的。

  这个实验表面上看起来似乎没什么,可我在做这个DMA测试的时候经历了很多。总结一下:

  1、第一个问题就是出现printf()函数打印不出来,这个问题可让我伤脑筋了,刚开始我以为是硬件坏了,所以我写了一个hello world程序测试了一下,发现有的时候确实就输出不成功!这里面的原因我想了很久。最后我得出了原因。原来是我的操作不当引起的,在quartus升级到9.1之后,里面改动了很多,如果你的硬件信息出现了改变,需要重新生成一下bsp工程库,另外也需要重新编译一下你的工程,在下载你的工程到硬件。这里面的步骤绝对不能有错误。这里面我就犯了这样的错误,我首先没有重新编译一下这个工程,只是run了一下,而我run的时候是用快捷键的,这里面的run其实没有重新编译你的工程,所以一定要重新编译,重新run一次。

  2、第二个问题就是接收通道打开不成功,还有就是传输显示没有传完,但是回调函数调用了,这样就告诉你传输成功啦!这些问题,都是我无法想象的。原因其实也是很简单,硬件这东西,他本身没有任何的差错能力,就是说,你必须完全按照正确的步骤来进行,才能得到你想要的结果,运行的步骤绝对不能求急,原因同上。

  现在再来看看DMA的一些基本原理。下面是DMA传输的基本应用。而我们不需要了解DMA内部的寄存器等等是什么样子的,它提供给你的那些API函数都是有统一的接口方便你使用。

Nios II中的DMA传输有以下三种形式:

1、 存储器到存储器

这种情况下需要同时打开发送通道和接收通道,而且源地址和目标地址都是自增的。

//打开发送通道

tx = alt_dma_txchan_open("/dev/dma_0");

//tx_buf是源地址、传输数据块长度是length

dma_res = alt_dma_txchan_send(tx, tx_buf, length, NULL, NULL);

//打开接收通道

rx = alt_dma_rxchan_open("/dev/dma_0");

//rx_buf是目标地址、传输数据块长度是length、dma_done()是DMA完成后被调用的回调函数

dma_res = alt_dma_rxchan_prepare(rx, rx_buf, length, dma_done, NULL);

2、 存储器到外设

这种情况下只要打开发送通道,而且源地址是自增的,目标地址是固定的。

tx = alt_dma_txchan_open("/dev/dma_0"); // 打开发送通道

alt_dma_txchan_ioctl(tx, ALT_DMA_TX_ONLY_ON, (void *)dst_addr); // dst_addr是目标地址

dma_res = alt_dma_txchan_send(tx, tx_buf, length, dma_done, NULL); // tx_buf是源地址

3、 外设到存储器

这种情况下只要打开接收通道,而且源地址是固定的,目标地址是自增的。

rx = alt_dma_rxchan_open("/dev/dma_0"); // 打开接收通道

alt_dma_rxchan_ioctl(rx, ALT_DMA_RX_ONLY_ON, (void *)source_addr); // source_addr是源地址

dma_res = alt_dma_rxchan_prepare(rx, rx_buf, length, dma_done, NULL); // rx_buf是目标地址

其中通过alt_dma_txchan_ioctl,alt_dma_rxchan_ioctl还可以设置每次发送和接收的字节数。

DMA在FPGA的应用之我见的更多相关文章

  1. FPGA-HPS

    最近在做DE1的图像方面实验,用到了HPS,所以简要谈一谈什么是HPS. 由图可知,DE1的板子就是有fpga+hps组成的: 参考自:http://bbs.eeworld.com.cn/thread ...

  2. 【FPGA】相关介绍

    什么是 FPGA ? FPGA是Field Programmable Gate Array的缩写,即现场可编程门阵列,它是在PAL.GAL.EPLD等可编程器件的基础上进一步发展的产物.它是作为专用集 ...

  3. Tesla P4 在深度学习上的性价比辗压目前所有量产的FPGA

    7000的价格, 5.5T FP, 75W不到的功耗,性能接近M40,敢问目前有哪个量产的FPGA能做到?还不算开发和维护的难度...KU115光PCIE+DMA+DDR4 controller+AX ...

  4. FPGA的图像处理技术,你知道多少?

    最近一段时间一直在研究基于FPGA的图像处理,乘着EEPW这个机会和大家交流一下,自己也顺便总结一下.主要是为了大家对用FPGA做图像处理有个感性的认识,如果真要研究的话就得更加深入学习了.本人水平有 ...

  5. v3学院带您一起学习FPGA

    本文为原创,转载请注明! 课程名称:双buffer乒乓操作项目概况:使用FPGA内部ram作为缓冲器,实现对外部数据流的缓存:为了提升数据的传输及处理速度,在此节课中将用到两个ram进行乒乓操作.结构 ...

  6. 基于FPGA的Sobel边缘检测的实现

    前面我们实现了使用PC端上位机串口发送图像数据到VGA显示,通过MATLAB处理的图像数据直接是灰度图像,后面我们在此基础上修改,从而实现,基于FPGA的动态图片的Sobel边缘检测.中值滤波.Can ...

  7. DriverStudio开发PCI设备DMA数据传输

    DriverWizard向导可以创建基本的wDM驱动程序框架,包括总线类型,地址空间,中断源,DMA资源,以及IOCTL(i/o控制代码)的定义等等.详细情况可参看DriverStudio的帮助文档, ...

  8. 利用ZYNQ SOC快速打开算法验证通路(3)——PS端DMA缓存数据到PS端DDR

    上篇该系列博文中讲述W5500接收到上位机传输的数据,此后需要将数据缓存起来.当数据量较大或者其他数据带宽较高的情况下,片上缓存(OCM)已无法满足需求,这时需要将大量数据保存在外挂的DDR SDRA ...

  9. dma子系统 dmac

    DMA子是CPU中实现数据传输的一种方式,CPU配置好DMA控制器之后发起数据传输,CPU本身不参与数据传输的动作中去. DMA种类: 分为外设DMA和DMA控制器.其中外设DMA实现的为特定的外设与 ...

随机推荐

  1. jquery 遍历 table 下所有得tr td

    $("#middle").contents().find("tbody tr").each(function(i,n){ var child = $(this) ...

  2. Android面试题目整理与解说(一)

    这一篇文章专门整理一下研究过的Android面试题,内容会随着学习不断的添加,假设答案有错误,希望大家能够指正 1.简述Activity的生命周期 当Activity開始启动的时候,首先调用onCre ...

  3. zookeeper应用场景练习(分布式锁)

    在寻常的高并发的程序中.为了保证数据的一致性.因此都会用到锁.来对当前的线程进行锁定.在单机操作中.非常好做到,比方能够採用Synchronized.Lock或者其它的读写多来锁定当前的线程.可是在分 ...

  4. Effective JavaScript Item 34 在prototype上保存方法

    本系列作为EffectiveJavaScript的读书笔记. 不使用prototype进行JavaScript的编码是全然可行的,比如: function User(name, passwordHas ...

  5. 从Oracle Database 角度来看浪潮天梭K1主机的操作系统选择

    背景: 浪潮天梭k1主机.事实上分好几个类别: K1-950 intel 安腾cpu K1-930 intel 安腾cpu K1-910 intel 安腾cpu K1-800 intel 志强cpu ...

  6. UI组件之AdapterView及其子类(四)Gallery画廊控件使用

    听说 Gallery如今已经不使用了,API使用ViewPaper取代了,以后再学专研ViewPaper吧如今说说Gallery画廊,就是不停显示图片的意思 Gallery是用来水平滚动的显示一系列项 ...

  7. 动态语言切换(续)-designer中的retranslateUi(带源码)

    本站所有文章由本站和原作者保留一切权力,仅在保留本版权信息.原文链接.原文作者的情况下允许转载,转载请勿删改原文内容, 并不得用于商业用途. 谢谢合作.原文链接:动态语言切换(续)-designer中 ...

  8. FPGA静态时序分析——IO口时序(Input Delay /output Delay)

    1.1  概述 在高速系统中FPGA时序约束不止包括内部时钟约束,还应包括完整的IO时序约束和时序例外约束才能实现PCB板级的时序收敛.因此,FPGA时序约束中IO口时序约束也是一个重点.只有约束正确 ...

  9. flatMap作用

    总结:1. map会将每一条输入映射为一个新对象.{苹果,梨子}.map(去皮) = {去皮苹果,去皮梨子} 其中: “去皮”函数的类型为:A => B 2.flatMap包含两个操作:会将每一 ...

  10. Struts2中Struts.xml的作用

    struts.xml 为Struts 2的核心配置文件.struts.xml文件主要负责管理应用中的Action映射,以及该Action包含的Result定义等.struts.xml中主要配置Stru ...