C and USB

The firmware code needed to implement USB will be quite similar across platforms.

Following is a great introduction to USB and C that we published in our newsletter

A growing number of microcontroller manufacturers provide USB interface engines as an on-chip peripheral. Here is an overview of the firmware required to communicate via Universal Serial Bus.

The first and most tedious step in implementing a USB application is learning the specification. Visit and download the latest specification and testing utilities.

The three-hundred page specification describes the connectors, cables, host software, firmware, transfer protocols, routing protocols, and other issues. There are also USB Class Definition documents, which contain the class information used to classify a USB device into a specific category.

The microcontroller's USB peripheral handles the more complicated aspects of sending and receiving data. The firmware developer does not have to worry about tedious tasks such as data bit stuffing, CRC checks, and bus manipulations. The developer sees a series of buffers, status flags and interrupt sources used for configuration and notification of USB events. Once configured, the peripheral will send out data marked for delivery and notify the firmware on pertinent USB data transfer events.

The firmware developer is interested mainly in chapter 9 of the specification, the "USB DEVICE FRAMEWORK". This chapter describes the possible USB requests and how to handle them. When the USB device is attached to the system, the host computer requests information from the device. This information is stored in the microcontroller's ROM, occupying approximately 250 bytes. Based on this information, the host computer will reserve USB resources for the device and assign it an address.

A USB device can't initiate a data transfer. It must inform the host of its intentions when it attaches to the bus: this process is called enumeration. The information returned by enumeration comes from the USB peripheral's "Device Descriptor Table", and tells the host computer how often to poll it for information, how much data to expect, and how to interpret this information. The order in which this information is retrieved from the device is not determined by the specification. The USB firmware must be able to determine which information the host is requesting and which function to call to handle this request.

See usb.c for a sample of what this firmware code may look like. This functionality will usually require approximately 150 bytes of code to implement.

This code and the request-handling functions will be very similar across all USB applications. The request-handling functions usually consist of a function that retrieves values from a table and sends it to the host. The GetReport() function (called when the host wants the device's data) will be fairly different across USB devices. For example, information retrieved from a mouse will be quite different from the information retrieved from a keyboard. The GetDescriptor() function of a USB mouse will be identical to the GetDescriptor() function for a USB keyboard, because they will both send the same table to the host. The table will be different but the function to send it out will be the same. The implementation of these standard handling functions requires approximately 200 bytes.