cancel
Showing results for 
Search instead for 
Did you mean: 

Stm32f4 Usb VCP corrupted data (CubeMX)

cfischbeck
Associate II
Posted on September 22, 2017 at 19:01

Hi,

I have a problem while implementing a USB Virtual Com Port (USB CDC Class) with CubeMX.

The setup is the following:

PC running Hyper Terminal sends keystrokes to the microcontroller (STM32F407VG) which are echoed to UART.

Now when im sending the same character more than once, every second byte returned is not the character I sent.

I Debugged it to the point where the I can see that the RX Buffer (given to USBD_CDC_SetRxBuffer) is already wrong when the OTG_FS_IRQHandler is called.

What do I have to look for?

3 REPLIES 3
Tilen MAJERLE
ST Employee
Posted on September 26, 2017 at 10:15

Hello

Fischbeck.Carsten

‌,

Can you show us your interface file where you call

USBD_CDC_SetRxBuffer function?

Best regards,

Tilen

cfischbeck
Associate II
Posted on September 26, 2017 at 11:07

Majerle.Tilen

Can you show us your interface file where you call

USBD_CDC_SetRxBuffer function?

Yes.

//usbd_cdc_if.c

...

#define APP_RX_DATA_SIZE 64

#define APP_TX_DATA_SIZE 64

...

uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];

/* Send Data over USB CDC are stored in this buffer */

uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];

...

static int8_t CDC_Init_FS(void)

{

/* USER CODE BEGIN 3 */

/* Set Application Buffers */

USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);

USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);

return (USBD_OK);

/* USER CODE END 3 */

}

...

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)

{

/* USER CODE BEGIN 6 */

extern osMessageQId QueueUsbvcpRxHandle;

extern osSemaphoreId BinarySemUsbvcpRxReadyHandle;

int i; for(i = 0; i < *Len; i++)

{

osMessagePut(QueueUsbvcpRxHandle, Buf[i], 0);

}

osSemaphoreRelease (BinarySemUsbvcpRxReadyHandle);

return (USBD_OK);

/* USER CODE END 6 */

}

...

void UsbvcpRxStart(void)

{

USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &UserRxBufferFS[0]);

USBD_CDC_ReceivePacket(&hUsbDeviceFS);

}

...

//freertos.c

...

void TaskUsbvcpRx(void const * argument)

{

/* USER CODE BEGIN TaskUsbvcpRx */

/* Infinite loop */

for(;;)

{

if(osSemaphoreWait (BinarySemUsbvcpRxReadyHandle, 10000) != osOK)

{

//fix uart error

}

UsbvcpRxStart();

}

/* USER CODE END TaskUsbvcpRx */

}

...

Above is the code responsible for Rx. Short explanation, the functions SetRxBuffer and ReceivePacket are extracted from the interrupt, because in previous projects (without rtos) it caused a crash because of HAL LOCK macro, when the struct is used at the same time by the interrupt and 'main' when full duplex transmissions occured. The problem described in original post arised there too, but I cant remember how i solved it. Maybe I left it aside and it just dissapeared. Ich checked the code but didn't find anything regarding to this.

Posted on September 26, 2017 at 11:35

There a few other things i did:

-----------------------------------------------------------------------------------------------------

static int8_t CDC_Control_FS  (uint8_t cmd, uint8_t* pbuf, uint16_t length)

{

    /* USER CODE BEGIN 5 */

    static uint8_t data_code[7];

    switch (cmd)

    {

...

    case CDC_SET_LINE_CODING:

        if (length > 7)length = 7;

        memcpy(data_code, pbuf, length);

        break;

    case CDC_GET_LINE_CODING:

        if (length > 7)length = 7;

        memcpy(pbuf, data_code, length);

        break;

...

-----------------------------------------------------------------------------------------------------

This fixes a possible crash with hyperterminal.

After the CDC is initialised:

-----------------------------------------------------------------------------------------------------

...

extern PCD_HandleTypeDef hpcd_USB_OTG_FS;

    ((USBD_HandleTypeDef*)(hpcd_USB_OTG_FS.pData))->pClass->DataIn = USBD_CDC_DataIn_2;

...

uint8_t  USBD_CDC_DataIn_2 (USBD_HandleTypeDef *pdev, uint8_t epnum)

{

    extern osSemaphoreId BinarySemUsbvcpTxReadyHandle;

    USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;

    if(pdev->pClassData != NULL)

    {

        hcdc->TxState = 0;

        osSemaphoreRelease (BinarySemUsbvcpTxReadyHandle);

        return USBD_OK;

    }

    else

    {

        return USBD_FAIL;

    }

}

-----------------------------------------------------------------------------------------------------

The custom callback function is a copy of USBD_CDC_DataIn with an added Semaphore for freertos. I did it this way so it does not get overwritten if I regenerate the code from cubeMX.