简单说说USB协议(二)包的结构与包的分类

        无论是什么传输设备,通信的过程就涉及到传输方法,USB协议中有四种传输方式:批量传输、中断传输,等时传输,控制传输。因此在这些传输方式上传输的都是包,所以在了解传输方式前,还需要知道包是个什么东西。

        之前说了USB协议通信的大概过程,获取各种描述符的过程本质上0和1的输出传输,加上USB协议的串行总线,因此0和1这些数据是一位一位发出去的,而USB协议中采用的LSB(低位先发)传输模式,即最先发送出去的是最低位的数据,最高位数据最后发送。

        但是实际逻辑上并不是木讷的0和1无时无刻发送出去,这些即在这各种信息的0和1,会被封装成包的形式发送出去,包的种类也多样化,有令牌包、数据包、握手包、特殊包。

        之前一直强调的各种描述符信息,就被放在了数据包里面。

        每一类包,都由几部分组成,比如令牌包的组成:

        比如数据包的组成:

        比如握手包的组成:

        看完会发现,不同的包有共同的三个部分:就是都是由同步域开始,紧跟着是包标识PID,最后以EOP结束符结束代表一整个包的结束,三个部分,每一个都有不可或缺的功能。

        同步域是用来告诉USB串行接口数据就要开始传输啦,请做好准备。

        它是以一连串的0开始的,而在USB总线协议NRZI编码中,0被编码为电平翻转,结果就是每一个数据都在发生电平翻转,这样的目的在于串行接口就很容易采集到电平时钟信号,同时,也能同步主机与从机两者的数据时钟。

        在低速和全速设备中,同步域为00000001;在高速设备中,同步域以31个0开头,以1结束,提醒一下,这是对发送端而言的,接收端在接收数据的时候,接收到的0的个数可以少。

        由于在NRZI编码中,1是代表电平不变的,同步域在发送的时候,串行接口会一直检测到电平翻转,当检测到电平不翻转时,就说明同步域已经处理完毕了,开始读取包标识PID数据。

        包标识PID是用来标识一个包的类型,由8个数据位表示,真正用来代表不同类型的是由前四位PID0~PID3,后四位PID4~PID7则是前四位的取反,目的在于检测检验PID有没有出错。

        而在前四位中,又只有前两位PID0~PID1用来表示包类型,其中01是令牌包,11是数据包。10是握手包,00是特殊包。

        EOP这个结束标志,对于不同速度来说也是不一样的,低速和全速的设备结束标志是一个2个数据位的SE0;

        何为SE0,就是D-和D+两条数据线同时为0;平常数据数据D-和D+通常都是一高一低的,两条数据线都处于低电平是一种特殊现象,刚好可以表示特殊的意义,结束标志就是其中一种。

        除此之外还可以表示复位信号,其实在一个USB设备刚插入主机并被检测到的时候,主机会将设备进行复位操作,就是将D-和D+设置成SE0状态大约10ms来实现的。

        言归正传,在高速设备下,EOP结束标志是用位填充错误来表示的,那么就产生一个问题,用什么可以判断EOP是位填充导致的错误还是真的出现错误了呢,在令牌包和数据包上存在一个CRC校验数据,就是用它来判断的,如果校验正确,说明是位填充错误。

        好了,说完各种包的共同部分,接下来就要捋一捋不同类型的包各自的特点:

1、令牌包

        令牌包是由主机发出的,用来开启一段USB传输,因为我们知道USB是主从模式,都是由主机主动发出数据,从机都是被动的应答,那从机怎么知道什么时候应答呢,就需要主机发出一个令牌包来通知:让设备做好准备,要开始响应了。

        令牌包有四种:

        1、OUT输出数据包

        2、IN输出数据包

        3、SETUP建立数据包

        4、SOF帧起始数据包

        OUT输出:用来通知从机,主机要给你发送一个数据包了,接好咯;

        IN输入:用来通知从机,你要给本大人发一个数据包,不得抗命;

        SETUP建立:这个令牌包只存在于控制传输的建立过程中,也是用来告诉从机,主机要给你发送一个数据了,接好咯。功能跟OUT输出是一样的,唯一不同的是,SETUP建立数据包只能传输DATD0数据包,而且从机还必须要接收;而OUT输出数据包则没有那么多规则。

        这是前面看到的包的组成,这是OUT输出,IN输入,SETUP建立令牌包的组成,除了共有的同步域,包标识PID和结束标识符外,7位地址指的是USB设备地址;4位端点号是端点地址;5位CRC5校验是用来检验PID之后的地址域和端点域,不包括PID。

        SOF帧起始:这个令牌包是在每帧开始的时候开始发送的,而且由于是广播形式发送,所以所有的全速和高速设备都可以收到;全速设备是1ms产生一帧,高速设备是125us产生一帧;每一帧开始的时候主机开始计数帧号,然后将11位的帧号发送出去。

        而且跟上面三种数据包相比,SOF令牌包是唯一后面不接数据包的,所以貌似看起来没什么卵用,额,在没有实际用到它的时候,确实是没什么卵用。

        这是之前看到的另一个令牌包组成,除了包共有的同步域、包标志和结束标志符,特有的11位帧号域是主机计数的帧号,5位CRC5校验用来检验PID之后的帧号域,不包括PID。

2、数据包

        数据包,就是用来存放数据的包啊,看一下数据包的不同的域组成:

        其中字节域就是用来存放数据的,16位CRC16校验就是用来校验PID之后的字节域,不包括PID。

        跟令牌包一样,数据包也有不同的种类,在USB1.1中就有DATA0和DATA1,而到了USB2.0又增加了DATA2跟MDATA,这两种包主要用来高速分裂事务和高速高带宽同步事务中,平时很少用到,主要用的还是DATA0和DATA1;

        这里就有一个问题,数据包不就是是传输数据用的吗,需要传输什么数据,放进去不就得了,为什么还整出不同类型的数据包出来?

        这么搞的原因是为了检验数据在传输的时候有没有出错。为此USB协议中,在主机和设备都制定了这样的检验纠错机制,检验纠错的原理就是数据包类型切换。

        假设现在有主机A和从机B,大致的检验过程是这样的:A发送一个输入令牌包给B,B接收到后不敢怠慢,立马发送了一个数据包DATA0(假设发过去的数据包是DATA0),A接收到后此时A端的数据就成了DATA0类型,并返回给B一个应答信号,B接收到应答信号后就把自身的DATA0数据包类型切换成DATA1类型;

        当下一次需要时,A献给B发一个输入令牌包,上一次B发送数据包时发送的类型就是DATA0的,由于类型切换已经变成了DATA1了,A接收到B传来的数据包时,会进行一个判断,如果跟自身数据包类型不一样,那就说明上一次的数据传输正确;如果一样,那就说明,上一次的数据传输出现了错误,这就是检验。

        之所以出现错误,说明B端的数据包类型没有进行切换,之所以没有切换成功,说明没有正确接收到来自A端的应答信号,那这个应答信号就是在传输过程中出现了损坏或者丢失,所以B端才会保持DATA0数据包类型不变。

        这样一来,上一次的数据传输就相当于白干了,这一次的数据包传输,完全是上一次出现错误的重新操作,这就是纠错。

3、握手包

        握手包是一个应答信号,表示一次传输有没有成功。

        握手包只有同步域,包表示PID和结束标志符EOP,是最简单的一种包。

        握手包有四种:ACK,NAK,STALL,NYET;

        ACK:表示本次能正确接收数据,并且本设备有足够的空间来接收数据,这个握手包,主机和从机都可以使用。

        NAK:表示本设备没有数据返回或者本设备没有足够的空间来接收数据,此握手包主机不能用,只能是从机使用;

        当主机接收到NAK应答后,这并不是错误,只是设备还没有准备好,主机会在下次找机会重新试着传输。

        STALL:表示本设备由于某种原因无法执行接收数据这个请求,或者接收端点被挂起了不能接收数据,这个握手包只能是从机使用;

        这是一种错误的情况,出现这种情况需要主机来进行干预才能解除这种错误。

        NYET:表示本次能正确接收数据,并且有空间来接收本次数据,但是没有足够的空间来接收下一次数据,这个握手包只能是从机使用;

        因此主机在进行下一次数据传输之前,会先发送一个PING令牌包,用来检测设备是否有足够的空间来接收本次的数据,避免浪费表情。

        除了STALL这个错误之外,还有其他情况检测到数据传输错误,比如PID包标识校验出错,CRC检验出错,位填充出错等,这些情况下,设备将什么都不返回,主机就这样一直等着,产生超时等待。

4、特殊包

        特殊包是在一些特殊场合使的包,这并不是一个类型,是由一些令牌包和握手包组成的。

        特殊包一共有四种:PRE,SPLIT,ERR,PING,其中PRE,SPLIT,PING是令牌包,ERR是握手包。

        PRE是USB1.0和USB1.1中的协议,而ERR,SPLIT,PING是USB2.0中新增的。

        PRE:这是一种通知集线器打开低速端口的一种包,它虽然是令牌包,但是却只有同步域,PID包标识和结束符标志,而且只用在全速模式中。在平时的全速设备中,为了防止其低速状态产生误操作,所以一般全速模式中不会把信号传给低速设备,只有当接收到了PRE令牌包,才会将低速端口给打开。

        在全速模式下,假如需要处理低速事务,主机会发送一个PRE包,全速端口接收到次包会直接忽略,但当集线器接收到时,会打开其低速端口,然后主机就以低速模式给低速设备发送一系列令牌包、数据包等。

        PING:PING令牌包跟OUT输出令牌包一样,都是通知设备说主机将要发送数据了,但是PING令牌包后面是不接数据包的,只有当收到了设备发回来的ACK或者NAK应答才会开始发数据包,这就是为什么在将握手包的时候,NYET情况下主机会先发一个PING令牌包,确定设备有足够空间了才发送数据包,这就避免了浪费资源。接入直接只用OUT令牌包的话,后面直接跟一个数据包,一旦设备空间不够,数据包将会被丢弃,这就产生了一个现象,就是在下位机跑程序的时候发现程序漫了一下,虽然是一下,实际上是丢弃了一整个数据包。

        SPILT:这是高速事务分裂令牌包,可以将只有在高速模式下才能处理的数据包转化为低速或者全速数据包发送给相应的端口。

        讲了那么多令牌包,数据包,握手包和特殊包,那到底什么时候我们怎么去操作呢?

        在现有的USB芯片中,大多已经处理好了包与包之间的关系,就连像CRC检验、PID包标识检验、位填充等也都一并处理好了,我们只要知道有这么一个过程和出现了问题去哪里找就行了。

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值