cancel
Showing results for 
Search instead for 
Did you mean: 

USBX CDC ACM data read bug?

tec683
Associate III

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.

9 REPLIES 9
mohamed.ayed
ST Employee

Hi @tec683 ,

Thanks for reaching out ST community.

could you please confirm that this flags UX_DEVICE_CLASS_CDC_ACM_WRITE_AUTO_ZLP  is defined in ux_user.h in your project ?? 

 

 

Pavel A.
Evangelist III

The host does not send ZLP.

@tec683 Have you installed any special driver on Win10 for the USB serial port or Windows automatically recognized the CDC ACM device?

 

tec683
Associate III

I am using the standard Windows serial driver that is installed by default ie no special INF file or anything.

Yes,  UX_DEVICE_CLASS_CDC_ACM_WRITE_AUTO_ZLP is enabled in the IOC and defined in ux_user.h file. Though reading the comments, this just seems to affect the write behavior and not the read where I'm seeing what seems like anomalous behavior. 

Pavel A.
Evangelist III

Try another terminal program. Teraterm.

 

tec683
Associate III

I see the same behavior with Teraterm. I would think the Windows CDC ACM driver would be the main cause of behavior which will be the same across different terminal programs.

Pavel A.
Evangelist III

The Windows driver works for millions of users, every day, with thousands of device models. I cannot figure out why the ZLP is not sent, even with different host applications. Suggest to re-check your endpoint descriptors.

 

 

tec683
Associate III

I didn't say the windows driver was doing anything incorrect.  Just that the terminal program selected was not likely to matter for a low level issue such as I am describing. The terminal programs likely just take the input string and sends it to the COM write function call.  So the behavior is likely the same between programs.

To your point that the windows driver is likely correct, the problem is more likely in the STM32 firmware. As a practical matter, even if we could somehow prove the Windows USB serial driver was doing something incorrect, the device implementation would have to work around what ever the behavior is because it certainly is not practical to expect all the deployed Windows copies to change anything. 

I'm new to USB and specifically USBX. In another unanswered post, I could not get the USBX CDC ACM to work on an F7 series processor.  I had success on an H723.  But even on the H723, I found the behavior described here.  I'm hoping that someone much more knowledgeable than me on STM32, USB, and USBX could explain this behavior in more detail.

Hi, did you get any resolution to this problem?

I'm seeing the same thing - host PC sends 64 bytes and the USBX stack doesn't respond, whereas 63/65 bytes is fine. From what I see too, the ST/USBX stack is expecting more data or a ZLP but neither the standard Windows 11 serial CDCADM driver, nor Linux, sends one.

So it would seem to me that this has to be handled in the ST firmware/USBX but isn't. I'm using STM32U585.

I found a messy work around that seems to be working.

I do a blocking read with the read size set to the end point size of 64 bytes.  This returns if the data sent is less than or equal the end point size.  If less than the end point size, I think the ZLP is working as expected.  If exactly the end point size, I buffer this data and set a 50 mS timer.  If the data transmission is greater than the end point, the subsequent calls return with that data.  If the data returned is less than the end point, that completes the transmission. If another full end point, keep reading.  If the timer times outs, assume the transmission was a multiple of the end point size and consider the transmission complete with the previously buffered data.

The serial communication in my application is not very high performance.  I'm also sending specific messages so it doesn't have to work for streaming.  I've verified this with terminal programs and my own applications using COM calls.

A side note, a couple of months ago I noticed there is an USB IO control call that supports setting a timeout on USB CDC reads and writes.  I tried that and while I could do reads with buffers bigger than the end point size, I found it to randomly drop messages.  Since I had the other approach working, I just returned to using it as I didn't have time to dig into this other behavior.

What I am finding is while the ThreadX implementation is solid as it has been used on a wide variety of platforms and I expect many different projects, the ST contributions to adapt to their processors have not been as reliable or robust.