I ran into a curious problem. When my code booted, I initialized Papoon then went into a loop watching for a state variable to indicate CONFIGURED. I set that loop up with a 9 second timeout. So it waits 9 seconds, nothing happens and the loop exits. I ignore the status and try to run my demo (wich waits for received characters and echos them). Nothing is going to be received since we have not enumerated.
But the whole papoon structure is interrupt driven. I unplug and replug the cable. Now linux knows something needs attention and it tries to enumerate. The enumeration fails because of my printf() messages screwing up the timing. If I disable (again) my messages, the first wait does timeout, but then the enumeration works just fine later, being state driven.
Enumeration takes about 6 full seconds. This is measured with a stopwatch from when I plug in the cable to when it announces that the device is configured.
All of this suggests at least two code changes. One is that I could (should?) check that state variable and not jump into the demo if (and/or until) it is "CONFIGURED". Another is to track down where that state is set and switch on debug only when the state transitions to "CONFIGURED". I could even consider setting up a callback to notify me when enumeration finishes (not to mention, when it starts).
Does the "send()" method try to send data if the device is not configured. The demo would never do this (it tries to receive data before it sends anything).
But in some sense, we are getting ahead of ourselves. We want to find a way to study enumeration without having our messages screw it up. Here is the first part of a log from a failed enumeration:
USB lp interrupt 1 IH: usb reset USB lp interrupt 2 CTR - control 00008210 USB lp interrupt 3 CTR - control 00008200 USB lp interrupt 4 CTR - control 00008210 USB lp interrupt 5 IH: usb reset USB lp interrupt 6 CTR - control 00008210 USB lp interrupt 7 CTR - control 00008200 USB lp interrupt 8 CTR - control 00008210 USB lp interrupt 9 CTR - control 00008200 USB lp interrupt 10 CTR - control 00008210 USB lp interrupt 11 IH: usb resetWhen I first enter the interrupt handler, I print the "USB lp" message and show a count of how many interrupts this is. Then the "IH" message comes from inside the interrupt handler in papoon. We either get a "usb reset" or a "CTR" at this stage. CTR indicates "correct transfer" and may indicate either a packet received or that a packet has been successfully sent. The word "control" indicates that this is endpoint 0 (the "control" endpoint). The control endpoint will be used for all traffic dealingwith enumeration. I then show the "istr" register (the interrupt status), which is a 16 bit register.
0x8000 is the bit that tells us this is a CTR interrupt, so no surprise there.
0x0200 is SOF (start of frame). We don't enable this interrupt and I am not sure why
we might want to, so we can ignore this.
0x0010 is the DIR bit and the 4 bits following are the endpoint number (zero).
DIR tells us if we have data coming or going.
DIR = 1 is an OUT transaction (data from the host to us).
DIR = 0 is an IN transaction (data from us to the host).
Also notice the resets. For whatever reason, enumeration asks for several USB resets. These are accomplished by pulsing the FRES bit ("force reset") in the CNTL register for 100 ms. Enumeration starts with a reset, which sort of makes sense, followed by the host sending us something. To learn more we need to look at packet memory and the endpoint registers.
Packet memory (PMA) is a bunch of 16 bit words on a 32 bit bus. So even though there is 512 bytes of actual SRAM involved, it uses 1024 bytes of address space. When I write a 32 bit value like 0xdeadbeef to PMA from the ARM, the value 0x0000beef gets stored.
Here is what PMA looks like after papoon is initialized and before there is any traffic:
EPR-0 = 00003210 EPR-1 = 00000622 PMA 00000000: 0180 0040 01C0 8400 0178 0000 0000 0000 PMA 00000010: 0000 0000 0138 8400 00F8 0000 0000 0000
And here is what we have once the first packet has arrived:
EPR-0 = 0000EA60 EPR-1 = 00000622 PMA 00000000: 0180 0040 01C0 8408 0178 0000 0000 0000 PMA 00000010: 0000 0000 0138 8400 00F8 0000 0000 0000 PMA 00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ... PMA 000001B0: 0000 0000 0000 0000 0000 0000 0000 0000 PMA 000001C0: 0680 0100 0000 0040 DDDD 0000 0000 0000 PMA 000001D0: 0000 0000 0000 0000 0000 0000 0000 0000
And when papoon sends the first response:
EPR-0 = 000062A0 EPR-1 = 00000622 PMA 00000000: 0180 0012 01C0 8400 0178 0000 0000 0000 PMA 00000010: 0000 0000 0138 8400 00F8 0000 0000 0000 PMA 00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ... PMA 00000170: 0000 0000 0000 0000 0000 0000 0000 0000 PMA 00000180: 0112 0200 0002 4000 0483 5740 0200 0201 PMA 00000190: 0103 0000 0000 0000 0000 0000 0000 0000 PMA 000001A0: 0000 0000 0000 0000 0000 0000 0000 0000 PMA 000001B0: 0000 0000 0000 0000 0000 0000 0000 0000 PMA 000001C0: 0680 0100 0000 0040 DDDD 0000 0000 0000 PMA 000001D0: 0000 0000 0000 0000 0000 0000 0000 0000The first part of PMA holds the BTABLE. For us only the first 4 words are of interest -- for now. These describe the buffers for endpoint 0 (the control endpoint), as follows:
Addr--Tx = 0180 Count-Tx = 0040 (then 0012) ADDR--RX = 01c0 Count-Rx = 8400 (then 8408)So we first receive 8 bytes as follows:
PMA 000001C0: 0680 0100 0000 0040 DDDD 0000 0000 0000Then we respond with 0x12 bytes like so:
PMA 00000180: 0112 0200 0002 4000 0483 5740 0200 0201 PMA 00000190: 0103 0000 0000 0000 0000 0000 0000 0000After this we receive something else, then a reset, but we will look into that later.
What does all of this mean? The datasheet explains part of it, but for the contents of the packets we will need to go to the USB documents, along with studying the source code!
Before we examine packet contents, we should see what the data sheet tells us about the values in the endpoint register for endpoint 0, as well as the PMA values as well. We see the following values for our endpoint register:
EPR-0 = 00003210 EPR-0 = 0000EA60 EPR-0 = 000062A0There is plenty of information here, but nothing worth describing in detail.
And here are the corresponding values for the BTABLE entry for endpoint 0
PMA 00000000: 0180 0040 01C0 8400 PMA 00000000: 0180 0040 01C0 8408 PMA 00000000: 0180 0012 01C0 8400Here 0x180 is the location of the Tx buffer and 0x1c0 is the location of the Rx buffer. The Tx counts give us no surprises, other than being initialized to 0x40 (64). The Rx count field holds some extra information in the upper 6 bits. The 0x8000 bit indicates that the block size is given in 32 byte "units". The next 5 bits give the size (here the value is "2"). So we have 2 "units" of 32 bytes, so a 64 byte Rx buffer size.
PMA 000001C0: 0680 0100 0000 0040 DDDD 0000 0000 0000I am not yet able to decypher the source code, so I am using this: This is a setup packet. There are definite time limits about how quickly this must be responded to (50ms if there is no "data stage" and 500ms otherwise). Setup packets are 8 bytes in size. The fields are:
Request Type (1 byte) = 80 Request (1 byte) = 06 get descriptor Value (2 bytes) = 0001 ?? Index (2 bytes) = 0 Length (2 bytes) = 0x40 = 64 ??
PMA 00000180: 0112 0200 0002 4000 0483 5740 0200 0201 PMA 00000190: 0103This is a descriptor. The first byte gives the length (here 0x12) which clearly includes the length byte itself. The next byte (0x01) indicates this is a device descriptor.
Here is a device descriptor:
Length (1 byte) = 0x12 Type (1 byte) = 0x01 device bcdUSB (2 byte) = 0x0002 USB 2.0 class (1 byte) = 2 subclass (1 byte) = 0 protocol (1 byte) = 0 max pkt (1 byte) = 0x40 = 64 vendor (2 byte) = 0x0483 product (2 byte) = 0x5740 release (2 byte) = 0x0200 version 2.00 (bcd) iManuf (1 byte) = 01 iProd (1 byte) = 02 iSer (1 byte) = 03 iConf (1 byte) = 01The linux messages when enumeration succeeds are:
Nov 6 12:53:55 trona kernel: usb 4-1.2: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00 Nov 6 12:53:55 trona kernel: usb 4-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 Nov 6 12:53:55 trona kernel: usb 4-1.2: Product: STM32 Virtual COM Port Nov 6 12:53:55 trona kernel: usb 4-1.2: Manufacturer: STMicroelectronics Nov 6 12:53:55 trona kernel: usb 4-1.2: SerialNumber: 8717472853518850066fff48
Tom's Computer Info / tom@mmto.org