cancel
Showing results for 
Search instead for 
Did you mean: 

slow data rate with usb cdc on nucleo-h533

MScha.8
Associate II

Hi All,

I'm building an instrument that needs to stream data to a PC at ~4Mbps. People were claiming nearly twice this with USB CDC so I chose the nucleo-h533 board and started with the Ux_Device_CDC_ACM example. I disconnected the USART code and added a loop that calls ux_device_class_cdc_acm_write and then I measure the rate at which I receive data on the PC. I can't get past ~1.8Mbps.

I have tried the following:

  • varying the size of the buffer passed in from 64 to 2048
  • enabling ZERO copy in the driver UX_DEVICE_ENDPOINT_BUFFER_OWNER=1 and defining UX_DEVICE_CLASS_CDC_ACM_ZERO_COPY
  • setting USBD_CDCACM_EPINCMD_FS_BINTERVAL to 1 instead of 5

In all cases, the baud rate remains about the same at 1.8Mbps. Is there anything I can do to improve this?

Best,

Marc

 

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Super User

Hmm

If you add a USB hub, does it go down? If you remove one, does it go up?

Maybe it is a computer hardware limitation. Do you have another PC to test? You're on native Windows as opposed to some virtual machine, right?

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

11 REPLIES 11
TDK
Super User

The PC side needs to poll quickly enough. Most programs do not do this. What are you using on the PC side? Eliminate hubs from the chain. Ensure you send a new buffer immediately after the previous buffer is sent.

If you feel a post has answered your question, please click "Accept as Solution".
Pavel A.
Super User

Check the descriptors. For full-speed device the endpoint size should be 64 bytes. For high speed 512 bytes (on STM32H7 requires external PHY. Without that the "HS" USB instance is full speed).

 

I wrote my own C# application on the PC side and digging into that did indeed uncover a problem. It appears the default behavior for Windows serial ports is a 4096 byte buffer with polling at 16 msec intervals which works out to 2Mbps--exactly what I am seeing.

Some drivers support changing these values in device manager, but the default windows driver that gets used for the STM32 USB CDC device does not as noted in the link below.

Serial Port Latency Option Missing - Windows 11 - Microsoft Q&A

 

-Marc

 

I wouldn't put too much stock in that answer. You're probably running into a C# implementation issue rather than an underlying hardware limitation. If you can, try reading 16 kB at a time rather than 4 kB.

I'm able to achieve 9.2 Mbps.

USB CDC packet loss at high data rates - STMicroelectronics Community

If you feel a post has answered your question, please click "Accept as Solution".
FBL
ST Employee

Hi @MScha.8 

You can optimize better the provided implementation to achieve higher data rate using USBX stack. I'm suspecting the buffering and logic process.

    /* Check if there is a new data to send */
    if (UserTxBufPtrOut != UserTxBufPtrIn)
    {
      /* Check buffer overflow and Rollback */
      if (UserTxBufPtrOut > UserTxBufPtrIn)
      {
        buffsize = APP_RX_DATA_SIZE - UserTxBufPtrOut;
      }
      else
      {
        /* Calculate data size */
        buffsize = UserTxBufPtrIn - UserTxBufPtrOut;
      }

      /* Copy UserTxBufPtrOut in buffptr */
      buffptr = UserTxBufPtrOut;

      /* Send data over the class cdc_acm_write */
      if (ux_device_class_cdc_acm_write(cdc_acm, (UCHAR *)(&UserTxBufferFS[buffptr]),
                                        buffsize, &actual_length) == UX_SUCCESS)
      {
        /* Increment the UserTxBufPtrOut pointer */
        UserTxBufPtrOut += buffsize;

        /* Rollback UserTxBufPtrOut if it equal to APP_TX_DATA_SIZE */
        if (UserTxBufPtrOut == APP_TX_DATA_SIZE)
        {
          UserTxBufPtrOut = 0;
        }
  }
}

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.




Best regards,
FBL

Hi TDK,

I copied serial_gobbler from your post and adapted it to my data stream. My maxread is 4k while yours is 16k which I think accounts for the ~4x faster speeds that you get. What device driver are you using?

 

Received 257344 bytes over the last 1 second (2.06 Mbps) (n=64, minread=1696, maxread=4096)
Received 254944 bytes over the last 1 second (2.04 Mbps) (n=64, minread=1696, maxread=4096)
Received 245056 bytes over the last 1 second (1.96 Mbps) (n=61, minread=1696, maxread=4096)

 

For me, device manager shows this:

MScha8_0-1767102541527.png

-Marc

 

My driver page looks the same as yours. Standard device driver with Windows. I have done no customization other than keeping windows up to date.

varying the size of the buffer passed in from 64 to 2048

Try drastically increasing this to, say, 32 kB.

If you feel a post has answered your question, please click "Accept as Solution".

@TDK wrote:

My driver page looks the same as yours. Standard device driver with Windows. I have done no customization other than keeping windows up to date.

varying the size of the buffer passed in from 64 to 2048

Try drastically increasing this to, say, 32 kB.


No difference at 100kB and many options in between. My app on H533 now statically allocates 100kB of RAM and passes it straight to ux_device_class_cdc_acm_write with ZERO_COPY set.

-Marc

 

TDK
Super User

Hmm

If you add a USB hub, does it go down? If you remove one, does it go up?

Maybe it is a computer hardware limitation. Do you have another PC to test? You're on native Windows as opposed to some virtual machine, right?

If you feel a post has answered your question, please click "Accept as Solution".