英文:
Is USB CDC communication guaranteed?
问题
在使用STM HAL库配置USB 1.1端口,将USB设备配置为CDC(虚拟COM端口)时,通过write()/WriteFile()调用向STM32写入数据,是否保证数据完整到达STM32?(假设一切配置正确,不会写入大于缓冲区大小的数据,并且不会在传输已经进行时尝试写入)。
我找到了这个答案,它建议它们是的,但这与USB 2.0相关:https://stackoverflow.com/questions/38981712/do-usb-control-transfers-guarantee-delivery/38982617
背景:
我继承了前任的一个项目。用于通信协议的代码已经被修改,来自旧的遗留代码,该代码与非USB硬件一起使用以传输信号。
实际发送的数据包的大小可能是传输的缓冲区大小的两倍,因为两个8位值被保留(一个是数据包的起始字节),然后这些值被“转义”为2字节值。此外,每个数据包包含一个16位CRC。在我进行的所有测试中,从未发生传输错误。我不得不“伪造”错误来测试通信代码中的代码路径,因为我正在进行更改。
现在我们处于这样一种情况:我们希望为客户提供一个将数据吞吐量推到极限的功能。该功能有效,再次没有检测到由预期的数据包起始字节或CRC排列引起的传输错误。问题是,如果数据包包含保留值之一,那么传输速度实际上会下降,因为数据必须被展开。
除了扩展数据包之外,还必须检查传入的数据包、解除转义并计算CRC的开销。
因此,如果USB CDC协议保证数据将完整到达(我已经遇到并处理了64字节的块),那么我可以摒弃起始字节、转义数据和CRC,并获得在接收端的更快处理速度的有保证的固定传输速度(该处理发生在中断中)。
英文:
TLDR version:
Working with a Windows or Linux PC communicating with an STM32 micro via a USB port (USB 1.1) configured for Full Speed and the USB device configured as a CDC (Virtual COM Port) - all using the STM HAL libraries - when data is written to the device via write()/WriteFile() calls, is that data guaranteed to arrive intact on the STM32? (Assume everything is configured correctly, I'm not writing packets bigger than the buffer sizes and I'm not trying to write whilst a transfer is already in progress).
I've found this answer, which suggests that they are, but this relates to USB 2.0: https://stackoverflow.com/questions/38981712/do-usb-control-transfers-guarantee-delivery/38982617
Background:
I've inherited a project from my predecessor. The code that has been used for the communication protocol has been modified from other internal sources from fairly old legacy code that worked with non-USB hardware to carry the signals.
The data packets that are actually sent can potentially be twice as big as the buffer being transmitted, as two 8-bit values are reserved (one is a packet start byte) and these then get 'escaped' into 2byte values. In addition, each packet contains a 16-bit CRC. In all the testing I've performed, no errors in transmission have ever occurred. I've had to 'fake' errors to test the code path through the comms code as I'm making changes.
We're now in a situation where we'd like to offer a feature to our customers that would push the data throughput to its limit. The feature works, again no transmission errors are picked up by the anticipated packet start byte or CRC arrangement. The problem is, if the packets contain either of the reserved values, than the transmission speed effectively drops as the data has to be expanded.
In addition to the expanding packets, there is also the overhead of having to check the incoming packets, un-escape them and also calculate the CRC.
So, if the USB CDC protocol guarantees that the data will arrive intact (I've already encountered and handled the 64byte chunks), then I can do away with the start byte, escaped data and the CRC and get a guaranteed fixed transmission speed with faster processing speed on the receiving end (which occurs in an interrupt), too.
答案1
得分: 2
是的。CDC ACM虚拟COM端口使用批量端点传输它们的数据。您可以通过查看设备的USB端点描述符来验证这一点。批量端点的行为由USB规范定义。与大多数端点类型一样,批量端点使用CRC来确保数据被正确传输,并且USB内建了一个重试机制,以便在出现错误时重试发送数据。当然,这不能阻止糟糕编写的固件或软件意外丢弃数据。
另外,如果您正在设计一个串行协议,有一种让发送方将接收方置于已知状态的好方法,以防之前有其他软件与设备通信并发送了无效数据。通常,您可以发送一个特殊字节(或字节序列)来表示数据包的开始。另一种方法是使用CDC ACM提供的带外控制信号,例如“设置控制线状态”或“发送中断”命令。
英文:
Yes. CDC ACM virtual COM ports use bulk endpoints to transport their data. You can verify this by looking at your device's USB endpoint descriptors. The behavior of bulk endpoints is defined by the USB specification. Like most endpoint types, bulk endpoints use CRCs to ensure the data was transmitted correctly, and there is a retry mechanism built into USB to retry sending the data if there was an error. Of course, this doesn't prevent badly-written firmware or software from throwing away the data by accident.
Separately: if you are designing a serial protocol, it's a really good idea to have a way for the sender to get the receiver into a known state, just in case there was some other software talking to the device previously and it sent invalid data. Usually there is a special byte (or byte sequence) you can send that will signal the start of a packet. Another idea is to use the out-of-band control signals that CDC ACM offers, like the "Set Control Line State" or the "Send Break" commands.
答案2
得分: 2
除了David Grayson的回答之外,还应指出,从主机的串行API通过USB批量端点到STM32 HAL库的整个通信链具有流控机制。它们确保发送方被阻塞,直到下一个阶段可以接受数据。
即使您向WriteFile()
提交的数据多于链路上的缓冲区大小,也不会丢失数据。它将以较小的包传输,并以接收方可以接受的速度传输。
流控机制是WriteFile()
,USB批量端点和STM32 HAL库固有的(与RTS/CTS等串行流控无关)。
如果STM32代码正确检查CDC_Transmit_FS()
的返回代码,同样适用于另一个方向。
英文:
In addition to David Grayson's answer, it should be pointed out that the entire communication chain from host's serial API via the USB bulk endpoint to the STM32 HAL library has flow control mechanisms. They guarantee that the sender is blocked until the next stage can accept the data.
Even if you submit more data to WriteFile()
than the buffer sizes along the chain can hold, no data will be lost. It will be transmitted in smaller packages and at a speed that the receiver can accept it.
The flow control mechanisms are inherent to WriteFile()
, to USB bulk endpoints and to the STM32 HAL library (and not related to serial flow control like RTS/CTS).
The same also applies in the other direction if the STM32 codes properly checks if the return code of CDC_Transmit_FS()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论