am335 dma

AM335X DMA 驱动设计

AM335X的EDMA与以往的处理器的DMA有所不同,而我手头上只有AM335X的Technical Reference Manual以及PSP User's Guide,还有PPC的DMA驱动源码,可用的资料不多,自己一个人摸索,一路走来,遇到不少困难,甚至产生了想要放弃的念头。然而为了工作,为了生活,不得不咬紧牙关,迎难而上。皇天不负有心人,经过整整三周的艰苦奋斗,终于把问题给解决了。经此一役,深感技术交流与讨论的重要,为了后来的同学们能少走些弯路,特此将自己的开发经历书写成文,以供参考,希望能对大家有益。

做驱动开发的,如果对硬件不了解,根本做不出来,即使一不小心做出来了,也未必能够尽量使用硬件的特性,做到最好的优化,代码写得再好看也不高效。所以,首先对AM335X 的EDMA进行一个简单的介绍,如果要详细了解,则建议参阅AM335X的Technical Reference Manual,虽然是全英文版的,但是原汁原味的,更能理解芯片设计者的本意,比国内翻译版本的要好多了。

 

一、AM335X EDMA简介

1、EDMA(Enhanced Direct Memory Access)是增强型的DMA控制器,用于控制存储器与存储器、存储器与外设、外设与外设之间的数据传输。其结构主要包含TPCC(Third-Party Channel Controller)与TPTC(Third-Party Transfer Controller)两大部分,即通道控制器与传输控制器,如图1所示。

                                    图 1

2、通道控制器(Channel Controller)

主要功能:通道选择,事件(event)管理,向传输控制器递交传输请求(transfer request),向CPU发出完成中断(transfer completion);EDMA中有64个DMA通道,8个快速DMA通道,95个事件。其结构框图如图2所示:

                                    图2

 

DMA传输参数(源地址、目的地址、数据长度/宽度等)由一组parameter RAM set(在Linux 3.2.0系统中称之为slot)决定,启动DMA之前须配置这些参数。如图3所示:

                                 图3

       在PaRAM set中,OPT字段很重要,其含义参看11.3.3.2.1 Channel Options Parameter (OPT)部分,这里讲讲我在自己驱动所用到的几个选项(options):

(1)ITCINTEN:中间传输完成中断,用于一次传输请求(TR)完成后,产生一个chained event,触发下一个TR。如果你的外设不能触发TR,并且在驱动中用到了三维传输(3D transfer),而你又想在启动DMA之后让他自动完成传输,则要设置这个标志;

       (2)TCINTEN:传输完成中断,用于完成DMA传输之后,向CPU发出中断请求,把总线控制权交还CPU;

 

(3)TCCHEN:传输完成链接(chaining,暂且翻译为链接吧),用于在耗尽(exhausted)一个PaRAM set(Linux中称之为slot)之后,链接到下一个你指定的下一个PaRAM set;

(4)TCC:传输完成码,用于链接或者中断;

(5)FWID:FIFO宽度,最小8bit,最大256bit,当你的外设有一个数据移位寄存器,支持分页读写时,可设置这一标志,FIFO宽度既是你的外设的宽度。此时,地址编址模式必须设置为常地址模式(Constant addressing mode);

(6)SAM/DAM:源/目的地址编址模式,有两种,一是INR模式,表示传输一个array进行一次编址(addressing),编址之后才能把数据写进目的地址;另一种是FIFO,表示达到FIFO宽度之后进行一次编址,与(5)同时使用;当选择FIFO模式时,地址必须扩展对齐到256bit,即源/目的地址以256bit为单位对齐,前后两个地址之间相差256bit;

(7)STATIC:静止位,设为1时,完成一次TR不更新(update)PaRAM set,设为0时,完成一次TR更新PaRAM set;在3D transfer中,须把这一位设置为0;

(8)SYNCDIM:传输类型选择,A同步(synchronization)或AB同步,设为A同步时,一次TR传输一个array的字节,设为AB同步时,一次TR传输一个frame的字节。

OPT字段设置完成后,还须设置源地址,目的地址,ACNT,BCNT,CCNT,SRCBIDX, SRCCIDX,DESTBIDX,DESTCIDX等,这些会在后面提到。

 

3、传输控制器(Transfer Controller)

主要功能:接收TPCC的传输请求,产生读写命令,负责数据传送,传输完成回交TPCC。其结构框图如图4所示:

                                                 图4

 

4、传输类型(Types of EDMA3 Transfers)

与以往的DMA控制器不同,EDMA传输被定义为一个三维传输(3D transfer),如图5所示。

 

                                 图5

第一维:array,一个array里有acnt个字节,acnt是一个16位无符号数,取值可在1~65535之间,取0值时DMA传输变为null transfer或者dummy transfer;

第二维:frame,一个frame里有bcnt个array,bcnt是一个16位无符号数,取值可在1~65535之间,取0值时DMA传输变为null transfer或者dummy transfer;

第三维:block,一个block里包含ccnt个frame,ccnt是一个16位无符号数,取值可在1~65535之间,取0值时DMA传输变为null transfer或者dummy transfer;

与此对应的,EDMA传输类型分成A同步传输(A-synchronized transfer)与AB同步传输(AB-synchronized transfer)两种。A同步即一次传输请求(TR)传输一个array的数据,完成整个DMA传输须触发bcnt*ccnt次TR;AB同步即一次TR传输一个frame的数据,完成整个DMA传输须触发ccnt次TR。

5、DMA工作流程

DMA工作流程主要包括:向CPU发出DMA请求àDMA控制器获得总线控制权,CPU继续执行内部操作àDMA控制器负责数据传输à数据传输完成向CPU发出完成中断,将总线控制权交还CPU。

 

在linux下使用am335x的DMA

2017年07月15日 20:35:00 weixin_33924220 阅读数:14

[本文首发于cnblogs,作者:byeyear,Email:east3@163.com]

这几天在弄am3358的DMA,简化应用环境如下:

am3358的FSMC接了一片FPGA;

FPGA上接ADC;

am3358通过FPGA以DMA方式读取ADC数据。

事先在网上查找过相关资料,发现关于这方面工作的文章极少,即使TI官网上也没什么可靠资料,心里还是有些忐忑的,结果在实现过程中发现意外的简单,所以把过程写下来,希望有相似需求的同行可以少走弯路。

注意:阅读本文要求具备一定的linux设备驱动开发经验,如果您从没有做过linux驱动开发,那么阅读本文时可能会有一定的困难。

文章基于TI提供的Linux SDK 3.0。

1. 引脚配置

引脚配置分两块:FSMC引脚配置和外部DMA请求引脚配置。这里建议大家到TI网站上下载它的pinmux工具,点点鼠标就可以生成devicetree,非常直观简单,所以就不展开讲了。

2. 外部DMA请求形式

在TI的处理器手册上没有找到外部DMA引脚请求形式,不过一般来说不外乎上升沿或下降沿两种,所以我偷了个懒,使用一个1us宽度的正脉冲来提交DMA请求。

3. crossbar配置

crossbar的配置可以参照Linux内核文档Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt。我使用了DMA Channel 58和Transfer Controller 1,所以我的devicetree文件有如下内容:

dmas=<&edma_xbar 58 1 28>;

TI的EDMA Engine会根据上面这行内容为你配置好crossbar,几乎不需要在你自己的驱动里做任何工作。
4. linux下的DMA驱动程序框架

linux DMA驱动程序框架文档位于linux内核目录树下Documentation/dmaengine,主要看client.txt就可以了。在这篇文档里说明了该如何使用DMA Engine的API。原则上来说,只要根据这篇文档所述内容编程,就可以搞定了。另外我还参考了drivers/crypto/omap-aes.c,这个驱动也使用了DMA。不过针对具体的TI DMA控制器,这里还是有一些补充说明:

  • addr_width:这个根据你外设情况设置。我的是16位ADC,所以我设置为DMA_SLAVE_BUSWIDTH_2_BYTES。
  • maxburst:这个可设置为当你提交DMA请求时的可用数据量。我的FPGA里放了一个1k的FIFO,在累积到512数据点时提交DMA请求,所以将maxburst设置为512。maxburst的单位依据addr_width设定。比如addr_width是2bytes,那么一个burst就是512个数据点,或1024字节。
  • 不同的DMA控制器需要厂家实现自己的dmaengine底层,TI的底层实现在drivers/dma/edma.c。
  • 如果你将maxburst设置为1,TI的驱动将使用A Sync方式驱动EDMA;若maxburst大于1,就使用AB Sync方式。不管是哪种方式,acnt都等于addr_width所设定的数据量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值