7351|17

74

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

请教USB HOST开发中批量传输问题 [复制链接]


最近用LPC2378+ISP1161做一个USB host项目,除下了几个问题,拿出来和大家讨论一下:
批量传输问题。一次读或写操作有三个阶段:命令、数据、状态。调用三次批量传输实现三个阶段。在我的程序中,我的一次读写操作是都是读或者写512字节,也就是刚好一个扇区数据。读操作没有问题,但是写操作过程中,命令阶段后面,程序必须延时以等待命令执行。请教过别人之后,说是因为U盘接受到你的写命令之后首先要准备你要写的扇区(即U盘要先将你要写的flash擦除,这需要时间),然后在随后的数据阶段,才能接受主机发送来的数据。现在的问题是,就算是这样,且我的程序中不用延时等待,按照1161数据手册的说法,1161也应该会在命令阶段之后的数据阶段中收到设备返回的NAK信号,若收到NAK信号,1161在处理时就不会将PTD的active位由1更新为0,在下一次扫描中,1161会将active位为1的数据在处理一次,只有成功后才将active位由1更新为0,并退出数据阶段,执行随后的状态阶段。但是,我现在的实际情况是每次命令阶段之后的数据阶段,好像1161并没有按照1161数据手册描述的那样处理,而是在收到NAK信号后就直接退出数据阶段并返回出错信息,错误为“实际传送的数据量与期望传送的数据量不符”。我现在的解决方法是在命令阶段之后加入延时,等待U盘准备好接受数据后再发送数据。这样做有两个明显的缺陷:(1),由于在延时的过程中不知道U盘是何时准备好的,所以只能傻傻的等固定的延时后再去送数据,所以导致写速度很慢;(2),由于各个U盘厂商的U盘固件程序不同,命令阶段后的等待时间也不同,而我在程序中要么给个很大的延时以支持较多的设备而导致速度相当慢,到了坚决无法忍受的地步,要么加入短延时支持仅有的少量设备而使时间控制在可以忍受的范围内。我想问的是有没有一种办法,比如说中断,来告诉我的程序,U盘已经准备好的,可以进入数据阶段了!!
谢谢!!!

最新回复

你是怎么解决的啊 说给我们听听啊 我也碰到这个问题了  详情 回复 发表于 2009-12-29 21:51
点赞 关注

回复
举报

77

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
自己顶
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
帮顶

 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

4
 
“我想问的是有没有一种办法,比如说中断,来告诉我的程序,U盘已经准备好的,可以进入数据阶段了!! ”
>>就我所知,总线上是没有这样的物理上的信号来告诉Host端:设备端已经准备好,能一次性的成功接收数据。
  至于是否有一些非常用的scsi命令来得到这个信息,我就没有研究了(即便有也是不可取的)。

而你做的command阶段之后的延时做法肯定是不可取的,比如有的设备有时候需要受到write的cbw之后要等3s
才能接受好数据,那么你是否在代码中都延时3s?

1161应该是Host端的usb传输芯片吧?
在Data阶段,主机端发Out Token+Data,如果设备端没有准备好接收数据,那么应该会回应NAK。
在Host端收到Nak,再重发Out Token+Data,直到成功执行,收到ACK。重发一般都由硬件来完成,
由于效率比较高。一般嵌入式设备应该都是这种做法。

如果1161的硬件就是“收到NAK就退出”这样设计的,那是否可以考虑软件重发?
当然这时候你可以设定重发的时间,超过这个时间就认为write失败。上层可以再来选择retry 整个命令。
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

5
 
楼上说的很有道理,十分感谢!!

针对您所说的,我还有一点点疑问:
1,就像您说的,我也觉得如果数据阶段受到了NAK信号,那么硬件会自动将数据重新发送失败了的数据,
现在的情况是硬件似乎并没有重新发送上次发送失败了的数据,或者也有可能是虽然重新发送了,但是重发也没有
执行正确,所以返回了“实际传送的数据量与期望传送的数据量不符”的错误。但是按照1161的数据手册,硬件确实应该是
重新发过的。
2,如上所述,不管1161在收到NAK信号后到底有没有重发数据(不论发了没成功或者根本就没有重发),那么我应该考虑软件重发,
我现在的做法是,如果返回出错,那么就先设置设备重启,然后清楚端点bulk-in ,bulk-out的内容,最后将整个命令、数据、状态三个阶段都重新发送一次,
但是这样做虽然起到一定的作用,但是效果并不是很理想。即使重试多次,也还是收到同样的错误。   请问我的这种做法对不对?有没有更好的做法呢?你所说的将在上层来retry,是只重试数据阶段,
还是命令、数据、状态三个阶段都重试?

谢谢!!!
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

6
 
对于问题1:
>>如果硬件手册上说收到NAK的情况下重发,但实际上没有重发 ,我觉得可以先检查检查相关寄存器的设置是否正确。

对于问题2:
“我现在的做法是,如果返回出错,那么就先设置设备重启,然后清楚端点bulk-in   ,bulk-out的内容,最后将整个命令、数据、状态三个阶段都重新发送一次”
>>我说的重发是指只重发数据阶段,这是很common的做法,写数据收到NAK也是很很正常的事情。
上层retry是指在底层已经无法恢复(出错或给定时间内仍然NAK)的情况下,software的更上层重试整个命令(包括命令数据状态三个阶段)。

不过我觉得该问题可能需要从根源去查:硬件收到NAK重发了吗?为什么没有重发?这样也许能更快且有效的解决此问题。
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

7
 
谢谢,问题正在解决中!!!
谢谢ilyh!!!!
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

8
 
to: ilyh
上面的问题经过你的提醒与指导,基本得到解决。不过还有一个小问题,我一直想不明白,能否请您
再指教指教:我在发完命令,数据后,读取设备返回的状态,有时候会出现这样的情况:读取CSW的时候
总是收到NAK信号,并且重试多次之后一直是NAK,好像永远读不到CSW似的,不知道为什么。
我现在的解决办法是,如果在状态阶段连续100次都收到NAK信号,则返回错误,用控制端点发送命令让
设备复位,然后将上次出错的命令数据状态再重新发送。可问题是即使我发送复位信号,
设备还是不响应随后批量传输命令,一直是NAK,请问这种情况应该如何处理?谢谢!!
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

9
 
是不是你CBW的参数设置不对啊(要的数据长度不合spec)~~瞎猜的,
没遇到过这种状况,一般CSW都会很快返回的。不过才100次的NAK似乎太少了,至少要一个1-2ms吧。
 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

10
 
to:ilyh

我检查过CBW的设置,应该没有错误,要是有错误的话应该是一次也不会成功的写入数据的啊,可是现在是前面的数个扇区都写着正常,写着写着就出错了,就读不到CSW了。我原来是用do-while循环读的,可程序老是死在这里,就是过不去,所以我才设置了100次循环。
如果100次循环仍然读不到,那么就设置设备重启,(MassStorageReset,dev_req.bmRequestType = 0x21;dev_req.bRequest = 0xff;),然后清除批量输入、输出端点停止位(ClearEndpointSTALL,dev_req.bmRequestType = 0x02;dev_req.bRequest = 0x01;),然后再重新发送出错了的CBW,结果不论你发什么东西,批量端点就是不理我(NAK),而且一直是NAK。

请问这样的话怎么处理啊?
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

11
 
是Read还是Write?

最初的出错位置是
CBW?
还是DATA?
还是CSW?

“然后再重新发送出错了的CBW,结果不论你发什么东西,批量端点就是不理我(NAK),而且一直是NAK。”
>>这个是不是可能与Toggle Bit有关?可以看看Spec上关于Toggle Bit的论述。

有USB数据分析仪吗?分析仪能更快的帮助你解决问题。

用二分法慢慢排除,从而找出根源。既然是USB Firmware的底层的开发,还是要从根源上解决问题,

尽量一次成功,尽量不要用retry这样的方式,除非是设备本身有问题。
 
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

12
 
host controller如果发现数据和状态包没有全部收到,因该丢弃当前数据,然后再次请求发送, 要有test unit ready, 和reset masstorage,或者还不行,应该重新配置设备, 感觉你这边usb host的动作没有 按照USB spec走,这样不能兼容所有设备的。当然每次reset,应该将状态toggle恢复为0
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

13
 
谢谢楼上两位
我现在是如果出错,丢弃出错数据,然后,reset   masstorage,再重新请求数据的,但是即使我reset   masstorage,然后重新请求数据,设备也没有返回数据,仔细查看了一下,我复位恢复之后,在给设备发任何东西,好像都没有用,写进1161的FIFO缓冲区的PTD什么样,读出来还是什么样,好像1161根本就没有处理缓冲区的PTD似的,但是在PTD写进缓冲区前后,1161的HC_BufferStatus寄存器的值也会正常的变化,可就是他不对PTD进行处理,
楼上的意思是如果这样还是不行,那么就对设备进行断电上电,然后再重新枚举之后,再请求出错了的数据么?
硬件平台 ARM+ISP1161,读写u盘


PS:我的test   unit   ready函数不知道为什么,对有的U盘没有任何问题,但是有的U盘返回的CSW中的bCSWStatus域总是1而非正常的0,一直高不明白哪里有问题,检查裹好几遍我的函数,没看出来有什么为题,有人遇到过或知道这个问题的话,指教一下啊!
谢谢!!
 
 
 

回复

85

帖子

0

TA的资源

一粒金砂(初级)

14
 
我的test       unit       ready函数不知道为什么,对有的U盘没有任何问题,但是有的U盘返回的CSW中的bCSWStatus域总是1而非正常的0


>>有些设备就是会对test unit ready一直返回1,遇到过几个这样的设备,这是比较常见的。

电脑上好像并不是主要靠这个指令来判定设备媒体状态的,而是主要靠0x25+0x03。主要还是这个0x03(request sense)。
 
 
 

回复

89

帖子

0

TA的资源

一粒金砂(初级)

15
 
说到这个GetThisMediumCapacity,我遇到个小问题,这个0x25命令获得容量的时候,对于有少数u盘,第一次的时候返回错误代码04(Stall),我用ClearEndpointSTALL清除端点停止特性的后,第二次发CBW,然后IN-DATA,可就是没有数据,IN不到DATA数据,
我的程序执行过程
CBW:00,正确
DATA:04,STALL
ClearEndpointSTALL:00,正确
ClearEndpointSTALL:00,正确
CSW:00,正确
第二次CBW:00,正确
第二次DATA:无数据返回,程序死掉
 
 
 

回复

48

帖子

0

TA的资源

禁止发言

16
 
谢谢楼上各位的支持,虽然问题没有全部圆满解决,但是已经快了,现在结贴散分。

谢谢!!
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

17
 
请教一个 问题 : 谢谢先

“:我在发完命令,数据后,读取设备返回的状态,有时候会出现这样的情况:读取CSW的时候
总是收到NAK信号,并且重试多次之后一直是NAK,好像永远读不到CSW似的,不知道为什么。”

这个 是 您在2007年12月的提问 , 我也遇到了类似问题, 请问后来 是如何解决 的? 谢谢!
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

18
 
你是怎么解决的啊
说给我们听听啊
我也碰到这个问题了
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表