NIOS II的DMA之存储器之间的数据传输
0赞
发表于 8/13/2010 5:09:12 PM
阅读(2863)
今天一个哥们问我DMA的传输,他用我上一篇关于DMA串口传输的程序,因为他没怎么学过所以我给他讲不通,而且他根本不了解串口怎么连接!所以想做个DMA的存储器之间的传输。
下面的图是SOPC连接图,其中dma_0为上次的串口和SDRAM传输控制,注意上次讲错了——因为DMA是可以双向传输,即读写端口可以同时连载要传输的两个设备上。dma_1为这次要用到的,分别连到SDRAM和ON_CHIP_MEM上,其实可以不用ON_CHIP_MEM的,即DMA可以完成同一存储器之间不同地址的传输。

下面是NIOS II C++源程序
01 |
#include <stdio.h> |
02 |
#include <string.h> |
03 |
#include "system.h" |
04 |
#include "sys/alt_dma.h" |
05 |
#include "unistd.h" |
06 |
#include "altera_avalon_uart_regs.h" |
07 |
#include "io.h" |
08 |
#include <sys/alt_cache.h> |
09 |
static volatile int tx_done = 0; |
10 |
//回调函数 |
11 |
12 |
static void done (void* handle) |
13 |
{ |
14 |
tx_done++; |
15 |
} |
16 |
#define TRANSFER_LENGTH 128 |
17 |
int main(void) |
18 |
{ |
19 |
|
20 |
char *source = (void*)(SDRAM_0_BASE+10000); |
21 |
char *dest = (void*)(ON_CHIP_MEM_BASE+256); |
22 |
memset(source,0x54,TRANSFER_LENGTH); |
23 |
|
24 |
alt_dma_txchan tx; |
25 |
//创建DMA发送信道 |
26 |
tx = alt_dma_txchan_open("/dev/dma_1"); |
27 |
//当信道创建成功 |
28 |
if(tx == NULL) |
29 |
{ |
30 |
printf("Failed to open transit channel.\n"); |
31 |
} |
32 |
else |
33 |
{ |
34 |
printf("Create the transit channel successfully.\n"); |
35 |
} |
36 |
|
37 |
//创建DMA接收通道 |
38 |
alt_dma_rxchan rx; |
39 |
rx = alt_dma_rxchan_open("/dev/dma_1"); |
40 |
//当信道创建成功 |
41 |
if(rx == NULL) |
42 |
{ |
43 |
printf("Failed to open receive channel.\n"); |
44 |
} |
45 |
else |
46 |
{ |
47 |
printf("Create the receive channel successfully.\n"); |
48 |
} |
49 |
|
50 |
if(alt_dma_txchan_send(tx, |
51 |
source, |
52 |
TRANSFER_LENGTH, |
53 |
NULL, |
54 |
NULL)<0) |
55 |
{ |
56 |
printf ("Error: failed to post transmit request\n"); |
57 |
} |
58 |
|
59 |
|
60 |
//提交DMA接收请求 指定接收数据的位置(sdram)以及传输数据量 |
61 |
if(alt_dma_rxchan_prepare(rx, |
62 |
dest, |
63 |
TRANSFER_LENGTH, |
64 |
done, |
65 |
NULL) < 0) |
66 |
{ |
67 |
printf ("Error: failed to post receive request\n"); |
68 |
} |
69 |
|
70 |
// 等待发送结束 |
71 |
while (!tx_done); |
72 |
73 |
printf("Transmit successful\n"); |
74 |
75 |
usleep(5000000); |
76 |
int loop,errorcount=0; |
77 |
for(loop=1;loop<TRANSFER_LENGTH;loop++) |
78 |
{ |
79 |
//对比缓冲区数据 |
80 |
if(source[loop]!=dest[loop]) |
81 |
{ |
82 |
printf("Verify failed at location: 0x%X\n",loop); |
83 |
errorcount++; |
84 |
} |
85 |
} |
86 |
if(errorcount==0) |
87 |
{ |
88 |
printf("Transfer successfully !\n"); |
89 |
} |
90 |
else |
91 |
{ |
92 |
printf("Transfer failed !\n"); |
93 |
} |
94 |
95 |
while(1); |
96 |
} |
需要注意的是:DMA传输数据长度必须是2的N次方(2^N),否则会出现错误的,另外可能由于SDRAM数据同步问题,如果接收数据的是SDRAM上的内存空间,结果会打印:Transfer failed !即,在比较两个空间数据时会出现不相等,但是调试的时候是可以,虽然我做了延时5秒钟,但是还是不能解决,希望高手解答!如果接收数据的是ON_CHIP_MEM的话是完全没有问题的。
