SEP6200平台上Linux内核的USB OTG驱动设计

2013-09-21 10:44杨廉萍缪卫
单片机与嵌入式系统应用 2013年4期
关键词:驱动程序内核总线

杨廉萍,缪卫

(东南大学 电子科学与工程学院,南京 210018)

引 言

传统的USB协议(USB 2.0)规定了两个设备之间进行数据通信时,必须有一个Host设备作为固定的主机,通过这个主机来控制设备间的数据传输。在日常应用中,基本都是将USB设备连接到PC,并在PC的控制下进行数据交换。这种交换方式,一旦离开了PC,各设备间就无法利用USB口进行直接操作。随着嵌入式设备的快速发展,两个USB设备之间直接进行数据交换的需求变得越来越迫切。USB On-The-Go(USB OTG)技术便应运而生。OTG技术实现了在没有Host的情况下,设备之间点对点的数据控制与传输。本文通过研究USB 2.0协议和USB OTG补充规范,结合具体应用需求,建立了基于国产SoC的嵌入式USB OTG模块硬件平台,并在Linux操作系统平台上设计并实现了基于国产内核主控芯片SEP6200的USB OTG设备驱动。

1 USB OTG协议与实现方式概述[1]

USB OTG标准在完全兼容USB2.0标准的基础上,增添了电源管理(节省功耗)功能,并可提供一定的主机检测能力,支持对话请求协议(SRP)和主机交换协议(HNP)。在OTG中,初始主机设备称为A-device,外设称为B-device。

对话请求协议(Session Request Protocol,SRP):为了节省功耗,A-device在总线不被使用时允许VBUS总线关断,此时B设备就会检测到该状态并进入功低耗模式。当外部B-device需要向A-device发起对话时,它会通过SRP向A-device发出申请,请求A-device向VBUS供电并启动一次对话。对话将随VBUS的开启而开始,随VBUS的关闭而结束。

主机交换协议(Host Negotiation Protocol,HNP):该协议允许两个直接相连的OTG设备进行主机Host功能的切换,它能够根据电缆的连接方式来决定初始化角色,从而允许设备在通信时能够改变控制信号。当用户模式或应用程序下B-device有输入时,HNP将作初始响应。

OTG两用设备使用新型mini-AB插座,从而使mini-A插头、mini-B插头和mini-AB插座增添了第5个引脚(ID),以用于识别不同的电缆端点。mini-A插头中的ID引脚接地,mini-B插头中的ID引脚浮空。当OTG设备检测到接地的ID引脚时,表示默认的是A-device(主机);而检测到ID引脚浮着的设备,则认为是B-device(外设)。系统一旦连接后,OTG的角色还可以更换。A-Device作为默认主机并提供VBUS电源,并在检测到有设备连接时复位总线、枚举并配置B-device。

2 USB OTG模块硬件方案

为了后期USB OTG驱动设计需要,首先对OTG硬件模块作一些简单的介绍。本文设计的USB OTG模块在硬件上由主控芯片SEP6200以及USB控制芯片USB3343构成。SEP6200是东南大学国家ASIC工程中心自主研发的一款定位于手持视频播放设备、卫星导航产品的高性能应用处理器,它内部集成了ULPI总线接口,支持SRP和HNP协议,拥有USB2.0OTG功能[2]。USB控制芯片USB3343是SMSC公司生产的一款高速USB收发器,支持主机、设备和OTG三种功能,非常适合用于要求低功耗工作和待机工作的便携式设备[3]。SEP6200内部的OTG Controller和USB3343之间通过otg_transceiver接口来完成交互。

在本模块中,SEP6200处理器通过自带的ULPI接口与USB3343进行连接和通信,而USB3343收发控制器则是通过外接USB MiniAB插座与外部USB设备进行连接。其硬件连接结构图如图1所示。

图1 USB OTG硬件连接结构图

此硬件平台以SEP6200处理器为核心,处理器除了ULPI接口的12根总线与USB3343相连接外,另外分别通过两根GPIO接口线来控制实现OTG的低功耗功能。其中一根(GPIO_RESETB)用来对USB3343进行软件复位,另一根(GPIO_EN)用来控制对VBUS总线供电。当核心板作为device与PC进行连接时,软件检测到ID信号状态为浮空后将GPIO_EN引脚置0,切断电源模块,使5V供电电压与VBUS总线隔绝。相反,当核心板作为Host与U盘等外设进行通信时,软件检测到ID信号状态为接地,然后将GPIO_EN引脚置位,通过电源使能模块将5V电压加载到VBUS总线上,实现核心板作为主机对外设进行供电,从而实现对外部设备的检测和枚举等后续操作。

3 USB OTG驱动架构的设计与实现

3.1 OTG设备驱动程序架构

本设计的软件驱动开发基于Linux操作系统平台。作为开源操作系统,Linux有良好的兼容性和强大的USB技术支持。OTG设备驱动程序主要由USB目标设备软件包和USB主设备软件包构成。OTG驱动通过连接器中“ID”信号的不同连接,根据SRP和HNP协议的内部机制,确定使用USB主设备软件包还是USB目标设备软件包。图2是OTG设备驱动程序架构框图。

图2 OTG设备驱动程序架构框图

当OTG设备以从机方式工作时,USB目标设备功能模块工作。目标设备控制驱动完成USB目标设备软件包与OTG硬件间的数据交换。USB协议层完成USB协议规范,USB目标设备类驱动的功能取决于OTG设备的功能。

当OTG设备以主机方式工作时,USB主设备功能模块工作。主控制驱动完成USB主设备软件包与OTG硬件间的数据交换,USB总线驱动保存设备的信息。OTG提供通用的主设备类驱动程序,驱动支持的这些目标主设备包含在目标设备的列表里[4]。

基于以上分析,驱动软件设计的总体任务主要分为:USB从机设备驱动设计、USB主机控制器驱动设计以及USB OTG驱动设计。其中从机设备驱动模块和主机控制器驱动模块互相独立,OTG驱动依赖于从机设备驱动和主机控制器驱动。

3.2 USB从机设备驱动设计

基于SEP6200的核心板系统在作为USB从机设备时,要应答PC主机的标准请求,处理USB总线事务和用户功能。因此从机驱动包括3层:UDC驱动程序、Gadget驱动程序和Gadget API。UDC驱动程序负责直接访问硬件,控制USB设备与主机间的底层通信,向上层提供与硬件相关操作的回调函数。Gadget驱动程序具体控制USB设备功能的实现。Gadget API则是提供给UDC驱动程序回调函数的简单封装[5]。

Linux内核首先通过 musb_init_controller()函数初始化USB设备控制器,OTG驱动提供的状态机根据硬件信息将USB OTG工作模式配置成从机模式。接着内核会初始化Gadget驱动,完成Gadget驱动和UDC驱动的绑定,并配置控制器使其开始工作。然后调用底层Gadget API函数来激活端点进行数据传输。USB OTG定义了三个端点:程序中定义端点0在控制传输中应答设备枚举,端点1的功能为向PC机发送数据,端点2的功能为接收PC机发送的数据。最后,通过中断响应和中断处理函数来完成核心板作为设备与PC机的通信操作。内核使用struct musb结构体描述UCD驱动实例的各种信息。

3.3 USB主机控制器驱动设计[4,6]

核心板系统的主机驱动分为几个部分:Host controller drive、USB core和Class driver。在本设计中,Host controller drive与所应用的USB主控芯片USB3343相关,而USB Core和Class driver在Linux内核中提供了相应的支持。

Linux内核使用usb_hcd结构描述USB主机控制器驱动Host controller drive。usb_hcd结构描述了USB主机控制器的硬件信息、状态和操作函数,其定义如下:

软件根据HNP协议执行完所有的HNP状态后,OTG驱动进入USB Host模式。在对底层硬件初始化后,注册Hub和USB存储类设备,随后加载hub_probe对根Hub进行初始化和枚举。当外部USB设备插入后,系统将对USB类设备进行枚举,查找对应的USB存储类设备驱动,并加载storage_probe,然后读取插入的USB存储类设备的文件系统结构,将该存储设备注册为一个scsi disk。使用mount命令将该设备挂载到相应目录后,即可完成对USB存储设备的读写操作。

3.4 USB OTG驱动设计

OTG驱动维护着一个OTG状态机,从而支持HNP和SRP协议,转换主机端和设备端功能,上文中硬件状态的检测和驱动模式转化即由此实现。在模块初始化的时候,首先对OTG驱动进行注册,OTG驱动将自身注册为一个char设备。当找到设备时,在注册函数中执行设备控制器驱动对应的probe函数,初始化OTG模块,随后调用中断申请函数申请中断,并设置相应的中断处理函数。在本设计中,当有OTG中断产生时,首先执行硬件访问层的中断处理函数phy3343_hal_isr(),在这个函数中读取中断来源,若判断是OTG中断,则调用OTG驱动的中断处理例程usb_otg_isr(),启动 OTG状态机。

OTG驱动还需要向文件系统提供相应的file operations接口,供上层的application调用,这些接口函数包括:usb_otgdev_open、usb_otgdev_close、usb_otgdev_ioctl、usb_otgdev_fasync等。usb_otgdev_open函数负责 OTG application在打开OTG设备文件时,通过Linux文件系统接口调用该函数,进行OTG驱动自身参数的初始化;usb_otgdev_close函数负责OTG application在关闭OTG设备文件时,通过Linux文件系统接口调用该函数,进行OTG驱动自身参数重启;usb_otgdev_ioctl函数是在OTG application调用OTG设备文件的ioctl函数时,Linux文件系统接口调用该函数;usb_otgdev_fasync函数则是当OTG的application设置或者重设异步通知时,对该函数进行调用,当异步通知模式设置成功返回值为0,失败时返回负值[4]。

Linux内核中通过定义struct otg_transceiver结构体,提供给开发者一个与USB硬件进行直接交互的接口。在本设计中,即通过该结构体实现了软件与USB主控芯片USB3343的交互通信功能。

结 语

USB OTG技术满足了两个设备之间直接进行数据通信的要求。在对现有的OTG协议和相关应用进行深入研究的基础上,本文在国产SoC芯片SEP6200平台上设计并实现了基于Linux内核的USB OTG模块驱动。整个SEP6200核心板系统能够支持USB主机模式、USB设备模式,并且能够实现两个模式间的切换。

[1] Hewlett-Packard Company.On-The-Go and Embedded Host Supplement to the USB Revision 2.0Specification,2012.

[2] 东南大学ASIC中心.SEP6200设计文档,2010.

[3] SMSC.USB334xDatasheet.Revision 1.1,2011.

[4] 王栋柯.基于嵌入式Linux平台的USB OTG功能的研究和实现[D].南京:东南大学,2007.

[5] 陈效友.基于Linux的USB OTG IP核设备驱动开发技术[D].成都:电子科技大学,2010.

[6] 弓雷.ARM嵌入式Linux系统开发详解[M].北京:清华大学出版,2010.

猜你喜欢
驱动程序内核总线
多内核操作系统综述①
强化『高新』内核 打造农业『硅谷』
基于嵌入式Linux内核的自恢复设计
Linux内核mmap保护机制研究
基于PCI Express总线的xHC与FPGA的直接通信
机载飞控1553B总线转以太网总线设计
计算机硬件设备驱动程序分析
一种基于CAN总线的误码测试方法
CAN总线并发通信时下位机应用软件设计
妙用鼠标驱动