November 4, 2023

Let's learn USB! -- Papoon - a look inside

We have already pointed out that what I am using from papoon totals up to 7070 lines of C++ code. It is broken down like so:
[tom@trona papoon]$ wc -l *.cxx
   88 example.cxx
  210 usb_dev_cdc_acm.cxx
  880 usb_dev.cxx
   91 usb_mcu_init.cxx
 1269 total

[tom@trona papoon]$ wc -l *.hxx
   143 bin_to_hex.hxx
   181 core_cm3.hxx
    49 papoon.hxx
  1013 regbits.hxx
  2929 stm32f103xb.hxx
   752 stm32f103xb_tim.hxx
    94 usb_dev_cdc_acm.hxx
   675 usb_dev.hxx
    31 usb_mcu_init.hxx
  5867 total
I find it surprising that about 3/4 of the source code is in header files. I may have more to say about this once we take this file by file. Of particular interest is the gigantic stm32f103xb.hxx. This file, in conjunction with regbits.hxx set up a scheme for dealing with hardware unlike anything I have ever seen before. All this seems to be the invention of Mark Rubin, and he explains it in these documents:

I had expected the size of these files to be dominated by USB boilerplate and declarations, but this does not seem to be the case.

I am curious about "const" variables in these header files

In particular, I see things like this in stm32f103xb.hxx --
static const uint32_t   PERIPH_BASE         = 0x40000000U;

static const uint32_t   APB1PERIPH_BASE     = PERIPH_BASE              ,
                        APB2PERIPH_BASE     = PERIPH_BASE + 0x00010000U,
                        AHBPERIPH_BASE      = PERIPH_BASE + 0x00020000U;
It would seem to me (naive C programmer that I am) that if this header file was to be included in several files, the static variable would be duplicated in each location.
An experiment is in order. This header is included in two places. It is included in example.cxx (unnecessarily) and in usb_mcu_init.cxx

I select the first value and put printf statement into usb_mcu_init.cxx

TJT PERIPH_BASE = 40000000
TJT (addr) PERIPH_BASE = 08001D30
This is nice. That address is in flash where we would like it to be. It is safe to assume that the other three are there also. This would not be legal in C (initializing a variable, constant or otherwise from the value of another variable). Apparently C++ is smart enough to realize these are constant values and can be evaluated at compile time. And if they were not, C++ would generate some code that would run "pre-main" -- something for which my framework is not prepared and apparently Mr. Rubin has taken some pains to avoid.

Where I want to go next

The "example" demo calls usb_dev.poll() in a hard loop, calling usb_dev.recv() to check for input. What I would like to do is: This reorganization would allow the USB system to be initialized and not be tying up the processor polling, thus making it useful as a console to support other uses.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org