cancel
Showing results for 
Search instead for 
Did you mean: 

USB CDC Transmit Hangs Intermittently

eot105
Associate

Using CDC USB on STM32G4 FW version 1.5.2, Win10 with default VCP driver.

When calling CDC_Transmit_FS() from main() it will work for a few seconds and then hang indefinitely when TxState is never reset to 0. Others have had this issue (see: here, here) and reported the solution being interrupt priority. This is how I have my interrupts set:

eot105_0-1710777165869.png

Which seems right to me, nothing could overwrite the USB Tx interrupt - but the issue persists.

The project this is used in is more complex but this very simple program reproduces the issue:

relevant section of main.c:

uint8_t send_buf[APP_TX_DATA_SIZE];

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
static void MX_SPI2_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_USB_Device_Init();
  MX_SPI2_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  sprintf(send_buf, "Setting output of channel 10 to: 300.00000mA\n");
	  CDC_Transmit_FS(send_buf, strlen(send_buf));
  }
  /* USER CODE END 3 */
}

CDC_Transmit_FS() in usbd_cdc_if.c:

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
  uint8_t result = USBD_OK;
  /* USER CODE BEGIN 7 */
  USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
  if (hcdc->TxState != 0){
    return USBD_BUSY;
  }
  USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
  result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
  /* USER CODE END 7 */
  return result;
}

After connecting to the VCP this will send the expected output for a few seconds and then will stop sending until hard reset. 

Any ideas what I'm doing wrong?

 

2 REPLIES 2
FBL
ST Employee

Hi @eot105 

TxState should be reset after the transmission is complete. Maybe continuously calling CDC_Transmit_FS in the main loop without any delay can overwhelm the USB stack. Introduce a delay or a condition would help to control the transmission rate.

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.

Pavel A.
Evangelist III

Calling CDC_Transmit_FS in the main loop continuously without delay is not nice but by itself It should not "overwrite TX interrupt". It should check the internal state and return BUSY until previous transfer goes thru. So it looks like a sync problem or stack size too small or corruption of variables. For best results, consider other USB library