Calendar
载入中。。。
Placard
载入中。。。
Category
载入中。。。
Latest Entries
载入中。。。
Latest Comments
载入中。。。
Last Messages
载入中。。。
User Login
载入中。。。
Links
Information
载入中。。。
Search
Other


Welcome to my blog!
  Nios II Step By Step 3--Nios II 中的DMA
 

有了上一讲HAL的基础,我们来关注一下DMANIOS 中的实现和编程。DMA是个老问题了,从8086/8088一直到现在,完成不需要CPU参与的数据搬家,源和目标可以是内存也可以是设备,在NIOS II中通过基于HAL编程完成。
  
下图是三中基本的DMA传输:

 NIOS IIHAL DMA设备模式中,DMA传输被分为两类:transmit  receiveNIOS提供两种设备驱动实现transmit channelsreceive channelstransmit channels把缓冲区数据发送到目标设备,receive channels读取设备数据存放到缓冲区。
   
为了适应大家不同的开发环境,下面我们完成一个相对简单的DMA操作,复制SDRAM内存缓冲区到on_chip_memory中,如果我们在库工程属性中设置了SDRAM为主内存,那么程序中分配的数组缓冲区就在SDRAM中,我们用指针赋值让指针指向on_chip_memory。这个操作完全可以在程序中用memcpy来实现,我们趋简就繁,就是为了尝试一下DMAJ
   
首先我们在SOPC Builder中增加一个名字为dma_0DMA设备。两个表单设置都选默认。

 第二步,DMA设备有三个PORT,两个MASTER PORT:read_masterwrite_master,一个SLAVE PORT:control_port_slave。需要在SOPC BUILDER中设置AVALONE交换总线,设置read_mastersdram连接,write_masteron_chip_memory连接,具体见下图(交叉点为黑色)

sopc builder中生成系统,并在Quartus II中编译下载,硬件部分就OK了。如果你的DMA操作不是内存到内存的,而是内存到设备,或者设备到内存,那么你需要在上面这一步中加以设置,设备只支持读写,是CPU读写还是DMA读写设备不加以区分。
在程序中,我们要使用DMA必须包含:sys/alt_dma.h
因为是内存DMA操作,所以我们必须实现transmit channelsreceive channels,这在NIOS II中就是打开两个设备。在NIOS II IDE中生成一个以Hello World为模板的memory_dma工程项目修改一下程序如下:
#i nclude <stdio.h>
#i nclude <stdlib.h>
#i nclude <sys/alt_dma.h>
#i nclude "system.h"

static volatile int rx_done = 0;

/*
*   Callback function that obtains notification that the data has
*   been received.
*/
static void done (void* handle, void* data)
{
  rx_done++;
}

int main (int argc, char* argv[], char* envp[])
{
  int rc;
  static char buff[256];
  alt_dma_txchan txchan;
  alt_dma_rxchan rxchan;

  void* tx_data = (void*) buff;                 /* pointer to data to send */
  void* rx_buffer = (void*) 0x01000000; /* on_chip_memory addr*/
  
  /* Create the transmit channel */
  if ((txchan = alt_dma_txchan_open("/dev/dma_0")) == NULL)
  {
    printf ("Failed to open transmit channel\n");
    exit (1);
  }

  /* Create the receive channel */
  if ((rxchan = alt_dma_rxchan_open("/dev/dma_0")) == NULL)
  {
    printf ("Failed to open receive channel\n");
    exit (1);
  }
  /* Post the transmit request */
  if ((rc = alt_dma_txchan_send (txchan,
                                  tx_data,
                                  128,
                                  NULL,
                                  NULL)) < 0)
  {
    printf ("Failed to post transmit request, reason = %i\n", rc);
    exit (1);
  }
  
  /* Post the receive request */
  if ((rc = alt_dma_rxchan_prepare (rxchan,
                                    rx_buffer,
                                    128,
                                    done,
                                    NULL)) < 0)
  {
    printf ("Failed to post read request, reason = %i\n", rc);
    exit (1);
  }
   
   
   /* wait for transfer to complete */
    while (!rx_done);
        printf ("Transfer successful!\n");
    return 0;
}
我们很多人对DMA理解的很深入,在其他嵌入式领域有丰富的经验,在其他系统上的实现问题很自然会想在NIOS II中是怎么完成的呢,比如DMA完成以后需要中断吗?如何知道DMA传输完成等等,在上面的程序中,实际上是通过回调函数完成的,回调函数在Windows系统的WIN API中以及驱动开发中被大量使用。
   
好了,DMA就是如此,还有一些相关的函数需要去尝试一下。尝试非常重要,在资料欠缺的时候,需要创建环境去实验,你的理解是这样的,按这样的理解会有这样的结果,实际做一下到底是怎样的,不符合?是理解错了吗?不断尝试,收益无限

[ 阅读全文 | 回复(0) | 引用通告 | 编辑

  Post  by  jearome 发表于 2006-9-6 12:23:00
发表评论:
载入中。。。
载入中。。。