cancel
Showing results for 
Search instead for 
Did you mean: 

How to Handle CDC_Transmit_FS Completion Effectively

Shreayas_Acharaya
Associate III

Hello ST Community,

I am working on a project using an STM32 microcontroller with USB CDC class for communication. I am using the CDC_Transmit_FS function to send data over USB, but I am looking for best practices to handle the completion of data transmission effectively.

Current Implementation

In my current implementation, I am transmitting data using the following code:

 

 

char usb_buffer[64];
snprintf((char *)usb_buffer, sizeof(usb_buffer), "Hello, World!\r\n");
while (CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer)) == USBD_BUSY) {
    HAL_Delay(100); // Delay to allow USB stack to process
}

 

 

While this works, it is not efficient as it relies on a blocking delay which may not be optimal for all applications.

Questions

  1. Non-blocking Transmission: What is the best way to implement non-blocking USB transmissions using CDC_Transmit_FS?
  2. Completion Callback: Is there a way to use a completion callback to notify when the transmission is complete?
  3. Handling Busy State: How can I handle the USBD_BUSY state more effectively without using blocking delays?

Goal

My goal is to improve the efficiency and responsiveness of the USB transmission in my application. I want to ensure that the data is transmitted reliably without unnecessary delays and that the system can perform other tasks while waiting for the transmission to complete.

Additional Information

  • I am using the STM32CubeIDE generated USB stack.
  • The USB device is configured as a Virtual COM Port (CDC).
  • I am using the HAL library for peripheral initialization and control.

I would greatly appreciate any guidance, examples, or best practices on how to handle CDC transmission completion effectively.

Thank you for your assistance!

13 REPLIES 13
Shreayas_Acharaya
Associate III

Okay, I have attached my IOC file here.

BarryWhit
Senior III

You are right. The code generated for the F3 does not include this callback (It is present in code generated for G4).  I'll try and track down how the callback is called in the G4 code, to see if there's a reason why the F3 doesn't include such a callback (perhaps it's just an older version of library)

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.

Yes, the F3 firmware pack uses an old version of the USB device library (2.5.3) from April 2019.

This callback was added in 2.6.0 December 2019.

USB_new_version.jpg

 

You can try to simply replace the library (or even just the CDC library files your project uses) with a newer version (from the G4 firmware pack for example) and work through the compiler errors, if any. Maybe you'll get lucky.

 

The invocation of the callback in the new version of the lib comes from a simple change to

USBD_CDC_DataIn:

 

 

static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
  // ...
  else
  {
    hcdc->TxState = 0U;

    // this was added in 2.6.0
    if (((USBD_CDC_ItfTypeDef *)pdev->pUserData)->TransmitCplt != NULL)
    {
      ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum);
    }
  }

  return (uint8_t)USBD_OK;
}

 

 

So, in the worst case, you can diff the two versions and pick out only the changes relevant to CDC (added struct members, updated code generation templates, etc), and apply them. It's not fun, but it's doable.

 

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.
BarryWhit
Senior III

@Shreayas_Acharaya I came cross this and I thought it may be useful to you:

How to use STMicroelectronics classic USB device middleware with new STM32 families

 

it explains how to port the middleware to families in which it isn't supported anymore, but should also be useful for your case, where you want to upgrade the library version to a newer version. Just in case it turns out to require more than simply copying over the updated library files.

 

 

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.