基于AM335X的EDMA 驱动程序开发

0 简介

       EDMA即TI自定义的加强版DMA数据传输模式,经过简单的了解,本质上它设计一种非常高效的可以合并多次DMA传输的模式。

1 协议简介

       协议的简单介绍可以参考http://blog.chinaunix.net/uid-28818752-id-3749701.html和http://blog.chinaunix.net/uid-24567872-id-3161827.html。

       基于linux内核提供的API可以参考http://blog.chinaunix.net/uid-28818752-id-3750016.html。

       简单的将EDMA用作DMA的驱动工程,可以参考http://www.cnblogs.com/imapla/p/4122609.html。

       希望完整的使用EDMA驱动,还需要一些准备工作,如内核提供哪些编译选项等,关于这部分可以参考http://processors.wiki.ti.com/index.php/AM335x_EDMA_Driver's_Guide。根据这个链接,可以发现官方推荐的参考代码是AM335x PSP Package Contents中的edma-test.c,但很可惜暂时没有找到。

2 工程开发过程记录

2.1 环境介绍

       硬件是基于am335x芯片的beaglebone-black平台,软件是linux-3.8.13内核。

2.2 记录

2.2.1 驱动程序说明:

       AM335X使用的是EDMA控制器,而不是DMA,基本原理与DMA一致掌握源、目的、长度即可,只不过传输的模式多样化了,而且理论上会是更高效的。

       使用默认的配置文件应该是配置了CONFIG_EDMA,如下图所示。

基于AM335X的EDMA 驱动程序开发_第1张图片

       主要参考的驱动文件说明

arch/arm/common/edma.cEDMA Controller提供的主要接口实现文件;

driver/dma/edma.c   一个使用edma api 的参考驱动daemon;

driver/dma/virt-dma.c 

       三者的联结思想有点类似于dev-platform-bus 总线的关系;

注意,实际上edma.c与virt-dma.c暂时并没有发现有什么用,但是当我试图从编译选项中去除时,整个系统无法启动,猜测“TI EDMA Support”不仅使能了编译virt-dma.c和edma.c文件,应该还牵涉很多其它的内容。另外,系统启动后,发现默认加载了driver/dma/edma.c的驱动,一直有其打印信息(通过选上“DMA Engine verbose debugging”还有降低打印阈值可以观察到)。

程序框架

       首先,驱动加载成功后会立即申请一个4MB的连续的物理地址的地址空间,申请的原因是,每次DMA传输使用的地址是物理地址,一般而言的应用描述场景可能是“应用程序需要使用DMAxxxx地址的大小xxxx字节的内容拷贝到我的缓冲区中”,如此xxx地址是物理地址,但缓冲区是应用程序空间使用的虚拟地址,由于申请大多数可能是malloc所以物理空间上是不连续的(所以即使使用API将虚拟地址转成物理地址也是没有意义的,非连续)。所以驱动程序使用一个4MB的大小缓冲区作为中转空间(之所以基于驱动程序完成该功能是因为应用程序是没有办法得到4MB连续的物理地址空间的),先使用DMA传输至该缓冲区,然后传输完毕后,用户程序读操作函数中将其拷贝至应用层指定的非连续的虚拟地址空间。这个拷贝操作相对较快(已经验证),猜测只是修改了虚拟地址到物理地址的映射关系,并不是真正意义的拷贝。另外,由于在不改变内核的基础上,只能申请到最大空间为4MB,所以限定了一次DMA传输的数据量需要小于4MB,如果需求大于4MB则需要在驱动程序中建立策略完成。

       其次,提供给用户使用的接口包括,通过ioctl设置源物理地址,长度,启动DMA传输,关闭DMA传输(释放资源),读操作(将数据拷贝至应用程序空间)。另外ioctl使用的命令字并不规范,之前测试0x0000002就一直报BAD ADDREESS的错误,测试是该数字不能使用ioctlcmd

       最后,应用层程序通过调用ioctl设置参数启动传输,再调用read将数据拷贝出来。同时通过mmap对DMA传输数据的正确性验证。需要注意的是,根据数据手册可以知道am335x的地址映射是将0x8000_0000~0xBfff_ffff映射,同时beaglebone-black的设备树文件中对memory节点的控制是8000_0000~9000_0000,所以搬运的物理地址如果使用的是SDRAM那么范围就应该是8000_0000~9000_0000。

你可能感兴趣的:(AM335X,Linux驱动)