AnsweredAssumed Answered

USB CDC breaks on heavy load

Question asked by Klaus U on May 30, 2017


I'm currently evaluating the STM32F072 Discovery. We are tending moving from ATXMega to ARM and I have to verify if the device is fitting our needs, before investing more time in learning a new architecture.


I successfully tested most of the peripherals, but I have some problems with USB / CDC. I started with the Cube examples that gave a quick start.


My test consists of a PC C++ program opening the comport and transmitting a block of random size (max. 256 Bytes) to the board and it expects the block being echoed. When the content of the response matches with the data sent, it continues in a loop transmitting 100000 frames. Results are quite good and I'm getting approx. 300kByte / sec. (150 to the board and 150 back). Not too bad for a start.


But, there is one restriction. I saw the test failing very fast on frames with 193 and 194 bytes (I guess it has something to do with 64 * 3). The test runs only if I exclude frames of these lengths.


The problem is that the board does sometimes not echo the last 1 or 2 bytes and returns only 192 bytes.


On the controller side I have buffers with 512 Bytes and a loop reading from USB receive buffer and writing it to a transmit buffer.


As soon as at least one byte was received data is echoed immediately.


In a next step I tried to detect a end of frame by waiting HAL_Delay(1) before starting the transmission process. In this case the test works stable, but with reduced throughput. Beside of this I think a delay should not be the solution and I'm missing something.


I found this threadSTM32Cube USB CDC (possible) Bug Found - Rx Tx Race condition and improved the __HAL_LOCK() mechanism like explained, but behavior is the same.


In my real projects a frame is received completely before some action takes place or a response is generated so the question is more theoretically, but shouldn't it be possible to transceive full-duplex? And why does it work with frames of 192 but not with 193 and 194 Bytes?


Have I overseen something?






EDIT: I found out that the board does not see the last two bytes sent by the PC and they are not copied into UserRxBufferFS. It seems that the reception is interrupted (maybe by an ongoing transmit).


Two more questions someone can maybe answer:

1. Is it possible to use multi-packet bulk transfers with CDC? I see CDC_Receive_FS being called with length of maximum 64 bytes . I see the fields ep->maxpacket . Am I right, that at the moment only 64 bytes of ep->xfer_buff are used for FS and a lager buffer does not make sense?


2. In the structure type USBD_CDC_HandleTypeDef is this field defined:

uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE/4];      /* Force 32bits alignment */

This consumes 512 bytes, even in FS mode. The field is exclusively used for the CDC_Control_FS callback. Is it save to reduce the size? Why is the 32 bit alignment important?