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;
}
}
?
|