• [转载].基于Nios II的DMA传输


    转门金瑞兄的博文:http://www.cnblogs.com/menjr/archive/2010/05/04/1727226.html

    关于DMA传输的实验。

    在系统运行时,当需要传输大量数据时,可以采用DMA的方式进行传输,以解脱出CPU来处理其他命令。

    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通过UART发送和接收数据的例子,注意DMA_0为接受通道,DMA_1为发送通道。当然可以将dma的read_master和writer_master同时连在uart_0和sdram_0的从端口上,这样是可以用一个dma对两者读写操作,但是不能同时做双向传输。

    #include <stdio.h>
    #include <string.h>
    #include "system.h"
    #include "sys/alt_dma.h"
    #include "unistd.h"
    
    int main(void)
    {/*
        alt_dma_rxchan rx;
        //创建DMA接收信道
        rx = alt_dma_rxchan_open("/dev/dma_0");
        //当信道创建成功
        if(rx != NULL)
        {
            printf("Dma transition start.");
            while(1)
            {
                //设置DMA传输的数据位宽 本例中为8位
                alt_dma_rxchan_ioctl(rx,ALT_DMA_SET_MODE_8,NULL);
                //指定从uart接收数据
                alt_dma_rxchan_ioctl(rx,ALT_DMA_RX_ONLY_ON,(void*)UART_0_BASE);
                
                //提交DMA接收请求 指定接收数据的位置(sdram)以及传输数据量
                if(alt_dma_rxchan_prepare(rx, 
                                           SDRAM_0_BASE, 
                                           1024, 
                                           NULL, 
                                           NULL) < 0)
                {
                    printf ("Error: failed to post receive request\n");
                }
                //关闭DMA接收信道
                alt_dma_rxchan_close(rx);
                usleep(1000000);
            }
        }
        
       */
        alt_dma_txchan  tx;
        tx = alt_dma_txchan_open("/dev/dma_1");
         if(tx != NULL)
        {
            printf("Dma transition start.");
        while(1)
            {    
                alt_dma_txchan_ioctl(tx,ALT_DMA_SET_MODE_8,NULL);
                alt_dma_txchan_ioctl(tx,ALT_DMA_TX_ONLY_ON,(void*)(UART_0_BASE+2));
    
              //注意是UART_0_BASE+2,因为UART的txdata寄存器在rxdata之后,偏移量为一个rxdata的长度(16位,2个字节)
                    if(alt_dma_txchan_send(tx, 
                                           SDRAM_0_BASE, 
                                           1024, 
                                           NULL, 
                                          (void*) NULL) < 0)
                {
                    printf ("Error: failed to post transmit request\n");
                }
                //关闭DMA发送信道
                alt_dma_txchan_close(tx);
                usleep(1000000);
            }
        }
        return 0;
    }
  • 相关阅读:
    一般查找 (顺序查找)
    sscanf
    uva-11044-水题
    uva-10785-模拟水题
    uva-10596-欧拉回路
    uva-10879-因数分解
    uva-10562-二叉树
    扯皮的cplex-感觉时间不对
    cplex-Java-样例代码解析
    cplexJava源码---计算结果
  • 原文地址:https://www.cnblogs.com/yuphone/p/1730896.html
Copyright © 2020-2023  润新知