cancel
Showing results for 
Search instead for 
Did you mean: 

HAL CDC Transmit dropping and duplicating data

davidpilcher9
Associate III

I have an issue where CDC transmission from an STM32L4 is dropping or duplicating data.

Here is a simple test case that runs from main.c

extern USBD_HandleTypeDef hUsbDeviceFS;
static uint8_t UserTxBufferFS[100];
 
void TestSerial()
{
     // connect USB during this delay
    HAL_Delay(5000);
 
    USBD_CDC_HandleTypeDef *hcdc =  (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
 
 
    while(1)
    {
        while (hcdc->TxState != 0);
 
        // usb no longer till transmitting
 
        memcpy(UserTxBufferFS, "01234567890", 11);
 
        uint8_t ret = CDC_Transmit_FS(UserTxBufferFS, 11);
        if (ret != USBD_OK)
        {
            // data not sent, so retry
        }
 
        while (hcdc->TxState != 0);
 
        // usb no longer till transmitting
 
        memcpy(UserTxBufferFS, "12345678901", 11);
 
        ret = CDC_Transmit_FS(UserTxBufferFS, 11);
        if (ret != USBD_OK)
        {
            // data not sent, so retry
        }
 
        while (hcdc->TxState != 0);
 
        // usb no longer till transmitting
 
        memcpy(UserTxBufferFS, "23456789\r\n", 10);
 
        ret = CDC_Transmit_FS(UserTxBufferFS, 10);
        if (ret != USBD_OK)
        {
            // data not sent, so retry
        }
 
        HAL_Delay(100);
    }
}

This simply posts an expected line out of the USB UART in three chunks, waiting for the TxState to indicate transmission is complete before sending the next block.

From the PC end the terminal shows an occasional either dropped or extended message:

I've pulled this test case out of a very large product code base down to a boot time example of CDC not working. It looks like the buffers are being overwritten or pointers are being corrupted on the next frame transmission, but there is nothing going on here except a loop of basic serial over USB transmission.

0693W000003QHH3QAO.png

I've tested changing the CDC_Transmit_FS size and around 8 bytes length is a sweet spot for least corruption, but it appears to corrupt whatever the size.

I've tried 100ms delays after TxState becomes 0 but it still randomly corrupts on send!

Any ideas?

Many thanks.

5 REPLIES 5
TDK
Guru

Looks like the first 4 bytes of the third transmission are sometimes duplicated.

I would look at the USB traffic with wireshark or similar to see what packets on the line look like. That will show what the chip is actually sending.

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

I have captured with Wireshark and the data is being transmitted:

0693W000003QJZnQAO.png

0693W000003QJaCQAW.png

Packet data length shown in the USB log matches the corrupted data length.

davidpilcher9
Associate III

Also, there are some other patterns of corruption. Sometimes drops occur which I think this is giving an example of despite looking like there is 'more' data - I believe the longer line is because some got lost.

0693W000003QJi1QAG.png

davidpilcher9
Associate III

In case someone comes here with a similar issue, there were two fixes:

  • I migrated to STM32CubeMX 6.01 and used the HAL/USB drivers included in there.
  • I upped the core clock frequency of the STM32. This was the primary issue. Clearly USB requires a core processor frequency that is not too low.

Moving to 6.01, at first I could see similar corruption to this in the terminal program, but no issue in Wireshark, so it turns out there were two issues: The Terminal app (realterm) corrupting data as well as too slow MCU clocking.

Using a secondary application to capture raw serial data I could validate that data was being received ok. My own app is also transferring data without lots of errors now too.

Note: I am now also using the new CDC_TransmitCplt_FS to flag transmission being complete and are using that to block a new call to CDC_Transmit_FS.

Aishwarya
Associate III

hello @davidpilcher9​ 

I am facing the same issue, to solve this issue, continuous monitor the CDC_TransmitCplt_FS   function to get data at serial monitor without corruption but program control reach to CDC_TransmitCplt_FS.