STM32CubeMX USB CDC VCP?
Asked Answered
H

3

12

I've found large number of examples, but nothing on how to do it "properly" from STM32MXCube.

How do I create skeleton code from STM32CubeMX for USB CDC virtual COM port communications (if possible STM32F4 Discovery)?

Hobble answered 5/11, 2015 at 15:53 Comment(0)
D
21

A STM32CubeMX project for Discovery F4 with CDC as USB device should work out of the box. Assuming you use an up-to-date STM32CubeMX and library:

  • Start STM32CubeMX
  • Select the board Discovery F4
  • Enable peripheral UBS_OTG_FS device only (leave over stuff uncheck)
  • Enable midlleware USB_Device Communication .. .aka CDC

In the clock tab check the clock source is HSE HCLK. It shall give 168 MHz HLCK and 48 MHz in the 48 MHz (USB). Check there is no red anywhere.

Save the project

Generate code (I used SW4STM32 toolchains)

Build (you may need to switch to internal CDT builder vs. GNU make).

Now add some code to send data over the COM port and voila it should work.

Actually, the tricky part is not try to make any "CDC" access until the host USB connects (no CDC setup yet)

Here is how I did it for quick emit test:

In file usbd_cdc_if.c

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
    uint8_t result = USBD_OK;

    /* USER CODE BEGIN 7 */
    if (hUsbDevice_0 == NULL)
        return -1;

    USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);
    result = USBD_CDC_TransmitPacket(hUsbDevice_0);
    /* USER CODE END 7 */

    return result;
}

static int8_t CDC_DeInit_FS(void)
{
    /* USER CODE BEGIN 4 */
    hUsbDevice_0 = NULL;
    return (USBD_OK);
    /* USER CODE END 4 */
}

In file main.c

/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"
/* USER CODE END Includes */
....

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

    /* USER CODE BEGIN 3 */
    uint8_t HiMsg[] = "hello\r\n";
    CDC_Transmit_FS(HiMsg, strlen(HiMsg));
    HAL_Delay(200);
}

As soon you plug the micro USB (CN5) CDC data will start to show on the host terminal.

That works. I can see "hello" on the terminal (you may need to install a driver, http://www.st.com/web/en/catalog/tools/PF257938).

For reception, it needs to be first armed, say, started by a first call to USBD_CDC_ReceivePacket() in a good place. For that it can be CDC_Init_FS.

Then you can handle data as it arrives in CDC_Receive_FS and rearming reception again from here.

That works for me.

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
    /* USER CODE BEGIN 6 */
    USBD_CDC_ReceivePacket(hUsbDevice_0);
    return (USBD_OK);
    /* USER CODE END 6 */
}

static int8_t CDC_Init_FS(void)
{
    hUsbDevice_0 = &hUsbDeviceFS;

    /* USER CODE BEGIN 3 */
    /* Set Application Buffers */
    USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, 0);
    USBD_CDC_SetRxBuffer(hUsbDevice_0, UserRxBufferFS);
    USBD_CDC_ReceivePacket(hUsbDevice_0);

    return (USBD_OK);
    /* USER CODE END 3 */
}
Deserving answered 5/11, 2015 at 21:43 Comment(10)
First big TNX! , after doing this procedure on my stm32f4Disc device manager shows 2 virtual com ports, I did steps exactly as you said, what could be the issue?Hobble
Why did you switch build (you may need to switch to internal cdt buidler vs gnu make )?Hobble
There is a change in usbdesc.c that should be done to make it work, 0x00, /* bDeviceClass */ changed to 0x02. Could some USB expert put it why?Hobble
depending on SW4STM32 Cube MX version and your "msys" version you may gnu make (call sh) build error due to "(" in commande lineDeserving
I would ask, how should we use CDC_Receive_FS() in main.c if this function declare as static? shame for ST there is no good example of VCP using Cube or at least HAL Libraries.Aiello
@MichelSanches Thanks for this very concise and simple example of how to use the CDC driver. Maybe I'm just stupid, but this has been much more helpful than all of STs documentation combined.Godinez
thanks i know st doc , example are not always easy to find or use or just folow common "logic" :(Deserving
Great answer. What was tricky for me is the STM32 Virtual COM port driver. It is not enough to install it by running the VCP_V1.4.0_Setup. The readme file contains steps that should be done after install. Like running the dpinst_x86.exe for windows 7, 32 bit from the install directory. It was not obvious for me first.Cruciate
right i noticed the issue on the setup for Win 7 and you find out the work around ;) I did noticed st about it maybe it will get fixed ...someday?Deserving
I had to select 'Activate-VBUS' when configuring USB_OTG in CubeMX for a NUCLEO-H723.Valdemar
C
8

There are a number of STM32F4 Discovery boards supported by the STM32Cube software, and you haven’t said which you’re using, but I’ve had exactly the same issue with the Discovery board with the F401VCT MCU.

After installing the STM virtual COM port driver, Windows Device Manager showed a STMicroelectronics virtual COM port, but with a yellow warning mark. The COM port was not accessible with a terminal application (PuTTY).

I eventually found that there is a problem with source code output from the STMCube program. But there is a simple fix:

  1. Open a new STM32Cube project and enable the USB_OTG_FS as Device Only and select CDC Virtual Port COM from the MiddleWares USB_Device drop-down.
  2. Generate the source code with no other changes needed to any USB settings.
  3. In file usbd_cdc_if.c, change #define USB_HS_MAX_PACKET_SIZE from 512 to 256.
  4. In file usbd_cdc.c, change the #define CDC_DATA_HS_MAX_PACKET_SIZE from 512 to 256.

After doing this, the yellow warning disappeared from Device Manager, and I could receive data at the CDC_Receive_FS function (in usbd_cdc_if.c file) when using PuTTY. Be aware that these definitions return to their incorrect values each time the STM32Cube generates code, and I haven’t found a way around this yet.

I hope this helps.

Catiline answered 6/1, 2016 at 11:11 Comment(1)
It is good to note here: Many of STM32 chip's don't even support HighSpeed. if you are using FullSpeed chip USB_HS_MAX_PACKET_SIZE must be equal to USB_FS_MAX_PACKET_SIZE because CDC code has an internal buffer with max packet size. You can save tremendous RAM in these RAM poor devices just doing this.Sri
D
4

iChal's fix worked to remove the yellow warning mark.

I would like to mention that USB_HS_MAX_PACKET_SIZE is now in usbd_def.h and CDC_DATA_HS_MAX_PACKET_SIZE is in usbd_cdc.h

I am using STM32CubeMX v4.11.0 STM32Cube v1.0 and the STM32F401C-DISCO.

On further work, I now only have to set the heap size to a larger value. I am setting it to 0x600 as I also have FreeRTOS enabled. I am using IAR EWARM, so the change is made in linker script stm32f401xc_flash.icf.

Dissidence answered 14/3, 2016 at 20:25 Comment(1)
if that can help requirement to have a descent "min heap size " with freertos +usb stack is cos of non rtos aware malloc and _sbrake getting confuse because "task sp" is not the shared heap/stack ram hence it fail to spit/brake the heap/stack . but usage of "malloc" (usb stack) is anyway not much thread safe.Deserving

© 2022 - 2024 — McMap. All rights reserved.