The challenge of designing a USB interface

If you didn’t think about it, you’d be forgiven for thinking that USB was an acronym for the word ubiquitous (except that the order of the letters is not right; so much for that idea). USB is the preferred peripheral interface for computers, and in fact, more often than not it is the only peripheral interface on a modern computer!

So why is USB so popular? Because it is cheap, robust, compact and easy to use, while offering performance capabilities that suit a broad range of tasks. USB really breathed life into the terms plug-n-play and hot swapping, because with a USB-connected device there’s no need to power everything down or worry about installing and configuring things. You just plug in the USB cable to connect the 2 devices, wait till it has been detected and identified, and start using it.

From data input tasks such as a interfacing a keyboard or mouse, through to data output tasks such as sending data to a printer, through to intensive bi-directional tasks like reading and writing data to an external mass storage device, USB supports them all.

These examples are all based around the personal computer, which is where USB started. Back then the world was simpler (well, at least for a serial interface like USB), where the PC as the command centre (the Host) and all the various attachments were the peripherals.

Time marches on and modern electronic products have become more sophisticated and mature, in both their functionality and behaviour. Now what we crave in our electronic goodies is connectivity – we want those sophisticated products to communicate easily with each other, in an intelligent way.

Take your digital camera. It does a great job of taking pictures, but how do you easily print photos? Do you really need to go through the whole connect-camera-to-PC-to-transfer-then-print process? Not with many cameras and printers, because they can talk directly to each other using a photo transfer standard called PictBridge. With the camera and printer connected via a standard USB cable the printer becomes the Host, supporting the direct transfer of image data from the camera through to the printer.

Capabilities like PictBridge and the newer On-The-Go (OTG) peer-to-peer USB standard can be developed and delivered over a USB cable because USB is such a well structured communications interface. By using a layered protocol, the USB standard allows the mechanical and electrical requirements to be detailed and managed completely independently from the higher-level communications requirements. But this flexibility comes at what cost to the designer?

Stack up the Layers

Like any well architected communications protocol, underlying the USB standard is a well defined set of layers. Broadly speaking, these can be represented as shown in the figure below


The USB communications protocol.

The purpose of layering is to separate out the various elements of the implementation into logical sections, each targeting a specific part of the solution. You can visualize this as each layer providing services to the layer above. How this is achieved does not matter, the higher layer only needs to know how to interact with the layer below.

In the figure above data appears to flow horizontally, directly between the host and the target physical device, on each of the layers. In reality all data flows via the physical cable and hubs. The virtual data flow shows how the management of communications happens on all layers, with each layer only dealing with detail that is managed by that layer. For example, the default control pipe in USB communications is a low-level connection that is established on power up, providing access to the device’s configuration, status and control information. That information is then available to the application software, via the device layer.

By designing in this way, you can write high-level application code that interacts with the 'system', with virtually no knowledge or understanding of how the system actually works. All you need to know is how to configure and communicate with the USB system.

This is only a simple outline of how USB communications works – because you really don’t need to know any more than that! Altium Designer provides both a plug and play FPGA hardware design methodology (called OpenBus), and also a plug and play software design methodology (called the Software Platform Builder), which together greatly simplify the process of designing and implementing something like a USB communications system. There is no need to worry about bus layers, hubs or default control pipes, you’re free to focus on the high-level application code.

Let’s take a look at how you assemble such a system in Altium Designer.

Assembling a Software Platform

In this article we’ll focus on the software side of assembling a USB communications system in Altium Designer. If you’re interested in an introduction on how to assemble an FPGA hardware system using OpenBus, then check out this article.

Meshing beautifully with OpenBus, Altium Designer’s Software Platform Builder allows you to visually assemble all of the low-level hardware wrappers, driver and context code needed for the peripherals used in your design, without you even getting your hands dirty in the low-level code.

There are a couple of excellent USB examples included with Altium Designer:

USB Mouse and Keyboard:
\Examples\Soft Designs\User Interface\USB-Host Mouse And Keyboard\USB-Host_Mouse_And_Keyboard.PrjFpg.
This example shows how to use the USB Host HID (mouse & keyboard) drivers. Keyboard characters and mouse coordinates are displayed on a Terminal Instrument.

USB Mass Storage:
\Examples\Soft Designs\Showcases\NB3000 USB Slideshow\NB3000_USB_Slideshow.PrjFp.
This example shows how to read image files from a USB mass storage device and display them on the NB3000 touchscreen.

Like any software application developed in Altium Designer, the process starts with an embedded project. To this you add a software platform and a C source code file. The complete structure for the FPGA hardware and the embedded software projects for the USB Mouse and Keyboard example is shown in the figure below:


The project structure, showing both the FPGA hardware and the embedded software.

The software platform is then edited to assemble device stacks for each hardware element in the design. Once this has been done you can write your high-level application code in main.c.

Growing the Stack

Since Altium Designer is a unified design environment which understands the relationship between the hardware design inside the FPGA and the embedded code that runs on that hardware, you can start building the lowest level of the software platform directly from the FPGA hardware project by clicking the Import from FPGA button. This adds a hardware wrapper for each hardware element detected in the FPGA design. Hardware wrappers are displayed in green, as shown in the figure below.

From there it is a process of selecting a wrapper and clicking the Grow Stack Up button to add the (orange) driver and (blue) context layers. Note that you can grow the stack to its highest level by immediately selecting the correct Context. The figure below shows the completed platform for the USB Mouse and Keyboard example project, ready to run on the NanoBoard 3000.


Device stacks for the USB mouse and keyboard example.

Once one USB stack has been defined for the Keyboard, the ISP 1760 Interrupt Connect can be Linked to Existing Stack. Since the underlying ISP 1760 USB host controller supports 3 USB ports, the second USB stack required for the pointer device (mouse) is derived by selecting the existing USB Host driver and clicking the Grow Stack Up button, to add the Pointer Services stack. Growing the Terminal Stack completes the software platform.

The address and basic configuration settings for the currently selected stack module are displayed to the right of the Device Stacks. Detailed information about the Software Services delivered by the currently selected module, such as interrupt management and message queues, are configured in the region below the currently selected stack module.

Coding the Application

So you’ve got a software platform and you’re ready to code, but what API’s are available? Click on any context module in the stack, such as the Pointer Context, and press F1. Altium Designer’s Knowledge Center panel will open, displaying information how to interface to the Pointer Services, as shown in the figure below.


Detailed information about software APIs is available in the Knowledge Center panel.

For the sake of brevity, we won’t cover the detail of writing the application code here. To explore the code, build and download the example on your NanoBoard 3000. Once the FPGA has been programmed, open the Terminal Instrument and then click the Download button in the Devices view to launch the application. Keyboard and mouse events will be displayed in the Terminal Instrument, as shown in the figure below.


Here the terminal instrument is being used to display keyboard and mouse events.

Ready to learn more?

If this article has piqued your interest about USB for your next design, then check out the example projects mentioned above. If you’re interested in learning more about Altium Designer’s software platform builder in general, then check out these links:

Introduction to the Software Platform
Getting Started with the Software Platform Builder – a tutorial

To learn more about USB in general, explore these links:
USB in a Nutshell
USB Made Simple
USB fundamentals 101

► October 09 Envision home