cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F1 USB CDC Transmit is getting more slower on large data transfer

BOh.1
Associate II

Hello community,

I'm using USB CDC functionality of STM32F103C8T6 to read file data from FATFS by SPI and transmit it to USB host by CDC_Transmit_FS(). USB MSC mode is not available because I need to send other commands to STM32 via CDC.

The file transfer sequence is like below:

1. Read 1 KB from the FATFS by f_read() to UserTxBufferFS, which is the USB Tx buffer. It typically took ~6ms each.

2. Call CDC_Transmit_FS() to transmit 1 KB from UserTxBufferFS. Busy waits for the previous transfer by checking if it returns USBD_BUSY.

3. Repeat until the file ends. There are 2 buffers and next f_read() will load data into UserTxBufferFS_2.

 

And I found something strange. USB CDC transfer is getting slower and slower as the transfer file size increases.

The busy-waiting time for the CDC transfer took 0 ms for the first 75 KB, which looks like it just copy data to its internal buffer and finish until the next 6ms f_read() ends.

Then, the waiting time starts to increase. if UserTxBufferFS is 1KB, it took some time once in a 5.

The delay looks like: 0 0 0 0 30 0 0 0 0 40 0 0 0 0 70...

And the delay is getting bigger and bigger as transferred bytes size increases. It took almost 300ms when the total bytes sent was over 300 KB.

 

Increasing time was all same for the various UserTxBufferFS size from 512 B to 4 KB.

Here is the graph of the time spent busy waiting, as the total bytes sent increases.

 

KakaoTalk_20240804_023631848.png

 

What I'm wondering is why it is getting much slower as more data is sent. If it is due to the buffer full, it should be bound to the maximum time of sending the full buffer.

If I use 2 KB buffer, it takes time once in a 3. Like 0 0 300 0 0 300... as the graph shows.

If the buffer is 4 KB, it takes time once in a 2, it took 0 300 0 300 0 300...

 

If it took 300ms to transmit 2 * 4 KB data, it is ~ 220,000bps, or 0.2 Mbps which is so disappointing speed for the USB FS.

 

What should I do to fix this? Changing receive buffer size from the Windows Device Manager side had no effect.

 

Here is the code used:

FIL fp;

if (f_open(&fp, (const char *)buf, FA_READ) != FR_OK) {
  USB_RESPONSE(RESP_ERROR);
  return;
};

uint32_t total_read = 0;
uint32_t use_primary = TRUE;

uint8_t usb_ret;

while (total_read < f_size(&fp)) {
  uint8_t *buf = use_primary ? UserTxBufferFS : UserTxBufferFS_2;

  uint32_t read;

  // f_read took typically 6 ms
  if (f_read(&fp, buf, APP_TX_DATA_SIZE, (UINT *)&read) != FR_OK) {
    USB_RESPONSE(RESP_ERROR);
    return;
  }

  total_read += read;

  USB_Transmit(buf, read); // <------ this is the one took so long!!

  use_primary = !use_primary;
}

#define USB_Transmit(buf, len)             \
  {                                        \
    do {                                   \
      usb_ret = CDC_Transmit_FS(buf, len); \
    } while (usb_ret == USBD_BUSY);        \
  }

 

Thank you for your help in advance.

2 REPLIES 2
FBL
ST Employee

Hi @BOh.1 

It seems CDC transfer become progressively slower because of busy-wait time for CDC_Transmit_FS()

To alternate between reading and transmitting in double buffer mode in current driver, it seems to be not properly handled.

Try the following fixed updates on F0 (internal ticket number 191935 is submitted to dedicated team)

 [HAL][LL][USB] Fix added to support bulk transfer in double buffer mode · STMicroelectronics/stm32f0xx-hal-driver@24bab79 (github.com)

 

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.

FBL
ST Employee

Hi @BOh.1 

Would you please provide us with minimal firmware and setup to reproduce on my end the behavior?

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.