admin管理员组

文章数量:1532175

2024年1月12日发(作者:)

DOI:10.3969/j.issn.1001-3824.201 1.02.O14 嵌入式Linux下USB设备的大容量数据 传输驱动开发与实现 范耀武,何 维,田增山 (重庆邮电大学无线定位与空间测量研究所,重庆400065) 摘要:针对手持终端探测过程中大容量数据传输驱动开发存在的难点,利用嵌入式Linux平台及USB驱动架构, 分析了EZ—USB驱动读取数据的流程,提出了大缓存USB驱动的设计方案,通过原型设备测试验证了该设计方案 的有效性,解决了EZ—USB FX2芯片高速传输中出现的数据丢失现象。 关键词:嵌入式Linux;高速传输;USB设备驱动;内存页申请 O 引 言 USB以其低成本、速度高、通用性强、支持即插 即用等优点使得越来越多的设备采用USB接口。 随着Linux系统的逐步完善,功能逐渐强大,在嵌入 式Linux平台下的USB设备驱动开发成为了该领域 工程实现的热点和难点。 高达60 Mbit/s,同时在Linux下也有USB的相关源 码,仔细分析Linux内核及USB源码,从USB读取数 据流程中提出USB驱动改进的方案,经原型设备测 试其有效性后,基于EZ.USB FX2设备的4 Mbit/s大 缓存的USB驱动最终被项目采用。 1硬件系统介绍 本次项目开发采用的嵌入式开发板是Dev, Kit8000,具有ARM+DSP双内核的OMAP3530处理 本项目研发的手持终端主要应用于定位和跟 踪手机目标,在刑警抓获匪徒、解救人质,以及在地 震等灾难后定位和搜寻人员都有着重大的意义。 但是手持终端在定位和跟踪目标时需要采集大量 器,可兼顾设备的数据处理强度大、调度和控制功 能要求高的需要。DSP内核对数据的压缩处理能力 的数据来解算,如果是4倍采样的话,则速率高达‘ 非常强,而ARM内核可以完成系统的整体控制功 20.48 Mbit/s,实时高速的传输是整个项目的一个研 能和对DSP运算结果的访问。 发难点。 USB芯片采用的是EZ—USB FX2,EZ.USB FX2 基于Linux嵌入式平台,我们开始设计了3种方 案,分别采用GPIO,GPMC,USB来传输。GPIO(gen— eral—purpose I/O)由于收发之间没有时钟约定以及I// 拥有1个独特的结构,其串行接口引擎SIE负责完 成独立串行数据的编解码、差错控制、位填充等与 USB协议有关的功能,FX2还包含一个通用可编程 O本身数据传输能力有限导致数据丢失的问题无法 解决。GPMC(general—purpose memory controller)专门 接口(GPIF),它支持所有通用的总线标准,如ATA PI(PIO和UDMA),IEEE1284(EPP并行口),UTOP— LA等,并可与外部ASIC,DSP等直接连接。 用于高速存储之间的访问,一般用于SRAM等设备, 在Hnux内核源码中仅仅有nandflash访问的源码,开 发用于FPGA高速传输的驱动难度较高。由于上述 原因我们采用较为成熟的USB2.0芯片,其理论速度 收稿日期:2010—12—28 为了验证数据传输的正确性还加了EP3C5E144 型号的FPGA,根据项目需要,FPGA的工作频率是 10.24 MHz,让其产生16位的循环码,通过USB传送 给DevKitS000,并计算其丢包率和误码率。 一53— 

硬件系统结构如图1所示。 AI TEl{A FP( FZ~ljSB FX2 i)evKit8(x)0 I 1.1 控制器 <————_c) S1 AVE1 USB q——— USB j测试 F1FO 日——— FIF()【20 目———口 驱动l程序 图1硬件系统结构图 1.1嵌入式Linux系统 1.1.】嵌入式Linux系统 嵌入式Linux系统主要分为4个部分,分别为 MLO,Uboot,ulmage和rootfs。Linux启动过程也是 按照这个顺序,先加载MLO即x.1oader,为第一阶段 引导装载器,主要实现的功能是初始化最基本的硬 件,然后根据启动方式从nand flash或mme/sd拷贝 u—boot代码到内存,把系统引导到能够装载第二阶 段引导装载器的状态。第二阶段引导装载器是u— hoot,但是大多数发行版在u.hoot.bin文件中提供 自己的U—boot版本。U.boot对大部分的硬件进行 初始化,然后引导Linux内核,完成系统的启动。 1.1.2系统移植步骤 MLO与uboot的编译非常相似,都是在其对应 源码中修改makefile“CROSS—COMPILE”为自己的 交叉编译器,然后执行“make distclean”和“make omap3530stalker config&&make”,MLO还要多1个 签名步骤./signGP x.1oad.bin,然后执行“mv x—load. bin.ift MLO”将x load.bin改名为MLO。 内核的编译可以通过命令“make menuconfig” 来自己配置需要的选项,生成自己定制的内核,也 可以在内核源码目录/arch/arm/configs中将对应的 配置文件拷贝出来,执行“make omap3一devkit8000~ defconfig”和“make ulmage”生成DevKit8000系统默 认配置的内核文件。 1.1.3根文件系统rootfs 如果是将rootfs烧录到nandflash启动的话,可 以使用后缀为.img的镜像文件如ubi.img。如果是 在SD卡启动,可以采用ramdisk的压缩包格式,它 是在内核加载完成后将rooffs解压缩到内存中让用 户自行操作内核;还有另外一种较为常用的方法是 使用双分区技术将SD格式化为2个分区,一个是 FAT32格式,另一个是EXT3,FAT32格式的分区可 以在windows下识别,用以存放MLO,uboot和uIm— age,而Linux分区即EXT3则存放rootfs,这样做的 ——54——DIGITAL COMMUNICATION/201 1.2 好处是系统启动后不需要将文件系统解压到内存 中,可以节约一部分内存。在嵌入式平台资源本来 就紧张的环境下,这不失为一种较好的方法。 1.2 USB驱动结构 USB驱动采用树形拓扑结构,在USB接口协议 中,USB被划分为USB主机和USB设备2个部 分¨J。每条总线上只有1个主机控制器HC(host controller),负责协议主机与设备之间的通信。而 USB设备则可以对应很多个,主机是USB的核心, 管理着每个USB设备,每一次USB数据通信都必须 由USB设备来发起。USB主机系统由多层构成,总 体结构如图2所示。 USB设备驱动 Mass smrage/CDC/H[D : USB核心 : USB主机控制器驱动 (1HC1/EHCI/[HCI : USB E机控制器 OItCI/EHCI/UH(:l : 根集线器 图2 USB驱动架构 在Linux主机驱动中,硬件部分包括根集线器 和USB主机控制器,提供USB的物理层功能。在其 之上运行的是USB主机控制器驱动HCD(host cont— oiler driver)。HCD作为底层硬件的驱动程序,一方 面控制和管理底层硬件,负责将USB事务发送给 USB主机控制器芯片;另一方面为上层的USB系统 软件提供了统一的接口HCI(host controller inter— face),方便将各种不同的HC映射到USB系统。目 前HCI主要有3种不同的标准:UHCI,OHCI和EH— cI,其中EHCI标准为增强型,HC1支持USB2.0高 速模式(60 Mbit/s)。主机控制器驱动之上为USB 驱动(USBD)层,再上层为USB设备驱动层。因此, 在驱动的总体结构中,要实现的USB驱动包括2 类:USB主机控制器驱动和USB设备驱动,前者控 制插入其中的USB设备,后者控制USB设备如何与 主机通信。 

Linux内核USB核心(USBD)负责USB驱动管 理和协议处理的主要工作,它通过定义一系列的数 据结构、函数和宏定义来抽象设备的硬件细节,向 上为设备驱动提供编程接口,向下为主机控制器驱 buffer,size_t count,loff t ppos)其中第1个参数为 该驱动的文件描述字,第2个参数为存放数据的首地 址,第3个参数为读取数据的大小。该函数最关键的 是调用USB驱动核心部分的bulk传输函数。 usbbulk动提供编程接口。其具体功能包括:提供与设备驱 动程序的接口API、读取USB设备描述符、配置描述 msg(dev一>udev. usbrevbulkpipe(dev一>udev,dev一>bulk—in—end— 符,为USB设备分配唯一的地址端点,支持基本的 USB命令请求、配置设备、连接设备与相应的驱动 程序、转发设备驱动程序的数据包。在Linux编写 USB设备的驱动程序,从严格意义上来讲,就是使 用USB内核定义的这些数据结构、函数来编写数据 的处理功能。 1.3 EZ-USB FX2驱动开发与实现 1.3.1 EZ—USB FX2驱动 USB驱动文件是在\Linux一2.6.29\drivers\usb 目录下,通过“make menuconfig”命令将USB驱动下 “EHCI HCD(USB 2.0)suppo ̄”和“Select PHY/ TLL mode for USB p0rts on OMAP34xx/OMAP35 xx” 配置选项选择为“ ”编译进内核,然后再编译对 应的USB设备驱动 。 EZ—USB FX2芯片驱动可使用\Linux一2.6.29\ drivers\usb目录下的示例usb—skeleton.e文件,将该 文件的第27行和第28行即匹配具体设备的VID和 PID,将其改为EZ—USB FX2芯片的VID和PID号, 具体修改如下:#define USB—SKEL—VENDOR—ID# 0x0547和#define USB—SKEL—PRODUCT—ID# 0x1002,然后将该文件与编译驱动的Makefile放在 一个目录下,在终端直接输入“Make”命令便可得到 想要的驱动文件,输入“insmod skeleton.ko”后系统 识别该文件下的module—init(usb—skel—init)继而调 用skel—probe()函数实现USB驱动的加载,若要卸 载该驱动则输入“nnmod skeleton.ko”系统会识别 该驱动文件的module—exit(usb—skel—exit)实现卸载 该驱动 。 1.3.2数据读取流程 上述编译的驱动虽然可加载成功,也可以读到 从FPGA产生并传给EZ—USB的循环码数据,但是 速率只有15 Mbit/s左右,同时伴随着丢失数据的不 连续。分析整个数据读取的过程,该驱动的skel— read()读数据函数,其函数原型为: static ssize t skel read(street file ifle.char:l: pointAddr), dev一>bulkinbuffer, arin(dev一>bulk—in—size,count), &bytes—read,10000); 从中可以看到该USB驱动使用了bulk传输。 第1个参数指定了该驱动对应的USB设备,第2个 参数定义了bulk传输过程的输入端点,第3个参数 为驱动存放数据的首地址,第4个参数表示最大可 读取的字节数,第5个参数表示实际读取数据的大 小,因为该函数采用同步等待,所以有最大等待时 间为10 000 ms。该函数会调用USB核心函数通过 USB主机控制器驱动将USB设备硬件端点的数据 传输至0 dev一>bulk—in—buffer。 当数据已经读到dev一>bulk—in—buffer中,skel read函数又调用copy—to—user()函数将USB数据 传送到应用层空问。 1.3.3 EZ—USB FX2驱动设计方案 整个数据读取流程只有dev一>bulk—in—buffer 可以修改,该buffer大小的申请在usb.skeleton.C文 件的第382行:dev一>bulk—in—buffer=kmalloc (buffer—size,GFP—KERNEL),其中buffer—size= le16to一—cpu(endpoint一>wMaxPacketSize),初始大 小为5 12 bit,也就是每调用一次skel—read()只能读 取512 bit,如果应用层一次需要读取几M大小的字 节则会频繁调用该函数,这样会导致在连续调用该 函数的间隙中丢失一部分数据,将该dev一>bulk— inbuffer=kmalloc(buffer—size 128,GFP—KER— NEL)即该buffer增大flJ64 kB时测试接收到的速率 有所提升,数据的丢失率也减少了,但是数据仍然 存在着丢失。因为利用kmalloc()函数申请buffer 的大小最大只能是128 kB,如果还想扩大buffer,只 能采用内存页的申请方式,同时由于底层传输采用 的是DMA方式,这就要求该buffer的物理地址必须 是连续的,所以最后决定使用…get flee—pages()内 存页申请函数,该函数定义在mm/page—alloc.C文 件的line 2172处,其原型为: 一55— 

unsigned long…get free—pages()(gfp—t gfp— 和数据的丢失多少有着根本的影响,从表1中可以 看出驱动申请的buffer越大则数据丢失率越小。在 mask,unsigned int order) 第1个参数gfp—mask为标识符也称之为分配 buffer为1 MB的时候速度已经接近理想速度,提高 为4 MB时发现测试速度为20.48 MB与理论速度 优先级,第2个参数order是指分配的大小,其最大 值由include/Linux/Mmzone.h文件中的MAX—OR— DER宏决定,在默认的2.6.29内核版本中,该宏定 义为1O。该函数申请内容空间大小的计算公式为: s/ze=(】<<order)×4 kB,最大可以申请4 Mbit大 相同,并用测试程序测试收到的数据也完全是FP— GA产生的循环码序列,从而验证了4 MB大缓存的 USB驱动的有效性。 小的连续内存空间即order:10。这里我们需要修 改为dev一>bulk—in—buffer=…get free—pages(一一 GFP—DMA,10),然后在对应kmalloc()函数释放内 存空间的地方我们也修改为对应的内存释放函数, 将75 line处的kfree(dev一>bulk—in—buffer);修改 为free—page(dev一>bulk—in—buffer);保存后输人命 令“make”后生成新的usb—skeleton.ko驱动,加载后 运行应用程序发现数据传输速率为理想的 20.48 Mbit/s,用程序验证接收到的数据也没有发 现有数据丢失的现象。至此,4 Mbit/s大缓存的 USB驱动开发完成 。 2测试及结果 在DevKit8000和EZ—USB FX2平台上,将USB 驱动中dev一>bulk—in—buffer修改为不同大小的数 值,分别为5】2 bit、64 kB、1 MB、4 M,1 M缓存是将 order赋值为8,4 M缓存对应的order为10。不同的 buffer大小都测试100次以上,取其平均值得到以下 的测试结果如表l所示。 表1不同buffer对应的测试结果 经测试发现buffer值的大小对数据的传输速率 一56一DIGITAL COMMUNICATION/201 1.2 3 结束语 本文为DevKit8000平台下的EZ—USB FX2设计 了基于嵌人式Linux的大容量数据传输驱动,成功 解决了数据丢失与速率不够的问题,目前已用于项 目开发平台。由于Linux内核源码的开放性与USB 设备的大量涌现 j,在解决高速传输数据的问题上 可以为同类Linux下的USB设备驱动开发所借鉴。 参考文献: [1] 毛德操,胡希明.Linux内核源代码情景分析[M].浙 江:浙江大学出版社,2001:415653. [2]JONATHAN C,ALESSANDRO R,GREG K H.LINUX 设备驱动程序[M].魏永明,译.北京:中国电力出版 社.2006:46-70,324—356. [3] 宋宝华.Linux设备驱动开发详解[M].北京:人民邮 电出版社,2008:24—134. [4] 曾水平,徐峰.Linux系统下USB设备驱动的实现[J], 国外电子测量技术,2006,25(10):3O一32. [5j 梁正平,毋国庆,肖敬.Linux中USB设备驱动程序研 究[j].计算机应用研究,2004,21(6):70—72. [6] 陈友贵,陶铮.基于Linux的蓝牙无线模块VSB驱动程 序的开发[J].重庆工学院学报:自然科学版,2008,22 (1):143—149 172. 作者简介: 范耀武(1985一),男,山西忻州人,硕士研究生,主要研究 方向为通信与信息系统,Email:395496026@qq.COI1];何 维 (1980一),重庆人,讲师,主要研究方向为移动通信技术;田增 山(1968一),男,河南信阳人,博士,主要研究方向为个人通 信、卫星导航、无线定位、信号检测与处理和语音视频处理。 

本文标签: 驱动设备数据函数内核