cancel
Showing results for 
Search instead for 
Did you mean: 

(SOLVED) USB Device CDC middleware : unable to even understand how to use it.

JDoe.2
Associate III

(I'm still working on this, I'll edit this as I progress, keep reading)

Well, the title of this question should be clear enough. I wanted to add virtual COM port functionality to a project. Using STM32CubeIDE, I enabled the USB device on an SMT32F103 and then I enabled the USB CDC middleware. After generating the project, I get 20 new source files, none of which seem to contain anything even remotely comparable to the USART HAL functions, either in name or in purpose.

The code does compile. But when I connect the USB to my PC my board isn't even enumerated. The generated code calls an MX_USB_DEVICE_Init function which executes without error but then again, so would a bunch of NOP's.

The offical documentation at https://www.st.com/resource/en/user_manual/dm00108129-stm32cube-usb-device-library-stmicroelectronics.pdf seems like it's talking about an entirely different middleware. It mentions files that appear nowhere in the code I generated. The "how to use" section might as well be fiction.

Trying to be as thorough as possible, I look at the example projects that shipped with the HAL installed on my PC (version 1.8.0) and find a couple of CDC example which do contain the files mentioned in the documentation (usbd_cdc_interface.c and .h)

So I read those files, trying to find what they could be doing and how it matches what the code generator barfed. I'm hopeful at first : it looks like this code uses the USART HAL functions over the VCP, using a mysterious instance USARTx... except I look for its definition and it turns out to be USART2. I'm starting to get angry : how is a function named CDC_Itf_Init is supposed to work if it references USART2 ?

At this point I've spent the better part of 4 hours trying stuff, reading code, Googling left and right, and I know the pattern : once again, as with Ethernet, Cube is trying to sell me something that doesn't exist and I'm wasting my time.

So I'm going to ask : can anyone show me how to use the so-called Communication Device Class middleware that Cube claims to offer ? Namely, how do I open that serial port, setup its baud rate, and send and receive data ?

I swear, any time I try to use Cube for anything more complex than blinking an LED, this kind of crap happens. I may have to start billing ST for my time.

(Cue Spongebob meme) 5 hours later...

I've started reverse-engineering the stuff Cube vomited into my project and I'm getting somewhere...

First, regarding the enumeration issue : that was a bad cable on my part. Apparently I grabbed an old "charge only" cable from work, you know, those that don't let you steal work data using your phone. With an actual USB cable, the STM32 enumerated and a nice new COM port appeared on my system.

Next step was to figure out data transfers. I'll spare you the details but I ended up in a file named usbd_cdc_if.c and that file appeared to contain nearly everything I needed :

  • Tx and Rx buffer declarations
  • Transmit function
  • Receive function, that's apparently passed as a handler to... something
  • Assorted init functions

My stm32f1xx_it.c file also got a new interrupt handler : USB_LP_CAN1_RX0_IRQHandler, which my intuition tells me is in charge (among other things) of handling incoming data over the virtual COM port.

At that point it wasn't clear where I should look next; so I decided to try actually using what I found. Good news :

  • I can use the CDC_Transmit_FS function to send data over the VCP. It's non-blocking, by the way.
  • I can read incoming bytes directly from the receive buffer UserRxBufferFS though that's clearly not how it should be done.

I still need to figure out non-blocking reception of data. There's a CDC_Receive_FS function but... well here's what its comment says. If you understand what's supposed to happen don't hesitate to share :

 *     Data received over USB OUT endpoint are sent over CDC interface

 *     through this function.

 *

 *     @note

 *     This function will block any OUT packet reception on USB endpoint

 *     untill exiting this function. If you exit this function before transfer

 *     is complete on CDC interface (ie. using DMA controller) it will result

 *     in receiving more data while previous ones are still not sent.

They say that "the code is its own documentation" is a stupid saying, but hey in this case it's better than any form of documentation I've come across. I'll keep at it, meanwhile don't hesitate to contribute. Thanks.

BREAKING NEWS : I've done it !

Sorry, I forgot to update this post afterwards but I eventually managed to understand how to use the Cube library. On the plus side, I've documented absolutely everything on my website, and you can find it at :

https://nefastor.com/microcontrollers/stm32/usb/stm32cube-usb-device-library/

My site targets newbies, so there may be a lot of explanations you don't need, but I've tried to make it funny (depending on your sense of humor). There are four pages in that section, you can access them with the navigation menu on the right.

Constructive criticism is welcome !

On a personal note : the Cube library, while it works, is definitely not beginner-friendly. I'm far from a beginner and it was a painstaking process to use it. Perhaps I'm wrong to compare Cube to Arduino but if you need to develop something really quick, especially a proof of concept, Cube isn't for you.

Maybe next I'll tackle Ethernet and LWIP.

21 REPLIES 21

Hi,

For me enumeration in system works without any problem. I use windows 8.1.

Some idea why it can't work: Do You have installed stm virtual com port driver if You not use windows 10?

https://my.st.com/content/my_st_com/en/products/development-tools/software-development-tols/stm32-software-development-tools/stm32-utilities/stsw-stm32102.license=1604465327594.product=STSW-STM32102.version=1.5.0.html

Best Regards

Hi,

I have installed this driver too. But still it won't get enumerated.

Thanks anyway

I did manage, in the end. I've updated my post. Long story short, head over to my website to learn everything I have, there's also a tutorial.

https://nefastor.com/microcontrollers/stm32/usb/stm32cube-usb-device-library/

I did manage, in the end. I've updated my post. Long story short, head over to my website to learn everything I have, there's also a tutorial.

https://nefastor.com/microcontrollers/stm32/usb/stm32cube-usb-device-library/

Hi,

Nice tutorial. I will read it for sure.

Would it be possible that you kindly share the project files with us too?

You are hero!

Thanks a million,

Ehsan,

As you know, coding on STM32 is more than just the source files, there's also the project configuration, etc... and a lot may be specific to your board. So what I've done on my site is try to be generic and show you how to setup the project, generate the code, and then what part of the code to modify. After that, you should be able to copy-paste code directly from my site. I think this will be a lot easier than if I just upload my source files and you need to modify everything so it works on your board.

@Community member​ ,

Very nice pages.

JW

Hello,

nice tutorial, it solved my issue with the STM32F103 on my Olimex-Board, not it connects. The issue was very simple:

Pin 53, DISC, controls the 1.5k Pullup. Once I configured it correctly and the pullup was active Windows detected the device and the STM32-P103 (Rev.B) Board showed up as a VCP. With a terminal I was able to receive Strings.

HAL_GPIO_WritePin(GPIOC, DISC_Pin, GPIO_PIN_SET); // Make sute the DP+ is pulled up

Thank you very much for the good work, I hope you continue your tutorial. How about Interrupts, DMA,… ?

Best Regards, Seppel

0693W000005Aw5OQAS.png

Glad to have been helpful. Given the current pandemic and other things happening in my life, I intend to spend a lot of time working on my website but also on a YouTube channel. There's a lot of work involved in setting everything up, but once that's done I'll be posting regularly. Not sure if this can become a new career but if all else fails I still have my day job !

JDion.1
Associate

I feel your pain and frustration, I have things sort of working, but trying to understand how the interrupt works for available CDC data. If I remove debug messages, stuff stop working properly, it seems to be a timing issue, but I can't find enough descriptive documentation on how the USB middle-ware CDC works to be able to debug! Its been a year working on this and I still don't have a handle on how it works, just pick up bits of code hear and there on the web, nothing from official docs from ST!