S: Simple STM32F103 usb vcp interrupt driver in C - Page 1
Forum section: electronics / general

author: bingo600
author_rank: Super Contributor
timestamp: March 23, 2016, 05:05:13 pm
content: GentsI'm playing with the cheap stm32f103 boards from *bayI would really like to get the usb interface going as a uart.I need it to be interrupt controlled, so i don't need to poll for incomming outgoing data.I'm not familiar with c++ , so i need a simple working example in C , with a makefile for arm-gcc.Does anyone of you have a simple "loopback" example to share ?Please don't point at stm32cube , but at a working exampleTIA/Bingo

author: Brutte
author_rank: Frequent Contributor
timestamp: March 23, 2016, 07:00:25 pm
content: STM32_USB-FS-Device_DriverQuoteNot sure about the board you are using but I am almost sure the LEDs and pushbuttons might be tied to different IOs than Evals used for those examples (requires some #define renaming).

author: Jeroen3
author_rank: Super Contributor
timestamp: March 23, 2016, 08:04:09 pm
content: Yes. Just don't use CAN at the same time. CAN and USB share their peripheral memory.

author: Brutte
author_rank: Frequent Contributor
timestamp: March 23, 2016, 08:49:05 pm
content: Quote from: Jeroen3 on March 23, 2016, 08:04:09 pmAnd also worth noting STM32F103 does not have an integrated DP pullup, as in the case of STM32L1XX chips. So depending on the design of your Chinese FR4 the firmware might be forced to service setup packet just after power-up (PITA debugging and restarting USB) if DP is hard-wired.Did I mention the USB requires ACCURATE clock of adequate frequency? So I suggest that you should configure MCO pin (PA8) to check if you use what is intended. Running USB from misconfigured RC clock is very frustrating. Been there, done thatCode:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_MCOConfig(RCC_MCO_SYSCLK);//<- HERE PICK THE CLOCK SOURCE, do not exceed 50MHz//The MCO is an alternate function of PA8GPIO_InitTypeDef GPIO_MCOStructure={.GPIO_Pin = GPIO_Pin_8,//MCO pin.GPIO_Mode = GPIO_Mode_AF_PP,//MCO on PA8.GPIO_Speed = GPIO_Speed_10MHz,//edge smoothing};GPIO_Init(GPIOA,&GPIO_MCOStructure);

author: bingo600
author_rank: Super Contributor
timestamp: March 23, 2016, 10:48:22 pm
content: Thanx Brutte , i have seen that one.I was hoping for a working example with a makefile (blush...) , i'm a big usb beginnerThat lib just have stupid ide "files"I use Code::Blocks "launchpad gcc" and external makefiles.Ohh and i don't think i have any sw-config DP pullup , but might hack something together with a small fet./Bingo

author: Brutte
author_rank: Frequent Contributor
timestamp: March 23, 2016, 11:25:47 pm
content: Quote from: bingo600 on March 23, 2016, 10:48:22 pmThe linked "USB library" is a set of 6 source files + some accompanying headers. Just copy those to each of those USB projects, add -I here and there and you are done. No need to make a static library for that if you do not want to. Same applies to peripheral library, ctrl+C/V would do. Mind ctrl+C/V is not the proper way to manage source files because of the maintenance, upgrades etc, it is always better to keep it as lib in one place and just -l.As for the project and IDE, these are provided (with project settings) for 4 IDEs: Keil, Atollic, IAR and Raisonance. No netbeans.Atollic is gcc-arm-embedded if you are interested in detailed makefile settings.I am assuming you have already mastered "hello world" or "blinky" at least...If that was over optimistic and you want to start Project_One from transplanting ST VCP to your custom IDE - no.I am assuming your cutting edge FR4 is properly tied to some decent debugger, gdb works seamlessly, etc.

author: bingo600
author_rank: Super Contributor
timestamp: March 24, 2016, 07:04:03 pm
content: Quote from: Brutte on March 23, 2016, 11:25:47 pmI have done "blinky" , serial and some other stuff , and have a stlink-v2But would have loved a working demo as a base.I am rather surprised that there isn't a working example "out there" for the F103 , i have trawled the net for hours.I might go with stm32cube, now that i have to flicker something together my selfWell thanx BrutteI'll see what i can come up with./Bingo

author: Brutte
author_rank: Frequent Contributor
timestamp: March 24, 2016, 07:50:27 pm
content: Quote from: bingo600 on March 24, 2016, 07:04:03 pmBut the point is that those are working examples!You just open the project ST provides in one of the IDEs I have mentioned, click the "make and run" and enjoy USB VCP! Do you think these ST examples are buggy, are you superstitious or what?It is simply that those examples are not tailored to Chinese $3 "evals". Nor to Code::Blocks you happen to use. Well apparently you cannot suite all.Have you considered installing uVision? It has 32k limit for debugging but you should have running VCP example in no time. IAR has no size limit but it only runs for 30 days or so. Not sure about Atollic or Raisonance limitations.

author: dadler
author_rank: Unknown
timestamp: March 24, 2016, 08:33:39 pm
content: There might be a starting point here:https://github.com/libopencm3/libopencm3-examples/blob/master/examples/stm32/f1/stm32-h103/usb_cdcacm/cdcacm.cNot much for interrupt based, but at least the basic APIs are cleaner than the std peripheral library or that cube nonsense.There may be an interrupt based version in one of the other chip directories that can be adapted.

author: westfw
author_rank: Super Contributor
timestamp: March 25, 2016, 07:22:19 am
content: QuoteUSB tends to be substantially complex. People who loudly proclaim that "the vendor libraries are all complete crap" and are completely happy to write their own drivers for normal peripherals like I2C, SPI, UART, and A2D are prone to looking at USB stuff and saying "well, maybe just this once..." :-)You might look at the STM32 Arduino stuff...https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/STM32F1/cores/maple/usb_serial.cpp

author: bingo600
author_rank: Super Contributor
timestamp: March 25, 2016, 10:46:11 am
content: Quote from: Brutte on March 24, 2016, 07:50:27 pm@Brutte Please behave , you are not on "Freaks"The reason i was asking for a working example with makefile , is simply that i have no experience with USB comms.And i know that there are a lot of traps in USB for the inexperienced.Instead of figthing ie. a wrong PLL setup or whetever, it would have been a lot easier to get a working example.I know i'm taking the "lazy route" , but as westfw mentions: I would be perfectly happy with a "blackbox lib in C" that suited my needs and arm-gcc.But i'm still wondering why there isn't any arm-gcc examples with makefiile for the F103 "out in the wild", and was hoping that this post would make a mini project show up.I'll stop here and work with the tips i have gotten so far.Thanx to you all./Bingo

author: Brutte
author_rank: Frequent Contributor
timestamp: March 25, 2016, 02:52:40 pm
content: Quote from: bingo600 on March 25, 2016, 10:46:11 amIndeed, clock tree can ruin your day. That is where MCO + frequency counter comes handy.Anyway, I cannot help you with the project because I do not have STM32F103 right now (I use STM32L1XX). I suggest you should download STM32F10X peripheral library (from ST site), run through all the blinkies (toggling IOs, UART loop, IRQs etc) to practice a bit. Once you gain some experience you can move to USB.

author: westfw
author_rank: Super Contributor
timestamp: March 25, 2016, 05:04:44 pm
content: (USB reminds me of COBOL. It doesn't seem like the actual data transfers should be all that difficult, but there's all this "identification division, "environment division", and "data division" stuff (identification, enumeration, and setup?) that has to happen first, which contains more complexity and formality than I'm used to...)

author: Brutte
author_rank: Frequent Contributor
timestamp: March 25, 2016, 06:28:28 pm
content: Quote from: westfw on March 25, 2016, 05:04:44 pmThe library we are talking about is made so that for bidirectional communication you only provide three parts:1. Descriptors (const arrays of some 0xnumbers)2. Function that is called by USB IRQ when some data was received via USB endpoint (OUT)3. Function that is called by USB IRQ when some data was sent via USB endpoint (IN)Descriptors say how much current STM32F103 draws, how many endpoints it has, the USB class, endpoints directions, speed etc.As for functions, for bidirectional endpoint #1:Code:void EP1_OUT_Callback(void){//your code for receiving comes here}void EP1_IN_Callback(void){//your code for sending comes here}Not very sophisticated. Once the code does the job (reads or writes to USB shared memory, respectively) you have to flip a designated register bit to tell USB hardware that now it can take care of that shared memory (overwrite it with new incoming data or push the content to the host, respectively).Not sure about details but I think STM32F103 does up to 8 endpoints, all of them are independent, have their own memories, flip bits, etc.Interesting feature for these uCs is that they have a configurable IRQ that triggers on several USB errors. For example framing or some bit stuffing anomalities etc. That is how I found out that my clock tree used an internal RC instead of the quartz