Nios II中的DMA传输

本文详细介绍了Nios II系统中DMA(直接内存存取)的三种主要传输方式:存储器到存储器、存储器到外设及外设到存储器,并提供了具体的编程实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 Nios II中的DMA传输有以下三种形式:


1、  存储器到存储器


这种情况下需要同时打开发送通道和接收通道,而且源地址和目标地址都是自增的。


tx = alt_dma_txchan_open("/dev/dma_0");//打开发送通道


dma_res = alt_dma_txchan_send(tx, tx_buf, 32, NULL, NULL);  // tx_buf是源地址


rx = alt_dma_rxchan_open("/dev/dma_0");//打开接收通道


dma_res = alt_dma_rxchan_prepare(rx, rx_buf, 32, dma_done, NULL); // rx_buf是目标地址,dma_done()是DMA完成后被调用的回调函数。


 


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, 32, 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, 32, dma_done, NULL);  // rx_buf是目标地址


 


其中通过alt_dma_txchan_ioctl,alt_dma_rxchan_ioctl还可以设置每次发送和接收的字节数。







       下面给出两个实例,说明DMA传输的过程。


 


1、  存储器到存储器


下面程序为SDRAM到onchip-memory的数据传输。


硬件连接图示:


点击看大图


程序如下:


#include <stdio.h>


#include <stdlib.h>


#include <sys/alt_dma.h>


#include "system.h"


static volatile int rx_done = 0;


int rc;


alt_dma_txchan txchan;


alt_dma_rxchan rxchan;


static char buff[256];


void* tx_data = (void*) buff; /* 源地址 */


void* rx_buffer = (void*) 0x01801000; /* 目标地址,从上图看到0x01801000为onchip-memory的地址*/


//DMA传输结束回调函数


static void done_t(void* handle, void* data)


{


   


    rx_done++;


   


}


 


int main (int argc, char* argv[], char* envp[])


{


 


/* 打开发送通道 */


  if ((txchan = alt_dma_txchan_open("/dev/dma")) == NULL)


  {


    printf ("Failed to open transmit channel\n");


    exit (1);


  }


/* 打开接收通道 */


  if ((rxchan = alt_dma_rxchan_open("/dev/dma")) == NULL)


  {


    printf ("Failed to open receive channel\n");


    exit (1);


  }


/* 开始发送数据 */


  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);


  }


/* 开始接收数据*/


  if ((rc = alt_dma_rxchan_prepare (rxchan,


                                    rx_buffer,


                                    128,


                                    done_t,


                                    NULL)) < 0)


  {


    printf ("Failed to post read request, reason = %i\n", rc);


    exit (1);


  }


/* 等待传输结束 */


  while (!rx_done);


  printf ("Transfer successful!\n");


 


  return 0;


}


程序运行结束后在Nios IDE的console界面中显示:


Transfer successful!


表明传输成功。


 


2、  存储器到UART


下面程序为SDRAM到UART的数据传输


硬件连接图:


点击看大图


程序如下:


#include <stdio.h>


#include <stdlib.h>


#include "sys/alt_dma.h"


#include "altera_avalon_uart_regs.h"


#include "system.h"


#include "alt_types.h"


 


static volatile int tx_done = 0;


volatile static alt_u8 chr[20] = {1,2,3,4,6,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20} ;//待发送的数据


//回调函数


static void done (void* handle)


{


tx_done++;


}


int main()


{


int rc;


alt_dma_txchan txchan;


 


void* source_buff_ptr = (void*) chr; /* 源地址 */


void* destination_buff_ptr = (void*)IOADDR_ALTERA_AVALON_UART_TXDATA(UART_BASE); /* 目标地址IOADDR_ALTERA_AVALON_UART_TXDATA(UART_BASE)函数读出txdata的地 */


 


/* 打开发送通道 */


if ((txchan = alt_dma_txchan_open("/dev/dma")) == NULL)


{


printf ("Failed to open transmit channel\n");


exit (1);


}


/* 设置目标地址固定 */


if ((rc = alt_dma_txchan_ioctl(txchan, ALT_DMA_TX_ONLY_ON, destination_buff_ptr)) < 0)


{


printf ("Failed to set ioctl, reason = %i\n", rc);


exit (1);


}


//设置每次发送一个字节,即8位,因为UART每次只发送8


if((rc = alt_dma_txchan_ioctl(txchan,ALT_DMA_SET_MODE_8 ,NULL))<0)


{


    printf("Failed to set mode 8\n");


    exit(1);


}


/* 开始发送 */


if ((rc = alt_dma_txchan_send(txchan, source_buff_ptr, 20, done, NULL)) < 0)


{


printf ("Failed to post transmit request, reason = %i\n", rc);


exit (1);


}


/* 等待发送结束 */


while (!tx_done);


printf ("Transfer successful!\n");


return 0;


}


不过该程序执行结束后,在串口调试器中显示Transfer successful!却没有显示DMA发送的那20个数字。不知道哪里需要修改,放在这里和大家讨论下。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值