The next step is to get it working using interrupts. This will make it possible to use it for real purposes rather than tying up the processor polling. I leave the working code with polling behind intacts and begin a new project:
I am doing things like setting the Nvic interrupts from my C code. As I add things It is an interesting choice whether to add the the Papoon C++ code or my own C code. My general tendency is to do as much on the C side as possible.C++ is not so bad! I don't intend to start working with it, but it is pretty easy to get the feel for his "regbits" scheme and see when he is accessing device registers and how.
USB has 3 interrupt vectors allocated to it. I added handlers for all 3 and put printf statements in them so I could learn when they get called. Only one of the 3 ever gets called (namely "lp"). The three are "hp", "lp" and "wk". The last ("wk" for wakeup) should never get called. It expects some kind of wakeup circuit to be set up using a EXTI interrupt (i.e. a configured gpio line if I understand it right). But I will announce if one ever comes along.
The names "hp" and "lp" are entirely confusing and undocumented (as near as I can tell). In situations where documentation fails, experimentation is the only recourse. Does "hp" means high power? Maybe it means "high priority". We may never know. Also note that these vectors are labeled "usb_lp_can_rx0" and "usb_hp_can_tx". My take on this is that the rx0 and tx business pertains to can and we can ignore that. We get a "lp" interrupt for both receive and transmit events for USB. USB and CAN share resources (both interrupts and packet memory) and cannot be used at the same time. Not that I care -- I never intend to use CAN.
When I first tried running the interrupt code, it did not work (it failed to enumerate). I had printf statements in each interrupt handlers. When I commented these out, it would work. I have seen this kind of thing before. It takes time to send characters over a serial line, and printing messages from inside the interrupt routine, while informative, either upset timing, or caused interrupts to be missed.
So what I did was to add a debug flag to prevent printout until enumeration was finished. After adding sufficient delay, I got this to work. So now I have interrupt driven USB with debug after enumeration finishes. This leaves two steps next:
I am also tempted to begin migrating code out of the C++ world. There is code for the Nvic in papoon, but it never gets used, so I might as well delete it. Also there is code for the Rcc to set up the 48 Mhz USB clock. I should migrate this, then delete that from papoon. Why do this? It is not that I hate C++ (well I do, but that is not why I want to move the code in this case). The point is that the fewer "distractions" I have in the papoon code, the easier it is to study it.
Also a quick comment on TinyUSB. I abandoned it because it did not offer a quick path to running code on the F103. It may well be worth revisiting once I have a low level USB driver that I am happy with. USB code can be partitioned (like network code) into a portable upper part, and a hardware specific lower part. TinyUSB could be a source for the portable upper part. I have not yet looked at the coding style and such to evaluate whether this would be a good choice. In addition, a serial port is all that I am looking for from USB, at least thus far. Here are two comments on the serial port as provided by papoon:
Tom's Computer Info / tom@mmto.org