您的位置:首页 > 其它

USB SCSI协议整个过程简介

2015-07-09 09:54 441 查看

一.硬件连接

首先,你需要配置你所用芯片的相关USB寄存器值,保证相关功能都已经打开,例如USB PHY 寄存器,USB 中断寄存器等。

Function连接到Host端首先会收到Host端Reset信号,Function进行复位,要进行多次的复位,接着Host会发送Get descriptor(Device)进行首次设备描述符的获取。

二.USB枚举

如果你想确认硬件连接是否正确,可以通过USB协议分析仪,看看Host端是否发送了Get descriptor(Device)命令。Host端发送命令后开始正式的枚举。第一条命令刚才已经提到,当你成功向Host回完你的设备描述符后,Host 会对你的Function进行设置地址,以后就会这个地址进行通信(开始时候默认地址0进行通信)。这里要注意的是,你需要判断Setuppack(定义的请求的命令格式,是一个结构体),Setuppack.wLength与你的报告描述符的长度,因为一般端点Maxpack是64,而设备描述符等需要传输的长度小于64字节,所以你发送的长度应该是两者的小值。长度回应不对会导致Host端没有回应ACK。获取第一次设备描述符获取完毕之后,你就要对Set
address请求进行回复,之后会进行这样一个过程:Device->config->Device->config->set config 过程,这里也要注意命令需要回复的长度。
if(setuppack.wLength>sizeof(Config_Description))
setuppack.wLength = sizeof(Config_Description);
最后Host端会发送请求:Get max lun 类请求。这个请求是获取最大逻辑单元。响应为一字节位(0~15)。如果你在BUS HOUND里看到CBW命令包的命令,那么说明前面枚举应该是成功了。
我总结的整个枚举过程应该是:Get descriptor(Device)->Set address(回复一个空包)->Get descriptor(Device)->Get descriptor(Configuration)->Get descriptor(Device)->Get descriptor(Configuration)->Set configuration->Get Max Lun->CBW。

三.USB SCSI(UFI)命令集

之所以我在括号里加了UFI,这是因为我看圈圈的书,在Host其实使用的UFI命令集,但是将接口子协议定义为UFI命令集,Host端电脑又不识别,然后又不是全是UFI命令集,这个比较怪,我也是暂时将他就看做SCSI命令集。关于CBW,CSW命令格式可以在网上查询一下,主要还是看标识头0x53425355。我认为需要的响应的命令主要有inquiry request(0x12),get configuration(0x46),mode
sense10(mode sense6)(0x5a(0x1a)),read capacity(0x25),readtoc(0x43),read10(0x28),testunitready(0x00),
其他的命令我均回复了一个空包。这些命令响应全部正确的会,Host端会一直不断的发送testunitready(0x00)命令,我们只要一直响应这个命令就可以了。我是认为只要一直发送testunitready(0x00)就可以稳定的进行数据传输了吧。
这里注意一点,也是我这次第一次写USBSCSI协议最深刻的一点,那就是我将USB_SCSI_CBW处理函数放在了中断函数里去处理,导致会莫名其妙的出现大量的NAK,一直过不了0x28这条命令,我是这样认为的:SCSI协议是批量传输,中断的时间比在主程序while里的慢很多,所以在下一个中断来之前Function一直回复的是NAK,对于FS来说一帧是1ms,而一帧里面可以传输了多个事务,所以会回复大量的NAK(此处还望高人指点)。
最后总结3点:
1.Receive CBW,根据CBWCS[0],判断命令,再根据SCSI协议进行命令响应,最后发CSW。
2.对于命令响应了空包加CSW。
3.Host发完需要响应的命令一直会发送testunitready。
最后我利用公司测试工具进行传输测试,可以进行传输。(注:回调函数,return:终止剩下的程序) 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  USB SCSI usb 通信