AnsweredAssumed Answered

USB CDC Receive for the STM32F103C8 using CubeMX?

Question asked by Nathan Conrad on Sep 6, 2017
Latest reply on Nov 29, 2017 by Vitor Pereira

How should I implement USB CDC Receive for the STM32F103C8 using CubeMX? I could not find any examples.


I have a partially working implementation of a USB CDC for this IC, but I have a few occasional issues with missed data.


First, I don't understand the CDC_Receive_FS(...) function.


  1. Do I process/copy the buffer on line 5 or line 10?
  2. Why does it need to SetRxBuffer? It shouldn't change, should it? Isn't it always stored into UserRxBufferFS? Or is this function passing a pointer to some other buffer internal to the USB driver, and UserRxBufferFS is never used?
  3. What does USB_CDC_RecivePacket do? Since it does LL stuff, why wouldn't it be called by the function that calls CDC_Receive_FS?
  4. My understanding is that the max packet length for full-speed USB is 512 bytes. Do I need to change APP_RX_DATA_SIZE to be 512?
  5. Are there still concerns with read/write locking? (See TM32Cube USB CDC (possible) Bug Found - Rx Tx Race condition).
  6. Is there a way to cancel the previous USB transmit, or append data to its buffer?


static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
  /**** Do I process the buffer here? ****/
  /* Can the next line be removed, unless the RX buffer needs to change? */
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); /*<-- Change buffer for next RX? */
  /**** Or do I process it here? ****/
  return (USBD_OK);
  /* USER CODE END 6 */

I'm currently detecting if the USB CDC is connected by seeing if the previous transmission succeeded in a timely fashion. I'm using FreeRTOS. Is this proper, or is there a better way? Since I don't know how to cancel the previous transmit, I don't want to overwrite the buffer while it may still be transmitting.

static void usbTx(char *msg) {
     static TickType_t lastXmit = 0;
     /* If still transmitting, and it has been more than 200 ms, give up */
     while(CDC_Busy() && (xTaskGetTickCount()-lastXmit < (200/portTICK_PERIOD_MS ))) {
     // Last transmission failed, so lets skip this one.
     size_t len = strlen(msg);
     uint8_t result = CDC_Transmit_FS((uint8_t*)msg,len);
     if(result == USBD_OK)
          lastXmit = xTaskGetTickCount();