风波邪人

幸福,幸福就是心里有那么一个人,不管你走到哪儿,也不管她走到哪儿,心里永远想着她

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

       

      DMA(Direct Memory Access)直接存储器传输,是指将外设的数据不经过微处理器直接传送到存储器中,或者,从存储器不经过微处理器直接将数据传送至外部设备。一次DMA传输只需要执行一个DMA周期(相当于一个总线时钟周期),因而能显著提高数据传输速度,以满足某些告诉外设的需求。在FPGA中,在进行DMA传输时需要一个DMA控制器,来协调外设接口和存储器的数据传输。SOPC Builder内部集成了一个DMA控制器部件,可非常容易的将其添加到SOPC系统,对于Nios II处理器,DMA控制器IP核的设备驱动程序在HAL系统库中提供。

       在Nios II HAL的DMA设备模型中,DMA传输归为两类:发送和接收。因此,HAL也提供了两套驱动分别完成DMA的发送和接收通道。发送通道负责将数据从源设备发送到目标设备,接收通道负责从源设备接收数据并存放于目标设备。

DMA传输按照原设备和目标设备的不同分为以下3中类型:

1. 外设——>存储器,接收传输

2. 存储器——>外设,发送传输

3. 存储器之间,同时实现发送和接受传输

在Nios II HAL的API中,对于存储器一方,即传输时产生地址自增的一方,需要打开一个接收或发送的通道。如果是地址固定的一方(外设),则不需要打开通道。以下为3种方式创建通道的代码:

1. 外设 ----> 存储器

// 打开接收通道 rx

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

// 指定源设备地址 source_addr

alt_dma_rxchan_ioctl(rx, ALT_DMA_RX_ONLY_ON, (void*)source_addr);

// 指定目标设备地址 rx_buf、传输数据块长度length以及DMA中断处理函数dma_done

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

2. 存储器 ----> 外设

// 打开发送通道 tx

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

// 指定目标备地址 dst_addr

alt_dma_txchan_ioctl(tx, ALT_DMA_TX_ONLY_ON, (void*)dst_addr);

// 指定目标设备地址 tx_buf、传输数据块长度length以及DMA中断处理函数dma_done

dma_res = alt_dma_txchan_prepare(tx, tx_buf, length, dma_done, NULL);

3. 存储器 ----> 存储器

// 打开接收通道 rx

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

// 指定目标设备地址 rx_buf、传输数据块长度length以及DMA中断处理函数dma_done

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

// 打开发送通道 tx

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

// 指定目标设备地址 tx_buf、传输数据块长度length以及DMA中断处理函数dma_done

dma_res = alt_dma_txchan_prepare(tx, tx_buf, length, dma_done, NULL);

 

例程:

#include <stdio.h>
#include <string.h>
#include "system.h"
#include "sys/alt_dma.h"

int dma(void)
{
    alt_dma_rxchan rx;
    //创建DMA接收通道
    rx = alt_dma_rxchan_open("/dev/dma");
    //如果信道创建成功
    if(rx != NULL)
    {
        printf("Dma transition start.\n");
        while(1)
        {
            //设置DMA传输的数据位宽
            alt_dma_rxchan_ioctl(rx, ALT_DMA_SET_MODE_8, NULL);
            //指定从uart接收数据
            alt_dma_rxchan_ioctl(rx, ALT_DMA_RX_ONLY_ON, (void*)UART_BASE);
            //提交DMA接收请求,指定接收数据的位置(SDRAM)以及传输数据量
            if(alt_dma_rxchan_prepare(rx,
                                      SDRAM_BASE,
                                      1024,
                                      NULL,
                                      NULL) < 0
                                      )
            {
                printf("Error: failed to post receive request\n");
            }
            //关闭DMA接收信道
            alt_dma_rxchan_close(rx);
            usleep(100*1000);
        }
    }
    return 0;
}

posted on 2011-12-26 11:54  风波邪人  阅读(1162)  评论(0编辑  收藏  举报