circuitcellar.com
Magazine Support   Digital Library   Products & Services   Suppliers Directory 
 
 





 

Issue 157 August 2003
Mission Possible:
Achieve Cheap USB Connectivity


 

BACK ON TRACK(ER)

If you’re a drag racing fan, you know that most of the real work is done in the pits before the race. The same can be said for working with USB. Before powering up the PICProto USB development board, I reread Jan Axelson’s book, USB Complete: Everything You Need to Develop Custom USB Peripherals. [1] In addition, I perused the Microchip USB documentation and datasheets to get the particulars on the PIC16C765 and PIC16C745 USB microcontrollers. A good collection of USB data comes with Microchip’s PICDEM USB development board.

After working out the initial emulator and compiler bugs, I decided to test run the USB Tracker 110. I used the resulting USB trace in conjunction with Axelson’s book and the USB specification to determine what was needed from a firmware standpoint to be successful with USB. Now, I’ll explain how it went.

Slow-motion photography is often used to study the minute details of a fast-moving event. You can do a similar thing electronically using an emulator like the MPLAB ICE 2000. So, I added a breakpoint to the PicBasic Pro compiler demo USB code to see if I could stop the USB process and examine it up to that point (see Photo 4). The PicBasic Pro compiler only supports three USB BASIC commands: USBINIT, USBIN, and USBOUT. According to Axelson’s book and the USB specifications, three simple USB commands won’t cut it. However, I saw two of those simple little commands wiggle a cursor using a rudimentary PIC circuit and USB. It was time to sip from the Holy Grail.

Photo 4—I wanted to show you the USBInit instruction and the MPLAB ICE 2000 breakpoint. Now you should have an idea of how PicBasic Pro fits inside an MPLAB IDE session. Note that only two PicBasic Pro USB commands are used, USBInit and USBOut.

I inserted the USB Tracker 110 into the loop with the analysis computer at the USB Tracker 110 analyzer tap. The test computer and PICProto USB development board were plugged into the USB Tracker 110’s device under test sockets. According to the PicBasic Pro Basic compiler description, the USBINIT command initializes the USB device and completes when the USB device is configured and enabled. I knew from my reading that the USB device must first enter the powered state and then proceed to the default, addressed, and configured states (in that order) before being able to intelligently communicate with the host. That is called enumeration. But how does the PicBasic Pro USBINIT command do it all?

Behold the screen shot in Photo 5, which is the USB Tracker 110’s view of everything USB that transpired between the test PC and the PICProto USB development board from the time the board was powered up. Wow! Think about what you could do with this information. With the trace, you could correlate the trace data to a corresponding segment of PicBasic Pro source code, and you should be able to investigate the particulars of the USBINIT command. Let’s work through an example. You can follow along using the USB Tracker 110 trace data in Photo 5 and either the original USB specification or USB Complete.

Photo 5—I couldn’t possibly show you everything, so I’ve decided to give you copies of all of my traces. You can view them using the USB Tracker 110 display software, UsbShow.

According to both sources, after a successful initial USB hardware reset sequence, the host PC will issue a GetDescriptor request. At power-up, the PIC-based USB device goes into a powered state with its interrupts enabled. When the PIC is able to execute instructions, the USBINIT macro invokes the InitUSB code that resides in the Microchip-supplied USB_CH9.asm module. When the host sees that the device is powered, it issues a USB reset to the powered device. Looking at the USB trace, the Extended SE0 (26.3 ms) is most likely the USB reset from the host. After starting the USB trace, it took a few seconds to plug in the PICProto USB development board’s USB cable and start the MPLAB ICE 2000 emulator.

The host USB reset then triggers the PIC’s USB reset interrupt, which configures the PIC’s USB address to 0x00 and enables endpoint zero. This collection of zeros is in the default state because every USB device must have an active endpoint zero at that point. In the default state, a USB address has not been assigned by the host, and the host expects to be able to talk to the newly found device at the 0x00 address using the bidirectional endpoint zero. The default state endpoint and device addresses (0x00) are verified in the first GetDescriptor(Device) trace entry.

The first transaction after the forced reset from the host is a set-up transaction aimed at device zero, endpoint zero. As you can see in Photo 6, the USB Tracker 110 and UsbShow trace program are able to show and decode the bit fields inside common USB packets. They also display the raw packet data.

Photo 6—This is a handy feature. Before obtaining a USB Tracker 110, I found myself searching through the pages of the USB specification and Microchip USB source code looking for the tables and declarations that defined the various bit fields.

You can pick out all sorts of details from the packet information provided by the USB Tracker 110 and UsbShow. For instance, in the data packet of the SETUP transaction, the packet identifier (PID) is actually the least significant nibble of the PID. The most significant nibble of every PID is a complement of the PID’s least significant nibble, which, along with a CRC word, helps to ensure data integrity.

In the aforementioned example, the token packet is followed by a data packet, which contains the set-up request information. Axelson says that although the host asks for 64 bytes, it will only read the first 8 bytes because all it really wants is the eighth byte of the device descriptor, which contains the maximum packet size. She’s right.

Axelson’s Carnac-inspired foresight is reinforced by an information message that UsbShow posts for the SETUP transaction. The UsbShow message tells you that the retrieval of less than 64 bytes is not an error and that the host would later ask again for the device descriptor information. Looking ahead in the trace shows you that the entire device descriptor is read in after the device address is established.

Using the ’16C765 and ’16C745 USB micros eliminates a great deal of USB configuration confusion because they’re low-speed devices. Low-speed devices are limited in many ways, one of which is the maximum packet size, which is set at 8 bytes. You can see the 8-byte limit enforced throughout the USB trace.

Moving to the next transaction, the IN transaction pulls the 8 bytes of the 64 bytes of requested data from the PICProto USB development board’s PIC firmware. The host has just enough information and status to grant the PICProto USB development board a USB address. But before knighting the development board, the host wisely resets it to make sure it is in the default state before sending the SetAddress request.

After the SetAddress request is acknowledged, the PICProto USB development board is considered to be in the addressed state. As you can see in the trace, the development board was reset and assigned an address (2). Remember that everything in USB is about the host. So, IN means to the host, and OUT is from the host.

From what you’ve seen thus far, you probably have a good idea of how the rest of the USB enumeration process will flow. Looking at the trace, you can see that device, configuration, and string descriptors are collected from the PICProto USB development board’s firmware as the USB enumeration sequence progresses. The Windows OS assimilates all of the data collected from the PIC and finally sends a SetConfiguration request, which ultimately results in placing the development board in the configured state. After configuration, the development board can pass data to and receive data from the host PC (the test computer).