USB四种传输相关

温故而知新, 记录点usb四种传输相关的内容。

根据usb协议ch8, ch9等章节, 传输分四种,控制,  批量,中断, 等时。

* 一个传输由多个事务组成。如建立(setup)事务, 读数据(IN)事务, 写数据(OUT)事务等等。

* 一个事务一般有三个阶段(三种包),  即令牌->数据->握手, 这三个阶段有些是可选的。

 

令牌包打头: 说明我(主机)要干什么, 有四种命令, SETUP, IN, OUT, SOF。

IN/OUT 标志读/写数据。

SETUP 设置/建立,  只用于控制传输,  

SOF 全称 Start Of Frame即标识帧的开始。这个包只用于全速以上的设备。 作用有以下几种:

1).  标志帧的开始。

2).  内部带有一个Frame ID,  usb设备可基于帧号做一些事情。

3).  对于全速设备,  主机端会每隔1ms发送一个SOF,  高速设备, 125us发送一个SOF, 防止usb设备进入suspend状态。

      1ms间隔的我们叫帧,  125us间隔的我们叫微帧, 即1ms内有8个微帧, 其中这些微帧的Frame ID不变,  即仅1ms帧号才家一次。

 


ok, 举点例子更清楚。

比如最常见的Get_Descriptor这个命令,  即枚举过程中通过端点0获取设备描述符这个动作。

1). 这个动作算一次传输

2). 这个传输是控制传输

3). 控制传输按事务分 通常 有三个阶段。建立事务 -> 数据事务 -> 状态事务

4).  建立事务,

      * 先发setup令牌,  包结构简单 [Sync][PID][ADDR][ENDP][CRC5][EOP], 内部含有usb设备地址(0~127), 控制端点0

      * 再发个具体Get_Descriptor这个命令,  跟在SETUP令牌后面, 主机端继续发数据包

         [Sync][PID][DATA0][CRC16][EOP]  其中DATA0就是usb设备请求, 根据ch9, 该数据为8位数据, 

         查看usb/ch9.h,

struct usb_ctrlrequest {                                                                                                                               
›   __u8 bRequestType;                                                                                                                                 
›   __u8 bRequest;                                                                                                                                     
›   __le16 wValue;                                                                                                                                     
›   __le16 wIndex;                                                                                                                                     
›   __le16 wLength;                                                                                                                                    
} __attribute__ ((packed));

         bRequestType即协议中的bmRequestType, 是bitmap格式。

         D7: 数据传输方向, 0: Host->Device, 1: Device->Host

        D6...5: 类型, 0 - Standard, 1 - Class, 2 - Vendor, 3 - Reserved

        D4...0: Recipient(收件人) 0 - Device, 1 - Interface, 2 - Endpoint, 3 - Other, 4 ... 31 - Reserved

 

        bRequest即具体的命令,

 

       GET_DESCRIPTOR即一个标准的设备请求。

       bmRquestType = 10000000B,  

       bRquest = 0x6,

        

       ok,  该请求就发送给设备端了, 这个事务就等握手阶段了。等带设备端返回ACK包,  则说明设备端接收到了,  可以发具体的读数据请求事务。

       握手包总共也是四种, ACK, NAK, STALL, NYET。

       字面意思

       ACK - 确认(收到)。

       NAK - 未确认。 只能设备发给主机, 一般是设备忙或者没有数据要返回就发NAK。

       STALL - 瘫痪。不支持的控制请求, 控制请求失败或终端失败等。

       NYET - Not Yet,  还不行... 高速以上设备才有。协议说和PING命令有关, 具体碰到再理解...

 

       是的, 控制传输的建立事务阶段终于结束了,  下一步,  具体的数据包...

5). 数据事务

       前面建立的是Get_Descriptor事务, 那紧跟着的就是一次读数据事务。

       发令牌 IN - > 设备发DATA0 - > ACK, 数据不够就继续读

       发令牌 IN - > 设备发DTAA1 - > ACK...

       ......

6).  状态事务

      设备描述符收到后, 主机端需要发起一个状态事务。嗯 这次是写数据, 需要跟设备说, 我收到啦!!

     发令牌 OUT -> 主机端发长度为0的数据包 -> 设备回复ACK

 

ok, 以上就是一次完整的GET_DESCRIPTOR 控制传输。


bulk传输, 非常常用的一种传输方式。

枚举,  配置等动作完成后, 如果该usb设备有提供bulk端点, 我们就可以利用该bulk端点进行批量传输。

bulk in 端点可以读数据, bulk out端点可以写数据。

相对于控制传输, bulk/isoc/interrupt传输都没有建立阶段。 都是直接批量事务走起。

一个批量事务 也是三个阶段

1). 发令牌包,  IN/OUT 即读还是写

2). 读 - 那就设备端给数据, 或者不给那就报错。 写 - 那就host发数据包。

      数据包格式 [SYNC][PID][DATA][CRC16] 其中 DATA数据域的长度根据协议是这样描述的。

      低速设备,  最多8byte...好少, 所以1.1只能用于一些HID设备了...

      全速设备,  1023byte,

      高速设备,  1024byte,

      超速设备,  貌似格式有点变化...需要仔细看下3.0协议...

     

      ok, 这是协议里定义的最大size。设备/端点描述符里其实有最大size的定义。所以具体采用的最大size, lsusb -v看一看吧。

      

      比如我的usb读卡器,

      

river@river-VirtualBox:~/mount/rootfs$ lsusb -s 1:4 -v

Bus 001 Device 004: ID 14cd:1212 Super Top microSD card reader (SY-T18)
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x14cd Super Top
  idProduct          0x1212 microSD card reader (SY-T18)
  bcdDevice            1.00
  iManufacturer           1 
  iProduct                3 
  iSerial                 2 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           32
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         8 Mass Storage
      bInterfaceSubClass      6 SCSI
      bInterfaceProtocol     80 Bulk-Only
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0

看到了吧wMaxPacketSize...  512byte。

嗯, 所以这玩意bulk传输时, 一个IN/OUT 数据包, 最多就是512byte。

ftrace查看下usb的log

	Line 14:            <...>-1454  [002] d... 21815.916651: xhci_inc_enq: BULK 00000000e4ad58e6: enq 0x000000003784ca00(0x000000003784c000) deq 0x000000003784c9f0(0x000000003784c000) segs 2 stream 0 free_trbs 508 bounce 512 cycle 1
	Line 17:            <...>-1454  [002] d... 21815.917057: xhci_inc_enq: BULK 00000000c99f84e6: enq 0x000000003784ad80(0x000000003784a000) deq 0x000000003784ad70(0x000000003784a000) segs 2 stream 0 free_trbs 508 bounce 512 cycle 0
	Line 20:            <...>-1454  [002] d... 21817.931934: xhci_inc_enq: BULK 00000000e4ad58e6: enq 0x000000003784ca10(0x000000003784c000) deq 0x000000003784ca00(0x000000003784c000) segs 2 stream 0 free_trbs 508 bounce 512 cycle 1
	Line 23:            <...>-1454  [002] d... 21817.932936: xhci_inc_enq: BULK 00000000c99f84e6: enq 0x000000003784ad90(0x000000003784a000) deq 0x000000003784ad80(0x000000003784a000) segs 2 stream 0 free_trbs 508 bounce 512 cycle 0
	Line 26:            <...>-1454  [002] d... 21819.948060: xhci_inc_enq: BULK 00000000e4ad58e6: enq 0x000000003784ca20(0x000000003784c000) deq 0x000000003784ca10(0x000000003784c000) segs 2 stream 0 free_trbs 508 bounce 512 cycle 1
	Line 29:            <...>-1454  [002] d... 21819.948468: xhci_inc_enq: BULK 00000000c99f84e6: enq 0x000000003784ada0(0x000000003784a000) deq 0x000000003784ad90(0x000000003784a000) segs 2 stream 0 free_trbs 508 bounce 512 cycle 0
	Line 32:            <...>-1454  [002] d... 21821.964510: xhci_inc_enq: BULK 00000000e4ad58e6: enq 0x000000003784ca30(0x000000003784c000) deq 0x000000003784ca20(0x000000003784c000) segs 2 stream 0 free_trbs 508 bounce 512 cycle 1
	Line 35:            <...>-1454  [002] d... 21821.964936: xhci_inc_enq: BULK 00000000c99f84e6: enq 0x000000003784adb0(0x000000003784a000) deq 0x000000003784ada0(0x000000003784a000) segs 2 stream 0 free_trbs 508 bounce 512 cycle 0
	Line 38:            <...>-1454  [002] d... 21823.980658: xhci_inc_enq: BULK 00000000e4ad58e6: enq 0x000000003784ca40(0x000000003784c000) deq 0x000000003784ca30(0x000000003784c000) segs 2 stream 0 free_trbs 508 bounce 512 cycle 1
	Line 41:            <...>-1454  [002] d... 21823.980864: xhci_inc_enq: BULK 00000000c99f84e6: enq 0x000000003784adc0(0x000000003784a000) deq 0x000000003784adb0(0x000000003784a000) segs 2 stream 0 free_trbs 508 bounce 512 cycle 0

3).  最后, 同样是握手包阶段。ACK, 那就确认了。


isochronous传输

继续看下isco,  即等时传输。字面意思即是定时定量的传...保证时延...用于usb音视频等设备。 比如uvc webcam一类的。

根据协议来, 等时传输, 就两个阶段, 令牌包->数据包。是的,  没有握手阶段, 即没有对端的确认包。 也就是说不管对端是收到与否, 我都按我的规则来读写。。。这样来保证等时。。。 

嗯, 也就是说bulk传输如果是NAK等握手包,  那么需要重传机制。 等时传输,  那就丢了就丢了, 尽量保证看到的听到的是最近的画面和声音  和 直播, 视频聊天, 电话等场景类似。 时延优先...

看下usb_in_a_nutshell.pdf这篇文档, 描述的很好, 记录下...

Isochronous Transfers provide
• Guaranteed access to USB bandwidth.
• Bounded latency.
• Stream Pipe - Unidirectional
• Error detection via CRC, but no retry or guarantee of delivery.
• Full & high speed modes only.
• No data toggling.

 

关于数据包的 Size, 和bulk一样 ,  也根据usb设备描述符来。比如我的uvc摄像头, 高分辨率,高帧率的,  对应wMaxPacketSize肯定就大点,  低分辨率低帧率高压缩比的wMaxPacketSize就小点。


说到uvc,  我这边遇到个问题,  我的罗技摄像头采用等时传输, 按照描述符中给的maxpackesize请求读数据,  可每次uvc摄像头给的数据都比我请求的小...  关于这种情况, 写数据发生呢肯定是异常的, 读数据嘛, 设备端给多少是设备说了算的, 所以也算不得异常。 但xhci控制器 还是会报个 Short Packet上来,  就是短包。 本来嘛, 报就报了呗, 就按正常的情况处理下, 继续就是了。PC上也是这样处理的。 但是却苦了我的FPGA验证环境了......

 

我的FPGA验证环境,  就塞了一个cpu核进去, 主频也就20Mhz.... 按usb2.0 高速设备的协议....

125us就是一个微帧了... 也就是差不多125us就是一个isoc传输.....

每次isoc传输, 都报Short Packet错误....

1s内得有8000次短包消息.... 我的20Mhz cpu就处理不过来了....

最后xhci模块的Event Ring Buffer就爆炸了... 

具体log如下:

        v4l2_cam-937   [000] dnh1  1769.737663: xhci_handle_event: EVENT: TRB 0000000039050dd0 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.737771: xhci_handle_event: EVENT: TRB 0000000039050de0 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.737878: xhci_handle_event: EVENT: TRB 0000000039050df0 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.737986: xhci_handle_event: EVENT: TRB 0000000039050e00 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.738094: xhci_handle_event: EVENT: TRB 0000000039050e10 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.738201: xhci_handle_event: EVENT: TRB 0000000039050e20 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.738308: xhci_handle_event: EVENT: TRB 0000000039050e30 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.740535: xhci_handle_event: EVENT: TRB 0000000039050e40 status 'Ring Overrun' len 0 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.740605: xhci_handle_event: EVENT: TRB 0000000039050e40 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.740715: xhci_handle_event: EVENT: TRB 0000000039050e50 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.740824: xhci_handle_event: EVENT: TRB 0000000039050e60 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.740933: xhci_handle_event: EVENT: TRB 0000000039050e70 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.741041: xhci_handle_event: EVENT: TRB 0000000039050e80 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.741149: xhci_handle_event: EVENT: TRB 0000000039050e90 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.741257: xhci_handle_event: EVENT: TRB 0000000039050ea0 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.741365: xhci_handle_event: EVENT: TRB 0000000039050eb0 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.741473: xhci_handle_event: EVENT: TRB 0000000039050ec0 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.741580: xhci_handle_event: EVENT: TRB 0000000039050ed0 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.741688: xhci_handle_event: EVENT: TRB 0000000039050ee0 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.741795: xhci_handle_event: EVENT: TRB 0000000039050ef0 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.741902: xhci_handle_event: EVENT: TRB 0000000039050f00 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.742010: xhci_handle_event: EVENT: TRB 0000000039050f10 status 'Short Packet' len 180 slot 1 ep 3 type 'Transfer Event' flags e:c
        v4l2_cam-937   [000] dnh1  1769.742118: xhci_handle_event: EVENT: TRB 0000000000000000 status 'Event Ring Full Error' len 0 slot 0 ep 0 type 'Host Controller Event' flags e:c

ok... 未完待续...

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值