franksunny的个人技术空间
获得人生中的成功需要的专注与坚持不懈多过天才与机会。 ——C.W. Wendte

 

USB设备枚举全纪录

 

在编写这部分程序之前首先需要了解有关USB协议,重点是USB数据通信结构11条标准请求命令和标准USB描述符

因为嵌入式设备的软硬件是密切相关的所以还需做的准备工作是了解选用的USB芯片及主控MCU的性能

 

.硬件篇

USB芯片

作用:

1.      管理和实现USB物理层的差模信号

2.      以寄存器的形式提供各种端点(如控制端点,中断端点,大批量传输端点,同步传输端点)

3.      提供状态寄存器,配置寄存器,存储寄存器,中断寄存器,控制寄存器

4.      电源管理(提供3.3V的电源)

5.      实现某些协议层功能(CRC校验/产生,PID校验/产生,同步模式的识别,并行串行转换等)

固件就是以这些硬件资源作为基础来实现USB设备功能的,其中,端点是需要重点学习的对象,需要熟练掌握与之相关的状态寄存器,配置寄存器,存储寄存器,中断寄存器

MCU主控芯片

作用:

1.      实现USB设备的功能

2.      处理USB芯片产生的中断,解析SETUP,处理标准请求和厂商请求

 

.软件篇

USB设备端固件程序,枚举部分是全部程序的基础和重心,只有主机对设备枚举成功后,主机才能和设备进行正常的通信

USB的枚举过程分为4个状态.

       1.接入态

v主机检测到USB设备插上,击活端口,并发送复位命令(保持10ms)

       2.默认态

v主机使用默认地址读取设备描述符        (GET_DESCRIPTOR)

v主机分配给设备一个总在线的唯一地址    (SET_ADDRESS)

       3.地址态

v主机从新的地址获取设备描述符(GET_DESCRIPTOR)

v主机获取所有设备的配置描述符(GET_DESCRIPTOR)

      4.配置态

v主机设置描述符(设备,配置) (SET_CONFIGURATION)

         v主机读取配置状态(可选) (GET_CONFIGURATION)

v主机读取接口状态(可选) (GET_INTERFACE)

 

.实践篇

在枚举阶段的固件编写中,我主要参考PHILIPS公司提供的D12 USB芯片代码(有参考比自己从零开始要容易很多).由于该代码是基于51单片机编写的,与我所用的16位单片机在性能和结构上有较大差异,因此在固件移植过程中,所遇到的问题大多来源于此.

 

下面是我在移植过程中碰到的四个主要问题。

 

第一个问题,出现在默认态阶段,主机用默认地址读取设备描述符。当MCU收到USB芯片产生的中断时,无法正确读出USB芯片中断寄存器中的值。

这个问题发生在整个枚举过程的一开始,准确的说是第一步,所以我开始怀疑MCUUSB芯片的通信是否真正建立;而在此前,我对它们之间的通信能力一直深信不疑;因为我曾经用MCU发出测试专用指令来读取USB芯片的ID值,并且正确地读到了USB芯片的ID值,从理论上讲MCUUSB的通信已经建立.解决这个问题大约用了半天时间,后来我在MCU读中断寄存器命令后加了一段延时程序,问题得到解决,即中断产生后MCU正确读出了USB芯片中断寄存器的值

我分析原因是MCU发送命令的速度太快,当发送了读USB中断寄存器值命令后,就迅速发送取数据命令,而USB芯片的速度要慢的多,在MCU读数据时还未来得及把数据准备好。之前我读取USB芯片ID值的测试指令是循环发出的,刚开始虽然数据没准备好,但随着指令的循环发出,后面指令自然可以把前面指令准备的数据发出。

 

第二个问题出现在默认态阶段,主机用默认地址读取设备描述符。MCU收到USB芯片产生的中断,却无法进入到正确的中断服务程序。

在第一个问题解决后,立刻又出现了这一问题。通过串口监控,我很快发现,解析中断信息的程序中,有一段程序的功能是互换一个BYTE数据的高低字节位,这一功能主要是针对51单片机数据存放的结构与USB接口芯片的数据结构高低位颠倒而设置的。通过实验我发现:这款16位单片机也不具有51单片机的这一特点,所以只要去掉这段高低字节互换的程序,问题就解决了。

 

第三个问题,出现在地址态阶段,主机获取设备描述符。USB设备响应主机要求,发送16字节的设备描述符给主机,主机不能收到。

因为16字节的数据是通过MCU发送到USB芯片,再由USB芯片发送到

主机的。所以需要判断数据是在哪一个环节没有被正确传输的。我利用串口监测到: MCU收到主机的读中断(读取设备描述符命令)后,会送出了16字节的设备描述符到USB芯片;但是用BUS HOUND(一种基于主机端的USB总线监视软件)监视主机端发现:主机并没有收到这16字节的数据。因此我判断问题出在数据从MCUUSB芯片这一环节——即由MCU发出的设备描述符没有被USB芯片接收到。通过实验,我发现USB芯片没有接收到MCU发来的数据是因为USB芯片的速度较慢,对它来说,每一笔由MCU发出的数据在数据线上保持的时间太短,以致USB芯片无法将数据存放到其寄存器中。当改变MCU的相关设置,延长数据在数据线上保持的时间后,问题得以解决。

   

    第四个问题,出现在配置态阶段,主机设置描述符。通过BUS HOUND监视,主机在SET_CONFIGURATION后停止枚举。

    这个问题是我碰到的最难解决的困难,难就难在一直找不出主机停止枚举的原因,不知道问题产生在哪个环节。通过BUS HOUND可以清楚地看到:主机发出了正确的SET_CONFIGURATION命令,接下来USB设备只需回送一个空包(数据为0)通知主机已收到该命令;可是主机的枚举过程进行到这里却戛然而止。为什么?难道是设备没有发出应答空包,或者是主机没有收到应答空包,还是设备回送的空包有错误?我大约用了5天时间来找支持这些假设的理由。不过,除了证明假设不成立外,一无所获。

第六天,在一次检查BUS HOUND的数据时终于有了新发现。我发现:在SET_CONFIGURATION命令之前,主机发出了GET_DESCRIPTOR来获取全部的描述符合集共46字节数据,设备回复的描述符中在第20多字节时多了一个0字节;不过我并不清楚是否是这个问题对下一步产生了影响,在我看来只要主机在枚举过程中发出了下一步枚举命令,那就表明在此之前的枚举都是正确的(后来的事实证明情况并非如此),后一步的枚举不成功应该与前一步无关。但是因为我再也找不到任何可疑之处,所以只好去寻找那一个字节的0是从哪里来的?又经过了一天的摸索,终于找到了问题的症结。我的描述符数据是以结构体的形势存放的,当MCU收到主机发出的获取描述复命令时,就通过指针的指示将结构体中的数据发出。这些数据大多数是CHAR型,少数几个是INT(症结),对16位单片机来说INT型数据存放是从偶地址开始的,因此,一旦在INT型的数据前有奇数个CHAR型数据,那就天下大乱了,INT型数据会空出一个奇数的地址位,从其后的偶数地址位开始存放数据。这样中间就多出1位的0字节数据。因此当主机那边收到时这笔数据时,从这一位起其后的数据就全部错位了。当我把INT型数据改用2CHAR型表述时,一切就正常了; 同时,在此之后的SET_CONFIGURATION也能顺利进行下去,直到枚举结束。

看来枚举的 GET_DESCRIPTOR阶段如果主机得不到正确得描述符信息,并不会影响该阶段的枚举,而是对SET_CONFIGURATION阶段产生影响,使枚举无法继续。我想这应该是由主机端驱动程序来决定的。

非常幸运,利用BUS HOUND观察到的有限数据中,在最后的几字就出现了异常,否则,这个问题不知道要困扰我多久(BUS HOUND可以显示主机端接收到设备发来的数据,但数据的长度仅为32个字节)

 

 

写在最后

对设备端固件开发而言,如果有专用的USB总线分析仪是最好不过了,不但能监视到主机端收发的数据,而且可以监视到设备端收发的数据,这样,开发的效率会大大提高,开发时间可以大大降低。但如果开发条件像我一样有限,至少应该保证有串口和BUS HOUND这种USB总线监视工具(从网上可以下载),其中,串口可以在枚举的开始阶段使用,监控MCU的相关数据;BUS HOUND则可以在枚举的后期发挥更大的作用,因为此时传输的数据量较大,串口已不太适合作为监视工具了。

此外,在USB设备的枚举程序编写中,我遇到的最大挑战来自于8位单片机与16位单片机的结构上的差别,比如数据存取速度,数据高低字节的存放次序,数据类型与存放地址相关的特点等。从我前面列出的问题来看,大部分问题均源自于此;因此在学习某种单片机时,就要准确地掌握不同类型的MCU特性,这样就一定可以降低开发难度,缩短开发时间。

 

posted on 2007-08-04 21:33 frank.sunny 阅读(5152) 评论(2)  编辑 收藏 引用 所属分类: 硬件开发

FeedBack:
# re: [转]USB设备枚举
2008-09-22 17:52 | yongjieguo
真是好文章!!  回复  更多评论
  
# re: [转]USB设备枚举
2008-10-30 17:00 | someguy
Bushound显示的数据长度是可以自己定义的,在setting里面改max phase的数值就行了  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理



常用链接

留言簿(13)

随笔分类

个人其它博客

基础知识链接

最新评论

阅读排行榜

评论排行榜