最近调了几个USB方面的问题,都是当传输数据长度在64的整数倍时,就出现了错误,因为STM32全速USB端点的最大长度为64Byte,STM32单片机的USB驱动在接收数据时,判断接收到的数据小于ENDSIZE时,才判断这次传输结束。 而当要传输的数据刚好是64的整数倍时,就有问题出现了,最后一包数据数据还是64,这时驱动就不会判断本次传输结束。如果当收到数据时,应该有两种情况来判断传输结束,一个是收到小于EPSIZE的数据,一个是超时。这样就不会出现这种情况。
既然STM32驱动会有这样的错误,其它USB设备当然也会犯这个错误,在我调试ME909的时候,果然当发送TCP的大小为64的整数倍时,TCP就发不出去了,由于TCP发送必须要求有ACK才会再发送下一包TCP数据,而ME909收到的是64的整数倍的数据,其驱动可能与STM32一样,认为本次传输没有完成,于是就等待下1包数据,TCP传输在没有收到对方的ACK包时,会一直等待直到超时重新发送这包TCP数据,但是重新发送的TCP数据仍是64的整数倍,结果ME909还是认为没有收到完整的数据,由于是单片机系统,除了这个TCP应用,系统不会再发送其它数据包。这样就陷入了死循环,直到死机。
在上面的过程中,如果你主动去PING一个公网IP,由于PING数据包刚好不是64的整数倍,这样ME909就被激活了,包括之前的数据一道发了出去,但是后续如果再遇到64整数倍的TCP数据包,就又会出现上面的死循环。
我的解决办法是,不管三七二十一,如果检测到一次传输的大小为64的整数倍时,会在驱动中自动的增加1个字节,正由于这多余的1个字节,就会把ME909激活。测试证明可以使用。 由于modem传输的数据格式是固定的“7E 长度 数据 CRC 7E”,中间多发一个字节也不会有任何影响。
后来才知道,在Linux驱动下,也有这个问题,好像叫做0包检测,看来不光是stm32下的问题!!!哈哈
0包检测无论针对USB主设备,还是USB从设备,都是要考虑的,USB主控制器要发送ENDSIZE整倍数数据时,一定要在最后增加一个0包数据, 如果是USB从设备要想向主控制器发送ENDSIZE整倍数数据时,也要把在最后增加一个0数据包,无论是主设备还是从设备,只要收到小于ENDSIZE的数据包,或者有效数据长度为0的数据包,都会认为此次传输结束。这就是0包检测的本质!!
最近调了几个USB方面的问题,都是当传输数据长度在64的整数倍时,就出现了错误,因为STM32全速USB端点的最大长度为64Byte,STM32单片机的USB驱动在接收数据时,判断接收到的数据小于ENDSIZE时,才判断这次传输结束。 而当要传输的数据刚好是64的整数倍时,就有问题出现了,最后一包数据数据还是64,这时驱动就不会判断本次传输结束。如果当收到数据时,应该有两种情况来判断传输结束,一个是收到小于EPSIZE的数据,一个是超时。这样就不会出现这种情况。
既然STM32驱动会有这样的错误,其它USB设备当然也会犯这个错误,在我调试ME909的时候,果然当发送TCP的大小为64的整数倍时,TCP就发不出去了,由于TCP发送必须要求有ACK才会再发送下一包TCP数据,而ME909收到的是64的整数倍的数据,其驱动可能与STM32一样,认为本次传输没有完成,于是就等待下1包数据,TCP传输在没有收到对方的ACK包时,会一直等待直到超时重新发送这包TCP数据,但是重新发送的TCP数据仍是64的整数倍,结果ME909还是认为没有收到完整的数据,由于是单片机系统,除了这个TCP应用,系统不会再发送其它数据包。这样就陷入了死循环,直到死机。
在上面的过程中,如果你主动去PING一个公网IP,由于PING数据包刚好不是64的整数倍,这样ME909就被激活了,包括之前的数据一道发了出去,但是后续如果再遇到64整数倍的TCP数据包,就又会出现上面的死循环。
我的解决办法是,不管三七二十一,如果检测到一次传输的大小为64的整数倍时,会在驱动中自动的增加1个字节,正由于这多余的1个字节,就会把ME909激活。测试证明可以使用。 由于modem传输的数据格式是固定的“7E 长度 数据 CRC 7E”,中间多发一个字节也不会有任何影响。
后来才知道,在Linux驱动下,也有这个问题,好像叫做0包检测,看来不光是stm32下的问题!!!哈哈
0包检测无论针对USB主设备,还是USB从设备,都是要考虑的,USB主控制器要发送ENDSIZE整倍数数据时,一定要在最后增加一个0包数据, 如果是USB从设备要想向主控制器发送ENDSIZE整倍数数据时,也要把在最后增加一个0数据包,无论是主设备还是从设备,只要收到小于ENDSIZE的数据包,或者有效数据长度为0的数据包,都会认为此次传输结束。这就是0包检测的本质!!
举报