阅读:1542回复:7
(90分请教)usb host设置地址超时的问题
嵌入式系统上是arm9+usb ohci控制器(这个集成在arm一起),跑linux2.4.14系统。遵循usb ohci协议。
将PC机的linux系统下usb-ohci驱动移植到这个嵌入式系统中,ohci的各个寄存器都写入初始化好了。插入usb设备时能够检测到设备(不过会出现两次,不知道这是什么原因?),可是在设置usb设备地址(set_address)时总是超时。我用示波器看过,好像是有数据发出了,因为有变化的波形。 如果正确数据发出的话(我的usb设备是好的),那么就会返回一个状态,而此时我的ohci没有产生“Write done head”中断,就说明ohci根本没有接收到这个状态(不管是正确与否的状态都应该产生这个中断啊,从而进行TD处理),ED中的HeadP指针也是没有改变。请问一下会不会是发出的数据根本就不正确啊?从而导致usb设备不知道如何处理(从而没有处理)? 如果正确的发出了数据,那么usb 设备一定会返回一个状态,此时没有产生中断,是否表明ohci接收数据有问题?硬件上不应该出现问题,那么就是软件设置的问题了,请问我该怎么处理呢? 我跟踪了set_address命令,发现在ED队列中产生了两个TD,但是本来在ED队列中就有一个TD(HeadP和TailP都指向它),所以总共有3个TD,setup命令数据在第一个TD中,最后一个TD什么事情都不作,仅仅是其NextTD为0。我从ohci协议中得知,当ED的HeadP指针和TailP指针指向同一个TD时就认为已经处理完所有TD了。我想如果在set_address命令中,只是处理前两个TD,而到第三个TD时由于HeadP和TailP相同,就结束了,从而没有处理第三个TD。不知道我这样理解是不是正确呢? 各位大虾一定帮我分析一下原因啊,搞了好长时间了,老是不能解决这个问题,快要疯掉啦 小弟在此先行谢过各位啦! 或者发邮件给我:flycat0101@sohu.com |
|
最新喜欢:wdy992...
|
沙发#
发布于:2003-12-05 15:29
插入usb设备时能够检测到设备(不过会出现两次,不知道这是什么原因?) 通过什么读到两次插入设备的? 寄存器?中断?
可能是SOF的波形。
如果一个TD传输完毕,不管成功还是出错,肯定ED里面相应的值要发生改变。相应的中断也会出现。 估计是软件上的问题。
对的! 可以看看TD中的data toggle 有没有设置正确。另外在set address 之前有没有获得endpoint0的maxpacketsize ? |
|
板凳#
发布于:2003-12-08 11:54
[quote]插入usb设备时能够检测到设备(不过会出现两次,不知道这是什么原因?) 通过什么读到两次插入设备的? 寄存器?中断?
可能是SOF的波形。
如果一个TD传输完毕,不管成功还是出错,肯定ED里面相应的值要发生改变。相应的中断也会出现。 估计是软件上的问题。
对的! 可以看看TD中的data toggle 有没有设置正确。另外在set address 之前有没有获得endpoint0的maxpacketsize ? [/quote] 对于第一个问题,我找到了原因。其实读到一次设备插入,然后进行设备枚举,如果不成功就重新再枚举一次,所以就出现了分配两次地址的情况,如果第一次枚举成功就不会出现第二次了。linux中检测root hub状态的是由一个专门的定时器控制,检查其寄存器状态,同时再配合一个hub的事件队列。进行usb枚举是有一个专门的线程完成。如果状态改变,同时hub事件队列为空,则唤醒线程进行枚举。 设置地址时出现的波形的问题。 如果是SOF的话,应该每次都是一样的吧?并且在没有设备插入时也应该有SOF的,可是在没有插入设备时没有出现波形,当枚举停止时也就没有波形出现了,同时每次的波形还不一样。所有我怀疑是不是发出的数据不对(也有可能是每次设置的地址不一样引起)。 再问一个问题,每次的SOF都会产生一个输出的波形吗?这个波形是什么样子的? 有没有可能我的数据发出后没有收到usb设备返回的状态信息,从而一直处于等待状态返回的状态?导致最后的超时? 我是按照linux中usb部分的源码改的,涉及到TD部分几乎没有动过,我想data toggle 估计是没有问题的。另外就是在linux中他是先设置usb设备的地址,然后再取得设备描述符的前8个字节的,也就是获得endpoint0的maxpacketsize。对于设置地址来说,我认为这个在前或者是在后是没有影响的。 大侠,再帮我分析分析 唉,公司里就我一个人作这个东东,没有人交流啊 郁闷! |
|
|
地板#
发布于:2003-12-08 17:26
如果是SOF的话,应该每次都是一样的吧? 这么肯定? 那framenumber 和 crc5 是相同的么?
建议看看ohci规范, SOF什么时候产生?
有。 没有传输的时候看到的波形只会是SOF。
sure
偶没看过linux, 不清楚。
要是不先获得maxpacketsize的话, control传输就可能出错。 你做usb driver有多久了? 呵呵 :cool: [编辑 - 12/8/03 by dopy26] |
|
地下室#
发布于:2003-12-08 19:03
[quote]如果是SOF的话,应该每次都是一样的吧? 这么肯定? 那framenumber 和 crc5 是相同的么?
建议看看ohci规范, SOF什么时候产生?
有。 没有传输的时候看到的波形只会是SOF。 要是不先获得maxpacketsize的话, control传输就可能出错。 你做usb driver有多久了? 呵呵 :cool: [编辑 - 12/8/03 by dopy26] [/quote] 呵呵,大侠见笑了,我作usb host也4个月了,不过从来没有注意过这个sof,因为没有用到过。 我又仔细看了一下波形,每一毫秒产生一个波形,并且前面部分几乎不变。这是一个SOF波形。我把从示波器上得到的最后一个信号画出来了,也作为附件传上来了。 这么看来是我的数据根本就没有发出来,唉,还得看看芯片文档。 这个usb host是集成在一颗ARM芯片中的,usb host和内存交换数据不是经过ARM的MMU,而是经过一个Local Bus和Local Bus MMU,看来是local bus有问题,唉,郁闷。 多谢大侠了,长了一些见识。 分数先送上。 另外再问一个问题,就是我的usb host端没有什么问题吧?下面是我在set_address时得到的一些数据: First TD MPUVA:C09B7180 LBVA:309B7180 TD[0] MPUVA:C09B71C0 LBVA:309B71C0 TD[1] MPUVA:C09B7200 LBVA:309B7200 TD1->hwCBP:30B3FAC0 hwBE:30B3FAC7 TD2->hwCBP:0 hwBE:0 ED->hwHeadP:309B7180 hwTailP:309B7200 MPUVA是arm的虚拟地址,后者LBVA是local bus虚拟地址,也就是usb host所要的地址(一般PC机中这个地址是物理地址),这两个地址指向相同的物理地址.从这些数据看,好像是没有什么问题的呀,是吗? 最后一点就是set_address命令是只有8个字节的setup命令,没有数据返回;而取得maxpacketsize的命令也是8个字节的,只是它要求返回数据,如果不取得maxpacketsize而按8个字节进行传输的话,也不会出现问题,你以为呢?所以我认为这个地方不会出现问题。 |
|
|
5楼#
发布于:2003-12-09 11:28
我觉得td2应该是ohci规范上说的Null TD。从上面的数据看来, 这个null td并没有放在TD序列上。所以当ED中的headP=309b7200 = tailP =309b7200 的时候传输就停下来了,而309b7200这个TD的传输不会产生。 建议读一下OHCI的相关内容。
会出问题, 虽然很多设备的control endpoint maxpacketsize都是8,但并不都是。 我用过的一款U disk就是64byte , hehe, 猜猜会出什么错? |
|
6楼#
发布于:2003-12-09 13:02
[quote] 我觉得td2应该是ohci规范上说的Null TD。从上面的数据看来, 这个null td并没有放在TD序列上。所以当ED中的headP=309b7200 = tailP =309b7200 的时候传输就停下来了,而309b7200这个TD的传输不会产生。 建议读一下OHCI的相关内容。
会出问题, 虽然很多设备的control endpoint maxpacketsize都是8,但并不都是。 我用过的一款U disk就是64byte , hehe, 猜猜会出什么错? [/quote] 上传的数据没有表达清楚,应该是这样: TD[0] MPUVA:C09B7180 LBVA:309B7180 TD[1] MPUVA:C09B71C0 LBVA:309B71C0 TD[2] MPUVA:C09B7200 LBVA:309B7200 TD[0]->hwCBP:30B3FAC0 hwBE:30B3FAC7 TD[1]->hwCBP:0 hwBE:0 ED->hwHeadP:309B7180 hwTailP:309B7200 TD0的NextTD指向TD1,TD1的NextTD指向TD2,而TD2的NextTD为0 由于是设置地址,只有8个字节的数据,所以只有第一个TD有数据,而第二个TD是没有数据的,其DP为输入;所有这三个TD都挂入队列了。 如果你说的那个U disk是必须用64byte的话,那么第一个命令(得到前8个字节的get_descriptor,在windows系统中)就会出错了吧? |
|
|
7楼#
发布于:2003-12-09 15:30
TD是用对了的。
如果U disk 的control endpoint maxpacketsize = 64 ,而你在ED中相应的值是8,就会data overrun . 所以我一开始就说 : 在set address之前必须先作一遍 get_DeviceDescriptor (得到maxpacketsize)。 |
|