Skip to main content
Visitor II
December 24, 2023
Question

USBX CDC ACM data read bug?

  • December 24, 2023
  • 14 replies
  • 6252 views

This behavior seems like a bug.

I’m using USBX CDC ACM on a H723 nucleo board. I’m trying to work with the blocking nature of the ux_device_class_cdc_acm_read. For my application, I would like to get data as soon as up to 256 characters are received but the length will be variable. I’ve tried a few things and found this behavior that seems wrong. My application currently just loops back any strings received.

The endpoint is set to 64 bytes. That was the setting from the example and seems ok. I’ve set the requested_length to 256 and have a buffer allocated to this. This is 4 times the size of the end point.

I’m using Hterm 0.8.9 on Windows 10.
STM32CubeIDE 1.13.2, STM32CubeMX 6.9.2-RC4, STM32Cube MCU Package for H7 1.11.1, X-CUBE-AZRTOS-H7 3.2.0.
ThreadX and USBX is 6.2.1.

When I send a 63 byte string, the read call returns with a length of 63. Data and length are good.

When I send a 65 byte string, the read call returns with a length of 65. Everything is ok.

However, when I send a 64 byte string, the call does not return. I am monitoring the USB traffic with a Beagle 480 USB protocol analyzer. I get an error T which is “Capture for transaction timed out while waiting for additional data.“ If I send an additional single byte, the read call returns with 65 characters. The original 64 and the additional byte.

This certainly seems like a bug as it works at 63 and 65 characters and doesn’t return at 64.

The attached PDF of this has capture information.

    This topic has been closed for replies.

    14 replies

    Graduate
    November 21, 2024

    Having a timeout to handle exact multiples of endpoint size seems a bit of a kludge and not really suited to a high throughput or low latency scenario.

     

    Super User
    November 22, 2024

    @AHugh.2 IMHO the most concerning part of the problem here is quality/stability of the low level USB code (ST library). If it really is as poor as reported and can cause loss of data in a "reliable" bulk pipe, this should be solved first.

    How to handle exact multiples of endpoint size vs. latency depends on ability of the USB driver to pass data to the user. In embedded RTOS everything lives in the same memory space. So as soon as the USB (DMA) gets endpoint-size buffer, the user task can work in it immediately, no latency involved. If more data follows, it is received in background. Even in OS like Linux, low latency can be achieved with shared memory and so on. ZLP is an easy way to signal "end of data" but it is overhead. Not actually required for structure-less serial  data.

     

    Visitor II
    January 16, 2025

    Hi,

    I have the same problem like you, Board:STM32U585xx, but I solved.

     

    By using function (ux_device_class_cdc_acm_read), the 3rd param (requested_length) must be 64 bytes in full speed, no matter how large your receive buffer is(256 or 1024 bytes).

     

    Because in the function (ux_device_class_cdc_acm_read), the reading while loop will check your requested length, if length is 256 bytes and only received 64 bytes, the data is copied to your buffer, but the while loop will keep running, not return.

     

    As you say, 63 bytes or 65 bytes is normal, it's because in the while loop, there is a short packet and ZLP detect, when received length < maxPacketSize(64 bytes), it means this transmit is complete, the function will return directly.

    63 < 64, is short packet, so return.65 = 64 + 1, the 1 will be seen as a short packet, return. So you can get 63 or 65 bytes at a time, but not multiples of 64, because the PC or Linux don't sent ZLP, the loop will not break.

     

    If you need to receive more than 64 bytes at a time, and want to avoid this bug, you need to put together every 64 bytes outside the cdc read function, otherwise you need to change the (ux_device_class_cdc_acm_read) source code, make it fixed.

    Graduate
    January 16, 2025

    The problem is clear. What modification did you make to `ux_device_class_cdc_acm_read`? (TBH I've not not spent any further time on this as yet but it is still on my list!)