1. NIOS2 DMA控制器结构框图
与其它IP外设一样,DMA控制器也是通过AVALON MM总线,实现寄存器配置,数据读写功能。
3. NIOS2 DMA API函数
NIOS2 DMA的API函数原型都定义在alt_dma.h头文件中,常用的API函数如下:
alt_dma_txchan alt_dma_txchan_open (const char* name);
static ALT_INLINE int alt_dma_txchan_send (alt_dma_txchan dma,
const void* from,
alt_u32 length,
alt_txchan_done* done,
void* handle)
{
return dma ? dma->dma_send (dma,
from,
length,
done,
handle) : -ENODEV;
}
static ALT_INLINE int alt_dma_txchan_ioctl (alt_dma_txchan dma,
int req,
void* arg)
{
return dma ? dma->ioctl (dma, req, arg) : -ENODEV;
}
alt_dma_rxchan alt_dma_rxchan_open (const char* dev);
static ALT_INLINE int alt_dma_rxchan_prepare (alt_dma_rxchan dma,
void* data,
alt_u32 len,
alt_rxchan_done* done,
void* handle)
{
return dma ? dma->prepare (dma, data, len, done, handle) : -ENODEV;
}
static ALT_INLINE int alt_dma_rxchan_ioctl (alt_dma_rxchan dma,
int req,
void* arg)
{
return dma ? dma->ioctl (dma, req, arg) : -ENODEV;
}
4. 参考设计——OnchipMenmory to SDRAM
1) Qsys设置
NIOS2代码运行在SDRAM中,OnchipMemory作为一个片上存储外设。
下面两个图是QSYS中的IP设置,图中可以看出DMA支持BURST读写模式,这样效率会大大提高。
在第二张图片中,博主勾选了show signals选项,可以看到,DMA组件定义的信号接口,有一个AVALON MM SLAVE端口,用于配制寄存器,两个AVALON MM MASTER分别实现读写功能,还有一个IRQ中断输出,向CPU产生中断信号。
2)软件源码
//file name: main.c
//date: 2016.8.15
//author: shugen.yin
//function: DMA, onchip memory to sdram/ddr2
//log:
#include <stdio.h>
#include <string.h>
#include <sys/alt_irq.h>
#include "system.h"
#include "alt_types.h"
#include "sys/alt_dma.h"
#define DAT_LEN 32
unsigned int buffer0[DAT_LEN/4];
unsigned int *point=ONCHIP_MEMORY1_0_BASE;
static void DMA_Init(void); //初始化DMA
unsigned int dma_end_flag = 0;
alt_dma_txchan tx;
alt_dma_rxchan rx;
void dma_done()
{
dma_end_flag++;
}
static void DMA_Init(void)
{
tx = alt_dma_txchan_open("/dev/dma_0");
if(tx != NULL)
{
printf("DMA transition start\n");
}
alt_dma_txchan_ioctl(tx,ALT_DMA_SET_MODE_32,NULL);
//point是源地址、传输数据块长度是DAT_LEN
alt_dma_txchan_send(tx, point, DAT_LEN, NULL, NULL);
rx = alt_dma_rxchan_open("/dev/dma_0");
alt_dma_rxchan_ioctl(rx,ALT_DMA_SET_MODE_32,NULL);
//buffer0是目标地址、传输数据块长度是DAT_LEN、dma_done()是DMA完成后被调用的回调函数
alt_dma_rxchan_prepare(rx, buffer0 , DAT_LEN, dma_done, NULL);
}
int main()
{
int i;
for(i=0;i<DAT_LEN/4;i++)
buffer0[i] = 0;
for(i=0;i<DAT_LEN/4;i++)
*(point+i) = i+1;
//初始化DMA
DMA_Init();
//等待中断结束,说明传输完成
while(dma_end_flag == 0)
{
}
//打印接收地址的数据
for(i=0;i<DAT_LEN/4;i++)
{
printf("buffer0[%d]=%d\t",i,buffer0[i]);
}
alt_dma_txchan_close(tx);
alt_dma_rxchan_close(rx);
return 0;
}
转载于:https://blog.51cto.com/shugenyin/1839585