Altera Scatter-Gather DMA (SG-DMA)的简单使用
文章来源:http://www.cnblogs.com/scnutiger/archive/2010/02/06/1664980.html
在Quartus7.2之后的版本中,除了原有的基于avalon-mm总线的DMA之外,还增加了Scatter-Gather DMA这种基于avalon-ST流总线的DMA IP核,它更适合与大量数据流传输的场合,使用起来比较灵活,增加了与外设流器件配合的能力。由于网上关于SG-DMA介绍的资料比较少,因此这里简单介绍一下SG-DMA的使用,利用它可以搭配Altera的千兆网MAC核来实现千兆网方面的应用。
SG-DMA的数据手册已经介绍得非常详细,具体的相关寄存器和功能可能查阅相关手册。Altera为了开发的便利,已经为各个IP核设计好了HAL软件层的代码,SG-DMA也不例外,因此使用的时候我们没有必要逐个配置相关寄存器,直接调用HAL层代码即可。这也是使用这类IP核简便的地方,只是需要清楚这类代码如何调用。
1. 首先我们简单看看SG-DMA的应用环境,从数据手册中截下几张图片简单介绍。
SG-DMA有三种工作方式,可以工作在Memory-to-Stream即存储接口到流接口,或者Stream-to-Memory即流接口到存储接口,以及Memory-to-Memory的存储器到存储器工作方式。工作在存储器到存储器的工作方式与普通DMA并无差别,没有数据流处理的优势。另外SG-DMA增加了Descriptor Processor,可以实现批量工作,从而进一步减轻Nios处理器的工作。只需要将Descriptor命令字写入到相应的Descriptor memory中。我们简单看看以上的工作方式。
图1. Memory-to-Stream
图2. Stream-to-Memory
图3. Memory-to-Memory
2. 然后我们直接进入主题,看在Altera的SOPC中如何连接使用SG-DMA器件。
M-to-M模式就不做介绍了,这里主要介绍M-to-S和S-to-M这两种方式。我们添加两个SG-DMA器件,让它们分别工作在这两个工作方式下。连接示意如下所示。注意到其中的descriptor memory的设置,原则上只要带有avalon-mm接口的存储器都可以用来做descriptor memroy,因此我们可以将decriptor memory与主存分离,亦可以直接使用主存的一部分作为descriptor memroy。但为了不影响主存的使用,最好将descriptor memroy分离。另外SG-DMA的有关设置,例如channel和error的位数控制可以参考avalon-st流接口数据手册,依照需要设置接口。由于在本例中只有一个通道,也不校验错误,所以我们都设置为零。
图4. SOPC连接示意图
3. SG-DMA HAL代码调用。
要使得SG-DMA正式工作起来,我们可以直接调用HAL层代码,省去很多开发时间。下面直接使用一段程序,添加部分注释,相信SG-DMA的基本使用即可完成了,并没有想象中的这么复杂。
#include <stdio.h>
#include "altera_avalon_sgdma_descriptor.h"
#include "altera_avalon_sgdma_regs.h"
#include "altera_avalon_sgdma.h"
#include "system.h"
#include "alt_types.h"
//注意包含这几个头文件alt_sgdma_dev *sgdma_tx_dev; //sgdma_tx设备文件
alt_sgdma_dev *sgdma_rx_dev; //sgdma_rx设备文件
alt_sgdma_descriptor *desc; //descriptor memory指针char buf[1000]; //SG-DMA传送缓存,暂定1000字节做测试
alt_u32 rx_payload[256]; //SG-DMA接收缓存void sgdma_rx_isr(void * context, u_long intnum);
//我们的基本思路就是,先配置好sgdma_rx和sgdma_tx的基本配置,然后设置好sgdma_rx的回调函数。
//即接收数据完成之后调用的函数,最后启动sgdma_tx完成dma发送。在这个过程中涵盖了sgdma_tx和sgdma_rx的基本使用
int main()
{int i;int timeout = 0;for(i=0; i<1000; i++) //填充缓存数据buf[i] = i%256;//重定义desc DISCRIPTOR_MEMORY_BASE定义在system.h中,即descriptor_memory的基地址desc = (alt_sgdma_descriptor *)DISCRIPTOR_MEMORY_BASE;//打开sgdma_tx和sgdma_rxsgdma_tx_dev = alt_avalon_sgdma_open(SGDMA_TX_NAME); //SGDMA_TX_NAME定义为"/dev/sgdma_tx"if(!sgdma_tx_dev) {printf("[triple_speed_ethernet_init] Error opening TX SGDMA\n");return -1;}sgdma_rx_dev = alt_avalon_sgdma_open(SGDMA_RX_NAME);if(!sgdma_rx_dev) {printf("[triple_speed_ethernet_init] Error opening RX SGDMA\n");return -1;}/* Reset RX-side SGDMA */IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_RX_BASE, ALTERA_AVALON_SGDMA_CONTROL_SOFTWARERESET_MSK);IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_RX_BASE, 0x0);/* Reset TX-side SGDMA */IOWR_ALTERA_AVALON_SGDMA_CONTROL(SGDMA_TX_BASE, 0);IOWR_ALTERA_AVALON_SGDMA_STATUS(SGDMA_TX_BASE, 0xFF);//注册sgdma_rx回调函数alt_avalon_sgdma_register_callback(sgdma_rx_dev,(alt_avalon_sgdma_callback) &sgdma_rx_isr,(alt_u16)ALTERA_AVALON_SGDMA_CONTROL_IE_DESC_COMPLETED_MSK | \ALTERA_AVALON_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK | \ ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK,
);//填充发送decriptor memory 并不需要自己填充,调用函数就好了。alt_avalon_sgdma_construct_stream_to_mem_desc(&desc[0], //主描述字&desc[1], //次描述字rx_payload,
,
);//填充接收decriptor memory alt_avalon_sgdma_construct_mem_to_stream_desc(&desc[2], //主描述字&desc[3], //次描述字(unsigned int*)buf, //发送指针(256), //发送字数
,
,
,
);//启动sgdma_rx和sgdma_txalt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, &desc[0]);alt_avalon_sgdma_do_sync_transfer(sgdma_tx_dev, &desc[2]);
}//回调函数,负责处理接收后数据,并重置sgdma_rx,本例中并未对数据进行处理
void sgdma_rx_isr(void * context, u_long intnum);
{int sgdma_status = IORD_ALTERA_AVALON_SGDMA_STATUS(SGDMA_RX_BASE);alt_sgdma_descriptor *currdescriptor_ptr = &desc[0];if(sgdma_status & (ALTERA_AVALON_SGDMA_STATUS_CHAIN_COMPLETED_MSK | ALTERA_AVALON_SGDMA_STATUS_DESC_COMPLETED_MSK) ) {desc_status = IORD_ALTERA_TSE_SGDMA_DESC_STATUS(currdescriptor_ptr);if( (desc_status & (ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_CRC_MSK | ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_PARITY_MSK | ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_OVERFLOW_MSK |ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_SYNC_MSK | ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_UEOP_MSK | ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_MEOP_MSK | ALTERA_AVALON_SGDMA_DESCRIPTOR_STATUS_E_MSOP_MSK ) ) == 0){printf("RX descriptor reported OK\n");} else {printf("RX descriptor reported error\n");}IOWR_32DIRECT(&(currdescriptor_ptr->write_addr), 0, (alt_u32)(rx_payload)); IOWR_32DIRECT(&(currdescriptor_ptr->actual_bytes_transferred), 0, (alt_u32) ((ALTERA_AVALON_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK |ALTERA_AVALON_SGDMA_DESCRIPTOR_CONTROL_GENERATE_EOP_MSK) << 24) );// Re-start SGDMA (always, if we have a single descriptor)alt_avalon_sgdma_do_async_transfer(sgdma_rx_dev, &desc[0]);}
}
Altera Scatter-Gather DMA (SG-DMA)的简单使用相关推荐
- 【Xilinx DMA SG】Xilinx DMA SG 模式
DMA简介: AXI 直接存储器访问 (AXI DMA) IP 提供高带宽直接存储器 AXI4 存储器映射和 AXI4-Stream IP 接口之间的访问.它SG模式还可以从中央处理中卸载数据移动任务 ...
- AXI SG DMA 简易驱动 版本构思 (一)
第一步: 利用mmap 在内核态和用户态形成内存映射关系,和进程间通信 shmat 的原理 一致 (节省内存,如果拷贝的话就是, double的关系) 第二步: mmap的 地址要映射到,dma 分配 ...
- JavaNIO - Scatter Gather
Scatter & Gather指在多个缓冲区上实现一个简单的 I/O 操作.减少或避免了Buffer间的拷贝和系统调用. Channel Write操作 Write操作 Channel Re ...
- NIO - Scatter/Gather
1.Scatter 从一个Channel读取的信息分散到N个缓冲区中(Buufer). 2.Gather 将N个Buffer里面内容按照顺序发送到一个Channel. Scatter/Gather ...
- RDMA技术详解(三):理解RDMA Scatter Gather List
1. 前言 在使用RDMA操作之前,我们需要了解一些RDMA API中的一些需要的值.其中在ibv_send_wr我们需要一个sg_list的数组,sg_list是用来存放ibv_sge元素,那么什么 ...
- 【Java NIO的深入研究6】JAVA NIO之Scatter/Gather
Java NIO开始支持scatter/gather,scatter/gather用于描述从Channel(译者注:Channel在中文经常翻译为通道)中读取或者写入到Channel的操作. 分散(s ...
- Java NIO系列教程(四) Scatter/Gather
转载自 Java NIO系列教程(四) Scatter/Gather 译文地址 作者:Jakob Jenkov 译者:郭蕾 Java NIO开始支持scatter/gather,scatte ...
- java nio 系列教程 四_Java NIO系列教程(四) Scatter/Gather
作者:Jakob Jenkov 译者:郭蕾 Java NIO开始支持scatter/gather,scatter/gather用于描述从Channel(译者注:Channel在中文经常翻译为通道) ...
- 【STM32】HAL库 STM32CubeMX教程十一---DMA (串口DMA发送接收)
前言: 本系列教程将 对应外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 所用工具: 1.芯片: STM32F407ZET6/ STM32F103ZET6 ...
- STM32CubeMX | HAL库的ADC多通道数据采集(轮训、DMA、DMA+TIM)、读取内部传感器温度
STM32CubeMX | HAL库的ADC多通道数据采集(轮训.DMA.DMA+TIM).读取内部传感器温度 目录 STM32CubeMX | HAL库的ADC多通道数据采集(轮训.DMA.DMA+ ...
最新文章
- JBoss下布署Spring2.5和Struts2系统
- 编程之美求二进制数中1的个数扩展题
- Vagrant挂载目录失败mount: unknown filesystem type ‘vboxsf’
- 基于RNN和CTC的语音识别模型,探索语境偏移解决之道
- 滚动时间选择器recyclerview_Android自定义可循环的滚动选择器CycleWheelView
- 通过MDaemon自带功能,实现同部门用同一账号对外收发邮件
- pe我的手机服务器存档文件,我的世界手机版怎么导出存档 pe版怎么把存档给别人用...
- nodejs学习笔记-1-文件系统
- Android 分享到新浪微博
- vue 使用 createjs 绘制扇形
- xp访问共享文件夹需要重启服务器,winXP共享文件夹断开、重新连接、重设置密码的方法...
- C# 判断文件是否在使用的状态FSDF
- gdown配置代理下载Google drive文件
- 康宁发布第五代大猩猩玻璃 坚韧度更强更耐摔
- java左手画圆右手画方_左手画圆、右手画方,双手齐用同时养护、开发你的左右大脑!...
- 植物大战僵尸数据修改总结
- 安全邮箱是什么,163邮箱安全中心,安全邮箱怎么注册?
- 使用python计算贝尔宾团队角色测评结果
- Unity3d用户手册用户攻略缓存效劳器常见疑问
- 示波器测量晶振、万用表测量晶振的方法