7. 重点讲解
7.1 如何理解CYPRESS 68013A程序框架
CYPRESS提供了非常好的程序框架,免去了用户自己编写一些通用性比较强、模式化的程序(如果不提供,很少有人能写出如此高效,结构紧凑的程序,实际上此框架和68013A内部结构关系密切,一般人也没有足够的内部资料也不可能写出来)。在框架的基础上,用户只需在相应的地方写相应的代码即可完成USB工作。
一般来说框架可以分成3个部分。
1) 描述符文件。例如dscr.a51文件,里面定义了枚举设备的时候要用的各种描述符信息,这部分用户需要根据实际的情况自己编写。我写的时候发现一个最大的问题就是各种书籍协议版本不同,翻译质量不同,同一字段的意义表述不同,容易让人产生困惑。例如USB 1.1/2.0/2.13对设备类型的子类定义都不完全相同,所以写的时候最好几种文档对比起来写。由于USB官方网站的文档中字段解释过于专业化,所以对USB不是很熟悉的人比较难以理解其真正含义。所以要多参考不同的书籍,某种程度上降低了开发速度,但对第一次做USB开发的人来说,这也是值得的。
2) 固件文件,例如FW.C文件,这是硬件程序的函数入口。主要有以下这些方法:
void SetupCommand(void); //握手命令处理
void TD_Init(void); //初始化,完成配置,启动时调用一次
void TD_Poll(void); //用户处理程序,循环调用
void IO_Init(void); //8051 IO初始化
void REG_Init(void); //8051寄存器初始化
BOOL TD_Suspend(void); //挂起处理
BOOL TD_Resume(void); //唤醒处理
//以下为各种描述符的获取和设置函数,重枚举时自动调用
BOOL DR_GetDescriptor(void);
BOOL DR_SetConfiguration(void);
BOOL DR_GetConfiguration(void);
BOOL DR_SetInterface(void);
BOOL DR_GetInterface(void);
BOOL DR_GetStatus(void);
BOOL DR_ClearFeature(void);
BOOL DR_SetFeature(void);
BOOL DR_VendorCmnd(void);
3) 功能文件,处理各种中断。例如PERIPH.C文件。8051一般默认只有四个中断,这显然不够USB使用,所以CYPRESS引入了自动向量的概念,相当于软中断,大大扩展了现有的中断数量。主要的中断有:
void ISR_Sudav(void) interrupt 0 //收到setup包
void ISR_Sutok(void) interrupt 0 //收到SETUP令牌
void ISR_Sof(void) interrupt 0 //收到起始帧
void ISR_Ures(void) interrupt 0 //收到RESET
void ISR_Susp(void) interrupt 0 //收到挂起信息
void ISR_Highspeed(void) interrupt 0 //高速模式
void ISR_Ep0ack(void) interrupt 0 //正常响应ACK
void ISR_Stub(void) interrupt 0
void ISR_Ep0in(void) interrupt 0
void ISR_Ep0out(void) interrupt 0
void ISR_Ep1in(void) interrupt 0
void ISR_Ep1out(void) interrupt 0 //EP1输入中断
void ISR_Ep2inout(void) interrupt 0 //EP2中断
void ISR_Ep4inout(void) interrupt 0
void ISR_Ep6inout(void) interrupt 0
void ISR_Ep8inout(void) interrupt 0
void ISR_Ibn(void) interrupt 0
void ISR_Ep0pingnak(void) interrupt 0
void ISR_Ep1pingnak(void) interrupt 0
void ISR_Ep2pingnak(void) interrupt 0
void ISR_Ep4pingnak(void) interrupt 0
void ISR_Ep6pingnak(void) interrupt 0
void ISR_Ep8pingnak(void) interrupt 0
void ISR_Errorlimit(void) interrupt 0
void ISR_Ep2piderror(void) interrupt 0
void ISR_Ep4piderror(void) interrupt 0
void ISR_Ep6piderror(void) interrupt 0
void ISR_Ep8piderror(void) interrupt 0
void ISR_Ep2pflag(void) interrupt 0
void ISR_Ep4pflag(void) interrupt 0
void ISR_Ep6pflag(void) interrupt 0
void ISR_Ep8pflag(void) interrupt 0
void ISR_Ep2eflag(void) interrupt 0
void ISR_Ep4eflag(void) interrupt 0
void ISR_Ep6eflag(void) interrupt 0
void ISR_Ep8eflag(void) interrupt 0
void ISR_Ep2fflag(void) interrupt 0
void ISR_Ep4fflag(void) interrupt 0
void ISR_Ep6fflag(void) interrupt 0
void ISR_Ep8fflag(void) interrupt 0
void ISR_GpifComplete(void) interrupt 0
void ISR_GpifWaveform(void) interrupt 0
特别是对于接受数据,一般都在中断中完成相应处理,“中断中适合进行少量简短的操作,不适合进行复杂操作”,这句话在此依然有效。如果要进行复杂的操作可以在TD_POLL()中进行(多数操作都是在这个函数中完成的)。
另外非常重要的一点是,中断程序的结尾应该让中断复位,允许下一次中断,有些端点的计数器也要清零并允许接受新的中断请求。例如:
EP1OUTBC = 0; //清空计数
EZUSB_IRQ_CLEAR(); //USB中断复位
EPIRQ = 0x08; //允许EP1中断请求
7.2 68013A端点寄存器介绍
68013A内部的寄存器约有300个上下,一次都记住是不可能的,而且每个寄存器都有8个位,也就是说一共有2000多个可以配置的位,一次都理解掌握这些位的含义也是不可能的,所幸地是开发中并不会用到所有的寄存器,但是依然强烈建议把FX2REGS.H和FX2.H走读一边,这就像读书一样,没有学会识字,再看都是天书。结合FX2 TechRefManual.pdf走读这些寄存器大约需要一到两天时间,这点时间投入还是值得的。
在通讯过程中,打交道最多的是各种端点寄存器,掌握好这些寄存器地使用对提升开发效率是很有帮助。值得特别关注的寄存器和配置位如下:
Rwuen、REVCTL、EP1OUTCFG、EP1INCFG、EP2CFG、EP4CFG、EP6CFG、EP8CFG、EP2FIFOCFG、EP4FIFOCFG、EP6FIFOCFG、EP8FIFOCFG、FIFORESET、EPIRQ、EPIE、EP1OUTBC、APTR1H、APTR1L、EXTAUTODAT1、AUTOPTRH2、AUTOPTRL2、EXTAUTODAT2、EP2BCH、EP2BCL
其中有些寄存器的设置需要连续设置多次,看似重复了,其实不然,这和设置的缓冲区数量有关。有些寄存器中间必须用SYNCDELAY来延时。这类寄存器FX2 TechRefManual.pdf上有说明。
对于EP0,用于系统握手,相关的寄存器操作基本上都由68013A的内核(SIE)来完成了。
对于EP1,分为OUT/IN两组配置和寄存器。
对于EP2~EP8,不分OUT/IN输入输出,主要有EP2CFG/ EP2FIFOCFG/ EP2BCH/EP2BCL寄存器。
7.3 什么是自动指针
自动指针是CYPRESS提供的一个非常有用的特性。在数据交互的过程中,很多时候都涉及到数据的搬迁,比如从EP2OUT收到的数据需要转发到EP6IN上(一些转换类设备);再比如从RAM中拷贝数据到EP4IN上,传统的做法是申明两个指针,指向源和目的地址,然后用循环一个个字节拷贝,同时还要考虑增加指针地址,对于连续的空间这到不是问题,关键是如果数据需要拷贝到多个缓冲时,指针地址是循环的。这时候如果手工完成操作很容易出错。
因此CYPRESS提供了两组自动指针,用的时候一组指向源,一组指向目的地址。然后循环拷贝数据就行了,自动指针会自动指向下一个源或目的空间,不论是否是循环地址方式。这样减少了程序出错的几率。
下面的程序将EP2OUT接受到的数据拷贝到EP6IN发送出去:
if(!(EP2468STAT & bmEP6FULL))
{ // check EP6 FULL(busy) bit in EP2468STAT (SFR), core set's this bit when FIFO is full
APTR1H = MSB( &EP2FIFOBUF );
APTR1L = LSB( &EP2FIFOBUF );
AUTOPTRH2 = MSB( &EP6FIFOBUF );
AUTOPTRL2 = LSB( &EP6FIFOBUF );
count = (EP2BCH << 8) + EP2BCL;
// loop EP2OUT buffer data to EP6IN
for( i = 0x0000; i < count; i++ )
{
// setup to transfer EP2OUT buffer to EP6IN buffer using AUTOPOINTER(s)
EXTAUTODAT2 = EXTAUTODAT1;
}
EP6BCH = EP2BCH;
SYNCDELAY;
EP6BCL = EP2BCL; // arm EP6IN
SYNCDELAY;
EP2BCL = 0x80; // re(arm) EP2OUT
}
}
APTR1H/APTR1H通过MSB和LSB获取EP2FIFOBUF的高位地址和地位地址。
EXTAUTODAT1表示APTR1H/APTR1H指向的数据。
AUTOPTRH2/AUTOPTRL2通过MSB和LSB获取EP6FIFOBUF的高位地址和地位地址。
EXTAUTODAT2表示AUTOPTRH2/AUTOPTRL2指向的数据。
7.4 CYUSB和CYAPI的关系
以前68013上位机程序的编写过程中,应用程序端通过调用DeviceIoControl() API或CREATEPIPE() API与驱动进行交互,继而读写控制硬件设备,在新的68013A的驱动中采用了两种新的调用方法:
第一种是继续使用DeviceIoControl()函数读写,不同的是,IOCTL控制字和老驱动完全不同,具体定义参考CYUSB.PDF。用户可以通过这些底层API完成操作。
第二种是使用CYPRESS提供的面对对象的类,一共有9个类,调用这些类的方法就可以和硬件打交道。这些类是对第一种方法的封装,使用起来非常简便。
用户可以根据需要选择这两种方法或混合使用,使用时需要加上头文件CyAPI.h和cyioctl.h,另外在项目中还要引用CyAPI.lib。
7.5 同步和异步读写的比较
CYAPI提供了同步和异步读写方式。同步方式的时候调用线程阻塞在哪里,直到读写到数据或超时;异步方式的时候调用线程立即返回。具体实例参考CYAPI.PDF。
7.6 如何用C++ BUILDER写上位机程序
1) 首先确定使用7.4中的第几种方法,添加相应的头文件和库文件。
2) 连接USB设备,确保驱动已经被正确加载。
3) 编写收发数据线程。通过开发板上的LED或CYPRESS CONSOLE或BUS HOUND分析收发正确与否。
7.7 U盘如何正确加载驱动
在WINDOWS 2000/XP上U盘使用的PID/VID应该直接能加载操作系统默认的海量存储器的驱动程序。为了使用正确的PID/VID,可以通过以下途径:
1) 找一个现有品牌的U盘,看看他的PID/VID是何值。
2) 在注册表中查找海量存储器信息。
1994年,Intel,Compaq等七家软硬件全球知名企业为了突破当时PC使用串口和并口传输速度的限制,成立了通用串行总线开发者论坛(USB Implementers Forum, USB IF),并在1994年11月提出了USB 0.7版,到了1998年开始出现了支持USB 1.1的设备,他的高速性(USB1.1支持1.5 Mb/s和12 Mb/s两种速度[1])和易用性迅速使之成为P C外设的宠儿.为了对抗1394速度的优势(1394可以达到400 Mb/s),1999年提出了US B 2.0规范的思想,2000年4月USB IF推出USB 2.0.USB 2.0向下兼容1.1,提供3种速度 ,最高可以达到480 Mb/s[2].
USB 1.1和2.0都是必须依赖于PC的,为了在一定程度摆脱对PC的完全依赖,有一定程度的主机功能,2001年12月推出了OTG 1.0,经过6次修改,于2003年6月推出了USB OTG 1.0 a,正式成为一个达到市场实用的规范[3].
本文中分析讨论了USB 2.0补充规范OTG的工作原理,并且针对目前数码相机伴侣存在的问题,作者提出了自己的解决方案.
1USB OTG的工作原理
OTG补充规范对USB 2.0的最重要的扩展是其更具节能性的电源管理和允许设备以主机和外设两种形式工作.OTG有两种设备类型:两用OTG设备(Dualrole device)和外设式OTG设备(Peripheralonly OTG device) .两用OTG设备完全符合USB 2.0规范,同时,他还要提供有限的主机能力和一个MiniAB插座、支持主机流通协议(Host Negotiatio n Protocol, HNP),并和外设式OTG设备一样支持事务请求协议(Session Request Protocol, SRP).当作为主机工作时,两用OTG设备可在总线上提供8 mA的电流,而以往标准主机则需要 提供100~500 mA的电流.
2个两用OTG设备连接在一起时可交替以主机和从机的方式工作,这个特点兼容了现有USB 规范主机/外设的结构模型.OTG主机负责初始化数据通信的任务,比如:总线复位、获取USB 各种描述符和配置设备.这些配置完成后,2个OTG设备便可以分别以主机和从机方式传输信息,2个设备主从角色交换的过程由主机传输协议(HNP)定义.
下面从5个方面说明OTG的工作原理.
1.1主机(Adevice)和从机(Bdevice)的初始功能
设备的初始功能是通过定义连接器来实现的.OTG定义了一个叫做MiniAB的袖珍插孔,他能直接接入MiniA或者MiniB插口,MiniAB有一个ID引脚 上拉至电源端,MiniA插头有一个与地连接好的ID(R<10 Ω),Mini B插头有一个与地连接的开路ID引脚(R>100 kΩ).当2个OTG设备连接到一起的时候,MiniA插头边的ID引脚会注入一个“0”状态,MiniB插头边的ID引脚为 “1”,ID为0的OTG设备默认为主机(Adevice),ID为1的OTG设备默认为从机(B device).图1对上述内容进行了图解[4].
1.2对话请求协议SRP(Session Request Protocol)
这个协议允许Adevice(可以是电池供电)在总线未使用时通过切断Vbus来节省电源消耗,也为Bdevice启动总线活动提供了一种方法.任何一个Adevice, 包括PC或便携式电脑,都可以响应SRP;任何一个Bdevice,包括一个标准USB外设, 都可以启动SRP;要求一个双重功能设备既能启动SRP,又能响应SRP.
1.3主机流通协议HNP(Host Negotiation Protocol)
HNP是一种用来实现Adevice和Bdevice主机/从机转换的协议(实际上是电缆的反转).主/从机功能交换的结果表现在下列过程中:
(1)利用上拉电阻来发送信号给从机.
(2)Adevice可在Bdevice上设置“HNP Enable”特性.
(3)Bdevice断开上拉.
(4)ADevice与上拉电阻相连,表明Adevice从属于从机.
(5)Adevice给Vbus供电.
(6)Bdevice检测Adevice的上拉.
(7)复位/列举/使用Adevice.
1.4驱动程序[5]
与PC主机不同,便携式设备没有便捷的方式和足够的空间装载新的驱动程序.因此,OTG 规范要求每个两用OTG设备有一个支持的外设式OTG目标设备的列表,列表中包括设备的类型和制造商等信息.
与PC机不同,OTG两用设备的驱动程序栈由USB主机栈和USB设备栈构成以满足两种工作方式的需要.OTG驱动程序通过连接器的不同或者是否有NHP交换设备的工作方式来决定使用USB主机栈还是USB设备栈.
当OTG两用设备以主机方式工作时,USB主机栈工作.其中的主机控制器驱动程序负责USB 主机栈与硬件端点的数据交换,USB驱动程序枚举并保存设备的信息,目标外设主机类驱动程序支持目标设备列表里的设备.主机类驱动程序由芯片制造商提供,同时,OTG提供通用的主机类驱动程序(可以修改以用于非通用设备).
当OTG两用设备以从机方式工作时,USB设备栈工作.其中的设备控制器驱动程序负责USB 设备栈与硬件端点的数据交换,USB协议层负责处理USB协议规范,设备类驱动程序的功能取决于该两用设备的功能(如数码照相机、存储设备、打印机等).
OTG驱动程序负责处理两用OTG设备的工作方式转换,同时,他还可以返回其结果(如设备是否支持HNP)并处理总线错误.应用层程序通过OTG驱动程序开始或者结束一个传输事务, 通过USB主机栈或设备栈与硬件层交换数据.
1.5数据流模型
OTG主机和设备被划分为功能层、USB设备层和USB接口层3个不同层次,如图2所示[5 ].
USB接口层为OTG主机和OTG设备提供物理连接,USB系统软件使用主机控制器来管理主机与 USB设备的数据传输.USB系统软件相对于主机控制器而言,处理的是以客户角度观察的数据传输及客户与设备的交互.USB设备层为USB主机系统软件提供一个可用的逻辑设备.主机通过与之功能匹配的客户软件实现其各种功能.
OTG设备与以往的USB设备一样有两种通道:数据流通道和消息通道.数据流通道没有定义好的结果,而消息通道则有固定的结构.但是,每个通道都有一定的带宽、传输类型、传输方向和缓冲区大小.自供电设备配置一个默认的控制通道,由他提供该设备的配置和状态等信息.
2目前数码相机伴侣存在的问题及其解决方案
上面对USB OTG的工作原理的主要部分进行了说明,下面将探讨USB OTG的应用.
当前随着中高档数码设备如数码相机的价格的下降,已经开始普及到千家万户,统计表明 ,2003年上半年数码相机的销量达到38.5万台,年底有望突破100万台,其进口量比去年同期增加了53倍,而现在一般使用的数码相机象素在200万~400 万,尤其以320万象素左右的为市场热点,如果要拍摄高质量的照片,每张会超过1M,即使是256M的存储空间也会很快消耗光了,而现在市场上CF卡等存储介质的价格一直高居不下,所以就应运而生了一种叫做数码相机伴侣(典型的产品如Phototainer,韩国Innoplus公司产品)的电子消费类产品. 这类产品能够提供以下功能:
(1)通过读卡机,能把各种存储介质(比如SD卡,CF卡等)上的内容拷贝到移动硬盘中去 ,为外出旅行的人们提供了极大的方便.
(2)通过USB口,可以在计算机上和数码相机伴侣之间进行数据拷贝、删除等功能.
(3)提供大容量的存储空间(从10 GB到40 GB都有),外出旅行的人再也不必为存储卡的容量操心了,大可放心的拍摄.
作者认为这类产品美中不足的是:
(1)他读取数码相机存储介质的方法是通过读卡机来实现的,也就是必须把数码相机的存储介质取下来,插到数码相机伴侣上的插口里,不但很不方便,而且注定了数码相机伴侣的尺寸重量不会很小,由于存在不同存储介质还必须有不同类型的插口(一般都是要两种插口 ).
(2)为了兼容多种存储介质,还必须要配置转接设备.
(3)耗电量也很大的,一般来说,一次充电只能用1~2 h.
(4)当前许多此类产品还采用USB 1.1接口,传输速度显然不可能达到用户的期望.
针对上面存在的问题,作者考虑把USB OTG技术应用到数码相机伴侣上来,从以下几个方面进行改进:
(1)采用PHILIPS 芯片[4]来实现USB OTG功能.优点如下:
①利用USB OTG的双重角色功能,使之可以在连接到其他便携式数码产品或者存储介质时可以作为主机,来完成数据从其他外设拷贝到移动硬盘中;当他连接到PC中时,就可以作为普通的USB设备,由PC控制,进行数据的操作.
②采用USB OTG,整体结构将发生翻天覆地的变化,将读取数据等工作将由芯片完成 ,也就省去了很多关系存储卡的工作,所以可以将尺寸和重量做的很小,而且在使用的时候也是很方便的,只要使用USB电缆连接移动硬盘和数码相机伴侣等设备就可以了.
③USB OTG的优秀电源管理能力也能使电池的使用时间更加持久.
(2)可以考虑采用大容量微硬盘,一方面满足大容量的存储需求,另一方面可以把整个数码相机伴侣体积大幅度的减小.
(3)USB 2.0在速度上的优势已经得到了市场的积极支持,所以采用的USB 2.0接口保证了数据传输的高效.
经过改进后的数码相机伴侣与目前市面上的数码相机伴侣相比,具有如下特点:
(1)PHILIPS 芯片来实现USB OTG功能,无需PC就可把图像等数据拷贝到硬盘上.
(2)内置1英寸大容量微硬盘,满足现在数据大量存储的要求.
(3)无需取下数码相机等数码设备的存储卡,使用方便.
(4)采用USB 2.0规范,最高速度可以达到480 Mb/s.
(5)可以充当便携式移动硬盘,完成数据备份等工作.
(6)简单控制,只有电源和复制按钮,即可轻松实现对存储数据的操作.
(7)采用微硬盘,典型的产品如Magicstore,体积可以更小,更时尚诱人.
(8)使用LCD显示各种状态.
(9)由于使用了OTG的特别供电模式,电源耐久性会有很好表现.
具有USB OTG功能的数码相机伴侣由于其具有海量存储、存取数据、存取速度快和出色的电源管理等特点,不仅可以充当便携式移动硬盘,更为外出旅行的人提供了极大的方便.
3结语
分析讨论了USB 2.0补充规范OTG的工作原理,作者针对目前数码相机伴侣存在的问题提出了应用USB OTG技术进行改进的方案.USB OTG已受到Cypress等芯片供应商、软件开发商和设备制造商的广泛支持,该方案从理论上和实际应用上都是实际可行的,非常具有应用价值.USB OTG规范是USB 2.0规范的补充而不是替代品.PC主机和标准外设并没有被取代,因为新的OTG仅适用于需要具有主机功能和更小体积的便携式设备.OTG在这些外设间引入了点对点的(point to point)通信方式,这使得便携式仪器的发展有了更加广阔的空间,OTG不久将会成为新一代的“移动计算”解决方案.
文章评论(0条评论)
登录后参与讨论