usb rndis主机接收数据错误的分析

1、背景

     本程序是一个stm32 usb host驱动4G rndis模块的程序,具体可以参考首创STM32 USB主机驱动4G rndis设备_fhqlongteng的博客-CSDN博客。这个程序在最近移植到真实的产品硬件上面做应用功能测试。测试发现产品在执行特定的操作时,出现4G 模块usb设备主动断开usb连接的情况。

2、问题原因浅析

       如下图的软件是用于测试4G模块实现的真实产品的功能的测试软件,点击“读取设备时间”,会通过4G网络读取到设备的RTC时间,点击“开关”按钮会打设备的电磁阀接口。测试发现点击开关时不会出现4G模块主动断开usb连接的情况,点击读取设备时间时会出4G模块主动断开usb连接的问题。这两个操作都是调用服务器的同一个API,只是向设备发送的数据内容不一样而已。竟然会出现一个不好使的情况???

     

     这个应用程序基于AT 指令串口通信时没有问题,也就是说应用层的程序没有问题,问题就出现在USB 驱动的4G rndis设备这里了。

     增加调试打印代码,获取到如下的USB rndis通信的数据,可以看到再进行读取设备时间的操作时,rndis eth接收到的第一个数据包长度为192字节的指令数据包(sys/383825/86807004059431
/cmd/request/270960dd-205e-47db -bcec-a0d74857ba46{"dev":"time"}),后面又收到一个22字节升序的错误数据包。

msh />rndis eth rx1 time=1479.514s,len = 192
[HEX] rndis eth rx1: 0000-0020: 01 00 00 00 C0 00 00 00  24 00 00 00 94 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ........$.......................
[HEX] rndis eth rx1: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 AC 0C 29 A3  9B 6D 00 AE AF AF AF AF  08 00 45 04 00 86 3A CA    ..............)..m........E...:.
[HEX] rndis eth rx1: 0040-0060: 40 00 33 06 6B 50 B7 E6  28 60 C0 A8 00 65 07 5B  C0 01 5E 25 1D 99 00 00  74 0A 50 18 FF 70 E1 CE    @.3.kP..(`...e.[..^%....t.P..p..
[HEX] rndis eth rx1: 0060-0080: 00 00 30 5C 00 4C 24 73  79 73 2F 33 38 33 38 32  35 2F 38 36 38 30 37 30  30 34 30 35 39 34 33 31    ..0\.L$sys/383825/86807004059431
[HEX] rndis eth rx1: 0080-00A0: 33 2F 63 6D 64 2F 72 65  71 75 65 73 74 2F 32 37  30 39 36 30 64 64 2D 32  30 35 65 2D 34 37 64 62    3/cmd/request/270960dd-205e-47db
[HEX] rndis eth rx1: 00A0-00C0: 2D 62 63 65 63 2D 61 30  64 37 34 38 35 37 62 61  34 36 7B 22 64 65 76 22  3A 22 74 69 6D 65 22 7D    -bcec-a0d74857ba46{"dev":"time"}
这条数据不符合rndis协议,是干什么的呢????应该是和某条数据一起的,或是未接收完整
rndis eth rx1 time=1479.606s,len = 22
[HEX] rndis eth rx1: 0000-0020: 00 01 00 AE AF AF AF AF  C0 A8 00 01 00 00 00 00  00 00 C0 A8 00 65                                   .....................e
rndis eth tx time=1479.623s,len = 232
[HEX] rndis eth tx: 0000-0020: 01 00 00 00 E8 00 00 00  24 00 00 00 BC 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ........$.......................
[HEX] rndis eth tx: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 00 AE AF AF  AF AF AC 0C 29 A3 9B 6D  08 00 45 00 00 AE 01 93    ....................)..m..E.....
[HEX] rndis eth tx: 0040-0060: 00 00 FF 06 18 63 C0 A8  00 65 B7 E6 28 60 C0 01  07 5B 00 00 74 0A 5E 25  1D F7 50 18 1D A4 12 2C    .....c...e..(`...[..t.^%..P....,
[HEX] rndis eth tx: 0060-0080: 00 00 30 83 01 00 4D 24  73 79 73 2F 33 38 33 38  32 35 2F 38 36 38 30 37  30 30 34 30 35 39 34 33    ..0...M$sys/383825/8680700405943
[HEX] rndis eth tx: 0080-00A0: 31 33 2F 63 6D 64 2F 72  65 73 70 6F 6E 73 65 2F  32 37 30 39 36 30 64 64  2D 32 30 35 65 2D 34 37    13/cmd/response/270960dd-205e-47
[HEX] rndis eth tx: 00A0-00C0: 64 62 2D 62 63 65 63 2D  61 30 64 37 34 38 35 37  62 61 34 36 7B 0A 09 22  61 63 6B 22 3A 09 22 4F    db-bcec-a0d74857ba46{.."ack":."O
[HEX] rndis eth tx: 00C0-00E0: 4B 22 2C 0A 09 22 64 65  76 5F 74 69 6D 65 22 3A  09 22 32 30 32 31 2D 30  39 2D 30 33 20 31 33 3A    K",.."dev_time":."2021-09-03 13:
[HEX] rndis eth tx: 00E0-0100: 30 31 3A 34 34 22 0A 7D                                                                               01:44".}
rndis eth rx1 time=1479.838s,len = 188
[HEX] rndis eth rx1: 0000-0020: 01 00 00 00 BC 00 00 00  24 00 00 00 90 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ........$.......................
[HEX] rndis eth rx1: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 AC 0C 29 A3  9B 6D 00 AE AF AF AF AF  08 00 45 04 00 82 A8 94    ..............)..m........E.....
[HEX] rndis eth rx1: 0040-0060: 40 00 33 06 FD 89 B7 E6  28 60 C0 A8 00 65 07 5B  C0 01 5E 25 1D F7 00 00  74 90 50 18 FF 70 1A 8A    @.3.....(`...e.[..^%....t.P..p..
[HEX] rndis eth rx1: 0060-0080: 00 00 30 58 00 56 24 73  79 73 2F 33 38 33 38 32  35 2F 38 36 38 30 37 30  30 34 30 35 39 34 33 31    ..0X.V$sys/383825/86807004059431
[HEX] rndis eth rx1: 0080-00A0: 33 2F 63 6D 64 2F 72 65  73 70 6F 6E 73 65 2F 32  37 30 39 36 30 64 64 2D  32 30 35 65 2D 34 37 64    3/cmd/response/270960dd-205e-47d
[HEX] rndis eth rx1: 00A0-00C0: 62 2D 62 63 65 63 2D 61  30 64 37 34 38 35 37 62  61 34 36 2F 61 63 63 65  70 74 65 64                b-bcec-a0d74857ba46/accepted
rndis eth tx time=1479.995s,len = 98
[HEX] rndis eth tx: 0000-0020: 01 00 00 00 62 00 00 00  24 00 00 00 36 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ....b...$...6...................
[HEX] rndis eth tx: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 00 AE AF AF  AF AF AC 0C 29 A3 9B 6D  08 00 45 00 00 28 01 94    ....................)..m..E..(..
[HEX] rndis eth tx: 0040-0060: 00 00 FF 06 18 E8 C0 A8  00 65 B7 E6 28 60 C0 01  07 5B 00 00 74 90 5E 25  1E 51 50 10 1D 4A 38 D3    .........e..(`...[..t.^%.QP..J8.
[HEX] rndis eth tx: 0060-0080: 00 00

      执行打开开关的操作时,usb rndis收到的数据包指令为rndis eth接收到的第一个数据包长度为191字节的指令数据包(sys/383825/868070040594313/cmd/request/2fed1446-8048-4504-a10f-c42e798e6a36{"switch3":0})。

rndis eth rx1 time=579.172s,len = 191
[HEX] rndis eth rx1: 0000-0020: 01 00 00 00 BF 00 00 00  24 00 00 00 93 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ........$.......................
[HEX] rndis eth rx1: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 AC 0C 29 A3  9B 6D 00 8A 72 72 72 72  08 00 45 04 00 85 14 E1    ..............)..m..rrrr..E.....
[HEX] rndis eth rx1: 0040-0060: 40 00 35 06 8F 3A B7 E6  28 60 C0 A8 00 65 07 5B  C0 02 86 D9 8D B0 00 00  28 56 50 18 9A F0 CE 58    @.5..:..(`...e.[........(VP....X
[HEX] rndis eth rx1: 0060-0080: 00 00 30 5B 00 4C 24 73  79 73 2F 33 38 33 38 32  35 2F 38 36 38 30 37 30  30 34 30 35 39 34 33 31    ..0[.L$sys/383825/86807004059431
[HEX] rndis eth rx1: 0080-00A0: 33 2F 63 6D 64 2F 72 65  71 75 65 73 74 2F 32 66  65 64 31 34 34 36 2D 38  30 34 38 2D 34 35 30 34    3/cmd/request/2fed1446-8048-4504
[HEX] rndis eth rx1: 00A0-00C0: 2D 61 31 30 66 2D 63 34  32 65 37 39 38 65 36 61  33 36 7B 22 73 77 69 74  63 68 33 22 3A 30 7D       -a10f-c42e798e6a36{"switch3":0}
rndis eth tx time=579.269s,len = 86
[HEX] rndis eth tx: 0000-0020: 01 00 00 00 56 00 00 00  24 00 00 00 2A 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ....V...$...*...................
[HEX] rndis eth tx: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 FF FF FF FF  FF FF AC 0C 29 A3 9B 6D  08 06 00 01 08 00 06 04    ....................)..m........
[HEX] rndis eth tx: 0040-0060: 00 01 AC 0C 29 A3 9B 6D  C0 A8 00 65 00 00 00 00  00 00 C0 A8 00 01                                   ....)..m...e..........
IN 3 URB_DONE recv:86
rndis eth rx1 time=579.317s,len = 86
[HEX] rndis eth rx1: 0000-0020: 01 00 00 00 56 00 00 00  24 00 00 00 2A 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ....V...$...*...................
[HEX] rndis eth rx1: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 AC 0C 29 A3  9B 6D 00 8A 72 72 72 72  08 06 00 01 08 00 06 04    ..............)..m..rrrr........
[HEX] rndis eth rx1: 0040-0060: 00 02 00 8A 72 72 72 72  C0 A8 00 01 AC 0C 29 A3  9B 6D C0 A8 00 65                                   ....rrrr......)..m...e
rndis eth tx time=579.363s,len = 195
[HEX] rndis eth tx: 0000-0020: 01 00 00 00 C3 00 00 00  24 00 00 00 97 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ........$.......................
[HEX] rndis eth tx: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 00 8A 72 72  72 72 AC 0C 29 A3 9B 6D  08 00 45 00 00 89 00 4B    ..............rrrr..)..m..E....K
[HEX] rndis eth tx: 0040-0060: 00 00 FF 06 19 D0 C0 A8  00 65 B7 E6 28 6IN 3 URB_DONE recv:191
rndis eth rx1 time=579.403s,len = 191
[HEX] rndis eth rx1: 0000-0020: 01 00 00 00 BF 00 00 00  24 00 00 00 93 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ........$.......................
[HEX] rndis eth rx1: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 AC 0C 29 A3  9B 6D 00 8A 72 72 72 72  08 00 45 04 00 85 E5 36    ..............)..m..rrrr..E....6
[HEX] rndis eth rx1: 0040-0060: 40 00 35 06 BE E4 B7 E6  28 60 C0 A8 00 65 07 5B  C0 02 86 D9 8D B0 00 00  28 56 50 18 9A F0 CE 58    @.5.....(`...e.[........(VP....X
[HEX] rndis eth rx1: 0060-0080: 00 00 30 5B 00 4C 24 73  79 73 2F 33 38 33 38 32  35 2F 38 36 38 30 37 30  30 34 30 35 39 34 33 31    ..0[.L$sys/383825/86807004059431
[HEX] rndis eth rx1: 0080-00A0: 33 2F 63 6D 64 2F 72 65  71 75 65 73 74 2F 32 66  65 64 31 34 34 36 2D 38  30 34 38 2D 34 35 30 34    3/cmd/request/2fed1446-8048-4504
[HEX] rndis eth rx1: 00A0-00C0: 2D 61 31 30 66 2D 63 34  32 65 37 39 38 65 36 61  33 36 7B 22 73 77 69 74  63 68 33 22 3A 30 7D       -a10f-c42e798e6a36{"switch3":0}
0 C0 02  07 5B 00 00 28 56 86 D9  8E 0D 50 18 1E 36 70 E3    .........e..(`...[..(V....P..6p.
[HEX] rndis eth tx: 0060-0080: 00 00 30 5F 00 4D 24 73  79 73 2F 33 38 33 38 32  35 2F 38 36 38 30 37 30  30 34 30 35 39 34 33 31    ..0_.M$sys/383825/86807004059431
[HEX] rndis eth tx: 0080-00A0: 33 2F 63 6D 64 2F 72 65  73 70 6F 6E 73 65 2F 32  66 65 64 31 34 34 36 2D  38 30 34 38 2D 34 35 30    3/cmd/response/2fed1446-8048-450
[HEX] rndis eth tx: 00A0-00C0: 34 2D 61 31 30 66 2D 63  34 32 65 37 39 38 65 36  61 33 36 7B 0A 09 22 61  63 6B 22 3A 09 22 4F 4B    4-a10f-c42e798e6a36{.."ack":."OK
[HEX] rndis eth tx: 00C0-00E0: 22 0A 7D                                                                                              ".}
rndis eth tx time=579.563s,len = 98
[HEX] rndis eth tx: 0000-0020: 01 00 00 00 62 00 00 00  24 00 00 00 36 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ....b...$...6...................
[HEX] rndis eth tx: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 00 8A 72 72  72 72 AC 0C 29 A3 9B 6D  08 00 45 00 00 28 00 4C    ..............rrrr..)..m..E..(.L
[HEX] rndis eth tx: 0040-0060: 00 00 FF 06 1A 30 C0 A8  00 65 B7 E6 28 60 C0 02  07 5B 00 00 28 B7 86 D9  8E 0D 50 10 1E 36 EB 4E    .....0...e..(`...[..(.....P..6.N
[HEX] rndis eth tx: 0060-0080: 00 00                                                                                                 ..
IN 3 URB_DONE recv:188
rndis eth rx1 time=579.640s,len = 188
[HEX] rndis eth rx1: 0000-0020: 01 00 00 00 BC 00 00 00  24 00 00 00 90 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ........$.......................
[HEX] rndis eth rx1: 0020-0040: 00 00 00 00 00 00 00 00  00 00 00 00 AC 0C 29 A3  9B 6D 00 8A 72 72 72 72  08 00 45 04 00 82 2F AB    ..............)..m..rrrr..E.../.
[HEX] rndis eth rx1: 0040-0060: 40 00 35 06 74 73 B7 E6  28 60 C0 A8 00 65 07 5B  C0 02 86 D9 8E 0D 00 00  28 B7 50 18 9A F0 02 FF    @.5.ts..(`...e.[........(.P.....
[HEX] rndis eth rx1: 0060-0080: 00 00 30 58 00 56 24 73  79 73 2F 33 38 33 38 32  35 2F 38 36 38 30 37 30  30 34 30 35 39 34 33 31    ..0X.V$sys/383825/86807004059431
[HEX] rndis eth rx1: 0080-00A0: 33 2F 63 6D 64 2F 72 65  73 70 6F 6E 73 65 2F 32  66 65 64 31 34 34 36 2D  38 30 34 38 2D 34 35 30    3/cmd/response/2fed1446-8048-450
[HEX] rndis eth rx1: 00A0-00C0: 34 2D 61 31 30 66 2D 63  34 32 65 37 39 38 65 36  61 33 36 2F 61 63 63 65  70 74 65 64                4-a10f-c42e798e6a36/accepted

     为什么会有这样子的不同呢?想了一上午没有找出问题,下午下班前打了一场羽毛球也没有找到答案。下班了,在进地铁的电梯上,我就想为什么192字节的长度数据有问题,191字节的长度没有问题呢?豁然间想到,USB数据包最大长度为64字节,192=64*3,也就是说在接收最大包长整数倍的时候出现的问题。那就是USB驱动程序的问题,即是stm32f4xx_hal_hcd.c的问题了。

 3、解决问题

      发现的问题的原因,解决起来就容易的多了,首先查阅一下资料,了解了usb分包的原理,在usb传输时,如果传输的包长为usb最大数据包的整数倍,最后要发送一个0包长的数据包表示传输完成。查找到代码HCD_RXQLVL_IRQHandler函数是对接收数据的分包接收,在pktcnt等于0时,表示接收到了0长度数据包,此时需要翻转数据包的状态。增加一行代码hhcd->hc[ch_num].toggle_in ^= 1U;  解决问题。

static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
{
  USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
  uint32_t USBx_BASE = (uint32_t)USBx;
  uint32_t pktsts;
  uint32_t pktcnt;
  uint32_t temp;
  uint32_t tmpreg;
  uint32_t ch_num;

  temp = hhcd->Instance->GRXSTSP;
  ch_num = temp & USB_OTG_GRXSTSP_EPNUM;
  pktsts = (temp & USB_OTG_GRXSTSP_PKTSTS) >> 17;
  pktcnt = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;

  switch (pktsts)
  {
    case GRXSTS_PKTSTS_IN:
      /* Read the data into the host buffer. */
      if ((pktcnt > 0U) && (hhcd->hc[ch_num].xfer_buff != (void *)0))
      {
        (void)USB_ReadPacket(hhcd->Instance, hhcd->hc[ch_num].xfer_buff, (uint16_t)pktcnt);

        /*manage multiple Xfer */
        hhcd->hc[ch_num].xfer_buff += pktcnt;
        hhcd->hc[ch_num].xfer_count  += pktcnt;

        if ((USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0U)
        {
          /* re-activate the channel when more packets are expected */
          tmpreg = USBx_HC(ch_num)->HCCHAR;
          tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
          tmpreg |= USB_OTG_HCCHAR_CHENA;
          USBx_HC(ch_num)->HCCHAR = tmpreg;
          hhcd->hc[ch_num].toggle_in ^= 1U;
        }
        //rt_kprintf("IN %d RXQLVL:%d, PID:%d\n", ch_num, pktcnt, (USB_OTG_GRXSTSP_DPID & temp) >> 15);
      }
      else
      {
         /*如果主机接收的包长为最大包长的整数倍,设备最后会发送一个0包长的数据数据表示数据发送完成,这里要对数据包状态进行变化,并且不再使能接收通道*/
         hhcd->hc[ch_num].toggle_in ^= 1U;
         //rt_kprintf("ZIN %d RXQLVL:%d, PID:%d\n", ch_num, pktcnt, (USB_OTG_GRXSTSP_DPID & temp) >> 15);     
      }
      break;

    case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
      break;

    case GRXSTS_PKTSTS_IN_XFER_COMP:
    case GRXSTS_PKTSTS_CH_HALTED:
    default:
      break;
  }
}

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值