没有时间把一件事情做好,却有时间把一件事情反复做!
全部博文(191)
分类: LINUX
2015-03-17 09:42:41
原文地址:OTG调试<转载> 作者:shangbaogen
http://blog.csdn.net/ccwwff/archive/2011/06/10/6537452.aspx
一、调试背景:
我所使用的处理器有一个USB 1.1 host接口,但是速度太慢,最高速度12Mbps;另外还有一个OTG接口,兼容EHCI(host), device, OTG, 通常这个接口会用来处理Mass storage和Android的adb调试,作为slave接口,连接PC机。也可以用来连接如wifi,3G, 无线电视等高速通信模块,这里将作为host接口。因此,这里就需复用一个OTG接口,分别充当host或device的角色,目前实现方法有两种:模拟开关与hub连接。模拟开关我认为控制简单,且不会影响连接速度。
二、调试的这些招数:
1. 这行文字的出现,让我看到了春天:
“usb 1-1: new high speed USB device using xxx9xx-ehci and address 2”
调试usb host驱动,这行串口输出的文字,一定能让你兴奋无比,因为这代表这你要的USB ehci(host)设备驱动已经加载,至于成功不成功,还得往后看,如果后面再没有错误信息出现,那么,恭喜你,你的USB设备已经成功枚举,后面就是加载厂商提供的设备驱动了,如果您比较幸运,轻松就可以完成工作,拿到奖金。但是,不一定每一次都会这么的幸运,人总需要在逆镜中成长,为了这一行文字,不幸的朋友和幸运的朋友都跟我一起来看看其中的奥妙吧。
1)首先我们来看看你的系统有几个USB相关的驱动,分析你的USB驱动架构;
xxx-otg
xxx-u2o
xxx-u2h
xxx-ehci -> 对应于 drivers/usb/host/ehci-xxx.c, drivers/usb/host/ehci-hcd.c中有对应注册的模块位置;
mass storage, adb驱动通常都会在gadget驱动中实现。
2)找到我们想要的USB模块吧,如果没有就自己依照现有例程编一个吧,EHCI有自己的标准驱动函数结构,并在drivers/usb/host/ehci-hcd.c注册你要的ehci host驱动;
3)ehci-xxx.c中,通过usb_add_hcd()加载你想要的hcd驱动,也可通过usb_remove_hcd()移除hcd驱动,在probe加载hcd驱动之后,就可以在设备启动上电后,检测到,并打印出上面引号中的一行;
4)khubd是一个关键的内核进程,USB设备的即插即用就全靠他了,在drivers/usb/core/hub.c中实现,系统启动后,用ps命令可以看到这个内核线程。
2. 这行文字一定让你疯狂,khubd timed out,天哪。Hi, 朋友,忍忍吧,看完所有的USB代码,仍然不知所措,这时候,只能叹息一下可怜的工程师命运,认命吧,这就是工程师的宿命,也难怪有两下嘴皮子工夫的都不来干这苦哈哈事情,也不能寐的日子从此开始了,可产生的原因和结果,往往让你大跌眼镜。不管怎么样,还是先来分析一下产生的原因吧。
“usb 1-1: khubd timed out on ep0in len=18/64”
1)先看一看这行文字在哪里吧,find命令在drivers/usb/core/message.c中usb_start_wait_urb()函数里发现了它,执行wait_for_complete_timeout()后出现超时,而报错;
2)再往下看吧,wait_for_complete_timeout()等待context->done的置位,如果在限定时间没有置位,则出现超时错误,然后往上层函数返回错误,然后USB会尝试再枚举几次,打印如下文字:
“usb 1-1: new high speed USB device using xxx9xx-ehci and address 2”
“usb 1-1: new high speed USB device using xxx9xx-ehci and address 3”
“usb 1-1: new high speed USB device using xxx9xx-ehci and address 4”
…
最后以无奈地失败告终。我这里便跟系统开了个玩笑,不管超时了,直接将其返回0(成功),哈哈,看来软件没有我想象想象的智能,居然显示枚举成功了,我不知道是该哭还是笑,是不是黎明前的黑暗呢,不管怎样,生活还得继续,坚持就会成功;
3)context->done到底在哪里置位呀,调查中发现,ehci_irq调用到了urb->complete(), 对context->done进行置位,调试发现ehci中断启动正常,ehci_irq()也会启动,为什么就是不会调用到urb->complete()呢?天哪,中断状态寄存器状态不正常呀,根本检测不到是什么中断,也就不对其中断进行处理了,系统认为已经处理好了中断,不理他了,让khubd苦苦相等,愁白了头呀,没路了。这里还有一个奇怪的现象,系统启动里,设备ehci中断状态竟然正常,枚举成功,再次启动USB设备,就会出现time out的错误;
4)实在没招,按照多年调试驱动的直觉经验,开始怀疑是不是USB reset不正常,开始啃USB specification, 研究USB reset, 发现除了SE0信号与PC reset信号有些差别外,没什么本质的差别,况且启动时的成功枚举时,reset信号也差不了太多呀,我只有无情地排除了这个假设;
5)“山重水复疑无路”,也不知道那“一村”什么时候才能找到了,喝杯茶吧。之前也试了好多次,ID pin脚接地,以前也调过,一般ID pin脚接地后,host驱动加载都很正常,这次发现都不灵了。一杯茶水下肚,奇迹发生了,看来还是特级龙井的威力大呀,启动后,ID pin脚接地,再次加载驱动,中断状态正常,枚举成功,这样屡试不爽,次次成功。
3. 看到类似这一行文字,没有别的错误出现,朋友,如果几天没睡个好觉,那么什么也别想了,好好睡一觉,再干吧。多少美好的青春岁月,流失到了这如烟如海的代码之中,别迷失了自我,还有更多比这代码更重要的东西在。痛苦在这里也暂告一段落,找个电影好好欣赏一下吧,忘记昨日的痛苦,享受一下成就,尽管明天还有痛。
“usb 1-1: configuration #1 chosen from 1 choice。”
如果打开了调试用的宏定义,还会看到以下更详细的枚举信息。
usb 1-1: New USB device found, idVendor=148f, idProduct=3070
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1: Product: 802.11 n WLAN
usb 1-1: Manufacturer: Ralink
usb 1-1: SerialNumber: 1.0
4. 世界永远都不是千篇一率的,不要永远期望自已掉进的是同一个陷井,下一次你遇到的不一定是同样的问题,从原理上根本的掌握,才能真正的处变不惊,成为一个真正成熟而优秀的BSP工程师。建议认真的通篇读一读第三部分提到的标准文档,比看任何资料都有用,当然这要考验你的英文功底了。真正优秀的BSP工程师,不能仅仅是软件,对硬件时序更应成竹在胸。这里所看的现象,不一定是您能遇上的,对设备时序的理解才是真正的王道。
我们不妨来看看几个USB的时序吧,几个经验跟大家分享一下吧。
1)reset时序:
(图1)
(图2)
如图1, 图2, 两根信号线分别是USB D+/D- pin脚,图1是与PC机USB连接时,产生的reset信号,SE0, KJKJKJ信号都非常清楚,图2是我所调试的嵌入式USB设备连接时,
产生的reset信号,SE0信号表现的不是很清楚,其实我后来发现,各种不同设备是有差异的,这也是正常的reset时序。
2)枚举过程时序:
(图3)
图3是一个USB reset,设备枚举的数据传输过程,USB插入后,D+拉低,然后reset, 然后,开始数据传输,USB2.0数据传输的脉冲比较低,一般只有500mV左右。
三、建议一定要看的参考资料:
1. Universal Serial Bus Specification, Rev. 2.0.
这个是对付USB必备的宝典,个人认为第七章和第九章是需要认真读的,特别是第七章,主要是讲接口的时序,不妨用示波器对照分析一下,一定收获不小,哥们,行动吧,别看着问题束手无策。
2. Enhanced Host Control Interface Specification for Universal Serial Bus.
这个是USB补充标准文档,如果你的USB host也是EHCI标准的,那么跟你的CPU spec中描述的EHCI章节对照阅读一下吧,有些不一定会是完全标准的EHCI接口,所以寄存器定义和配备都不会完全一样,不过也都大同小异了。
3. On-The-Go Supplement to the USB2.0 Specification, Rev 1.0
这也是USB的增补文档,OTG接口可以做host角色, 也可以作device角色,但他不是Host, 也不是device, 在他确认自己的角色之前,一般有两个硬件协议时序:HNP, SRP, 不过我遇到的真正支持OTG的设备不多,那最后,我只有强制将其设置为Host角色或者Device角色了,那么OTG接口的ID pin脚就可以实现你的愿望了,如果要强制为Host, ID pin脚就需要拉低,OTG文档要求ID pin脚对地不能高于10Ω。详细的自己去学习吧。
4. USBlyzer工具,PC上的好工具,学习分析USB协议的好工具,好好利用一下吧。
http://blog.csdn.net/ling1874/article/details/5758883