git clone https://github.com/rogerclarkmelbourne/Arduino_STM32.gitBuried inside here, is the directory Arduino_STM32/STM32F4/cores/maple/libmaple/usbF4, which is what I have been studying, for better or worse. This is code from ST Micro, taken from who knows what exactly. It came from them, then was part of libmaple, then that morphed into Arduino_STM32, or something like that.
I have been studying this code, but got the idea, "how hard would it be". So I pulled this directory into my "Hydra" project and spent about 3 hours fussing with it and creating a Makefile and got it to build and run, which was less trouble and suffering than I expected.
I did some cleanup. For whatever reason (i.e. signficant brain-damage) the ST code sequesters C source in an "src" directory and related include file in a "inc" directory. I did away with that nonsense and put both files together in one directory. I also shortened long directory names, and when I was done, I had files in 3 directories: driver, library, and vcp. The library also had things neatly split into a Core and Classes directory, with the code of interest to us in the Classes/cdc directory. I did away with all of that, deleting all the other Classes and putting the core and cdc files (and include files as well) into the directory "library". Too much "organization" is actually a bad thing.
Some of their nomenclature is a complete mystery. Who knows what DCD is supposed to stand for, but it ends up everywhere. Vcp and cdc are straightforward. Vcp stands for "virtual com port", and that is exactly what we want to end up with. Cdc is "communications device class" and is one of the standard USB classes that you can go read about. Just why "CDC" doesn't do the job by itself and why we need VCP to go along with it, is another mystery. Just what the API is between the various components of this 3 part epoxy is pretty vague, but it may all make sense someday.
At first glance this doesn't seem like much code, but when you actually count lines, there are 6413 in driver, 3136 in library, and 4081 in vcp for a total of almost 14,000 lines which is nothing trivial at all.
So, when I fire this up on my STM32F411 board and my linux system sees it, linux likes what it sees and hooks up a driver and calls this /dev/ttyACM0. I can put together a little loop to send a hello message once a second, run picocom on /dev/ttyACM0 and I see output.
This merits some investigation. It seems like it should be possible (up to a point) to buffer pending output so we always get everything written to USB when we connect picocom. It turns out that like reads, writes simply deposit data into a circular buffer and then return immediately. I see no evidence that this gets reinitialized during a USB reset (which is what I suspected).
So, why do we always loose the first bit of console output? My test runs with a 1 second delay. The first message is lost, but the second comes through fine. Well, when the first message is sent, it goes into the buffer and the code performs the manipulations to start the transfer on endpoint 9, but it is simply not ready. We still have not finished with setup and enumeration.
Tom's Computer Info / tom@mmto.org