Global Sources
EE Times-India
Stay in touch with EE Times India
EE Times-India > Interface

Designing a USB embedded host controller

Posted: 16 Feb 2004     Print Version  Bookmark and Share


PDF document

By Mark Schultz

Sr. Applications Engineer

Cypress Semiconductor Corp.

USB has historically been avail-


untapped potential in the area

of embedded systems. USB ap-


include keyboard-video-mouse

switches, digital cameras,

PDAs, printers, STBs and


What is an embedded sys-

tem? An embedded system is

defined as a hardware and firm-

ware--either standalone or part

of a larger system--usually with

some sort of an OS. The OS can

be Windows CE, VxWorks or a

simpler system consisting of

"home-made code." Using the

above definition, it can be said

that any electronic device that

has a processor has the poten-

tial to be an embedded USB


Design challenges

In a PC-based system, there are

three major components re-

quired for the USB operation.

They are the host controller,

which is usually part of the PCI

subsystem, the USB stack and

the USB class drivers.


the integrated motherboard

chipset. The USB stack in-

cludes drivers for the silicon on

the motherboard as well as the

universal host controller inter-


ler interface (OHCI) and USB

driver. PC-based implementa-

tion of USB requires expertise

in all of the above areas.



lar to that of a PC-based system.

The components include an

embedded host controller sili-

con, a real-time operating

system (RTOS) with an OHCI

stack and the application-

specific drivers.

There are a number of

choices for the host controller

silicon--some with processors,

some register-based. The

choice of component will affect

the next two layers.

RTOSes are available from a

number of vendors. The best

method is to select a processor

and RTOS that work together,

then, add the application code

on top of that. In the absence of

a true RTOS, some controllers

come with "frameworks" upon

which an application can be



a PC, there are an abundance of

resources already available.

These include up to 512MB of

memory, a 20GB to 60GB hard

drive and a 2GHz or faster

microprocessor. In addition,

OS such as Windows, MAC OS

and Unix have long been sup-

porting USB. There are hun-

dreds, if not thousands, of engi-

neers worldwide designing PC-

based USB applications and

device drivers.

Embedded systems, on the

other hand, have typically less

than 64K of memory--no hard

drive and processor run in the

12MHz to 33MHz range. As

USB is relatively new to embed-

ded systems, there are likely to

be only a handful of engineers

with experience in this area.

The Cypress EZ-Host de-

vice has two serial interface en-

gines (SIE), each containing

two USB ports. Therefore, the

Designing a USB embedded host controller

EZ-Host can control up to four

USB devices with no additional


The EZ-Host device in-

cludes a firmware framework

that takes care of most of the

USB host details. Another fea-

ture of the framework is hub

support. The question often

comes up pertaining to key-

board/hub combos: Is it a key-

board with a hub or is it a hub

with a keyboard? The answer is

that it is a hub with a keyboard.

So, to see the keyboard that is

behind the hub, you need to

have hub support. Fortunately,

the framework code includes

support for hubs.

The following sections will

introduce frameworks and

show some examples of its op-

eration and how to interface

application code to it.

Frameworks overview

The EZ-Host framework con-

tains all of the necessary firm-

ware to implement USB host

functionality, such as schedul-

ing, device enumeration, band-

width allocation and power


Applications, on the other

hand, are the firmware to con-

trol specific USB devices and

Control read transfer

Setup stage

Data stage


Status stage

Data phase



0 Length data/


Token phase




Handshake phase




Figure 1: TD processor handles USB transfer. To perform a control transfer, use the framework function send_request( ).

URB *send_request ( USB_DEVICE *dev, uint16 endpoint, uint16 direction,

uint16 req_tyoe, uint16 request, uint16 wValue,

uint16 wIndex, uint16 wLength, PFNURBCALLBACK callback )


URB *urb;

urb = alloc_URB ( TRUE, wLength );

if ( urb ! = 0 )


USB_DEVICE_REQUEST *req = (USB_DEVICE_REQUEST *) urb->setup_packet;

req->bmRequestTypw = req_type;

req->bRequest = request;

req->wValue = wValue;

req->wIndex = wIndex;

req->wLenght = wLength;

urb->dev = dev;

urb->dir = direction;

urb->usb_dev_addr = dev->address;

urb->endpoint = endpoint;

urb->speed = dev->speed;


urb->buffer_length = wLength;

urb->callback = callback;

if ( td_submit_URB ( urb ) ! = SUCCESS )


release_URB ( urb );

urb = 0;





DBGLOC ( TRC_host_sent_request, 0xe001 );

SYS_ERROR( "not enough URBs\n" );

#ifdef DEBUG


#endif /* DEBUG */


return urb;


/* pointer to associated USB device */

/* in or out end point */

/* device_address */

/* end point number */

/* high or low speed */

/* end point type. iso, intr, control, bulk */

/* callback for UR3 completion */

Figure 2: The TD processor transfers program control to the "callback" function specified

in the send_request( ) function.

communicate their data to an

end application.

At the heart of the frame-

works is the task descriptor


sor operates on a data structure

using its information to com-

municate with the USB hard-

ware, specifically the SIE. It is

important to note that each of


that there is a TD processor for

each SIE.

The EZ-Host framework in-

corporates a number of data

structures for its operation.

These structures include TDs


TD is the data structure that

is passed to the hardware. It in-


hardware interface, such as the

SIE and port number, endpoint

number, length of the data

buffer to be sent or received,

packet ID code and a pointer to

a URB structure.

URBs include the logical in-

formation required by the

TD. This includes the USB de-

vice buffer, setup packet and

a pointer to a USB device


When a USB transaction is

to take place, a URB containing

information about the transac-

tion is allocated and the data

structures are filled in. The

URB is then submitted to the

TD processor. The TD proces-

sor then adds the URB to a TD

list. During idle time, the TD

list is processed, transfers are

scheduled, and the scheduled

TDs are passed to the EZ-Host

hardware for processing.

Figure 1 shows a basic USB

control transfer. This diagram

will be used for the ensuing ex-

ample of how the TD processor

handles a USB transfer.

To perform a control trans-

fer, you can use the frame-

work function send_request(),

which will allocate a URB

structure to be passed on to the

TD processor.

Information about the setup

phase needs to be included in

the URB and will be passed to


The URB will need the follow-

ing information:

7 Requesttype--Bytesignifying

the type of USB request. This

byte contains bits denoting

transfer direction, transfer

type and transfer recipient.

7 Request--One of the 11 stan-



descriptor, get_interface,

get_status, set_address,

set_configuration, set_de-

scriptor, set_feature, set_in-

terface, synch_frame.

7 Value--Requestspecificfield.

7 Index--Requestspecificfield.

7 Length--Size of the associ-

ated data buffer.

Once the setup information

has been filled in for the URB,

fill in the rest of the device in-

formation in the URB such as

address, speed, endpoint num-

ber and transfer direction.

There is also a byte for the

transfer type and a pointer to a

callback function. The use of

callback functions allows for

some concurrency within the

frameworks so other tasks can

be performed while the hard-

ware is handling the USB trans-

action. The USB transfer type

information is required by the

TD in order for the frameworks

to schedule the correct type of

transfer. As opposed to bulk or

interrupt transfers, the frame-

works will only allow for one

control transfer at a time.


tion is filled in, the URB is sub-


TD processor is the part of the

framework that communicates

directly with the hardware and

takes care of the low-level de-

tails of the transfer. When the

TD has completed its task, the

TD processor will transfer pro-

gram control to the callback

function specified in the origi-

nal call to the send_request( )


Figure 3 shows a call to

send_request( ) along with a

callback function. In this ex-

ample, we are using a control

transfer to obtain the country

code of a keyboard. In the

get_country_code( ) function,


seen. Note that the last param-


is the callback function. This

function will be executed after

the TD processor has deter-

mined that the hardware has

completed this transaction. In

this case, the callback function


typecast it to an HID descriptor




be free.

One final feature of the EZ-

Host framework that is worth

noting is the use of device driv-

ers. For this implementation, a


functions: stop, start and run.

When a device driver is started,

its run( ) function is executed.

This function initializes some


URB that will be used for trans-

fer of data. In the case of a

mouse or keyboard, this URB

will occur every 10ms. When a

data transfer has completed,

the TD processor will transfer

control to interrupt_in_com-

plete( ) function. By inspection

of the URB, it is possible to tell

whether this data came from a

keyboard or a mouse device.

This callback function is re-

sponsible for sending the key-

board or mouse data to the ap-

plication layer.

When a driver is stopped,

its recurring URB is removed

from the TD list and then de-

allocated. Additionally, a mes-

sage is sent to the application

layer that the associated device

has been removed. If the device

associated with the stopped

driver is a hub, any device at-

tached to that hub is also re-


If any of those removed devices

is a hub, then the devices con-

nected to the hub will be re-

moved in the same way.

During a driver's run func-

tion, various tasks can take

place. In the case of the device

driver for a hub, the hub ports

are checked for insertion and

removal of devices. The run

function for the keyboard and

mouse drivers does nothing.

Framework flow

The framework code will ex-

ecute as follows. On power-on

reset, the microprocessor will


/* GetCountryCode */


void GetCountryCode (USB_DEVICE *dev)


URB *urb;

urb = send_request (dev, EPO, TD_CTRL_DIR_IN, 0x8, USB_GET_DESCRIPTOR_REQUEST,

0X2100, 0 0X9 (PFNURCALLBACK) req_complete);



/* req_complete */

/* */

/* description: callback function for the GetCountryCode control transfer */

/* */


void req_complete(URB* urb)



if (urb->status == 0


memcpy (&HidDesc, urb->transfer_buffer, urb->actual_length);

CountryCode = HidDesc .bCountryCode;




SendErr (8);


release_URB (urb);


Figure 3: Calling and callback functions.

initialize all registers, counters

and device structures. It will

then enter a loop that will ex-

ecute as follows:

1. Check the host USB ports for


inserted or removed).

2. Check the TD processor and

get status of all TDs running

on the two SIEs.

3. Go through the list of active

device drivers and execute

the run function for each.

Checking the host USB port

for status changes requires in-

spection of a change variable.

This variable will be set by the

port change interrupt handler

if a change occurs. If the port

shows a change, enumeration

code will be executed to service

this change.

Checking the attached hubs

for change values is accom-

plished via an interrupt trans-

fer from the hub to the host. If

devices are added or removed,

they will be enumerated as

with the previous case. When

a new device is found, its de-

vice driver needs to be

matched and then loaded.

Matching the driver to the de-

vice can occur in a number of

ways. Framework code will

first attempt to match a driver

to a device's vendor and prod-

uct ID. This technique will

only work if there is one spe-

cific manufacturer and device

to be run with a specific driver.

If no match is found, the

framework code will then try

to match by the device's class

and subclass. This allows for

more generic driver-to-device


There are two additional

tasks to go along with checking

for insertion and removal of

devices. If an attached device

is a hub, then its ports must be

checked to see if they also con-

tain devices. If a removed de-

vice is a hub, then all devices

attached to it must also be


Checking for new data from

attached keyboard and mouse


rupt transfer. These transfers


scheduled by the TD processor.

When complete, the TD pro-

cessor will transfer control to

Figure 4: Interrupt transfer callback function.

the callback function for these


board or mouse data can be ex-

tracted and sent to the applica-

tion layer.

Building an application

This section shows how to build

a simple embedded USB design

that controls a keyboard and a


This implementation uses a

processor-based USB host con-

troller. Code for the processor

will include the frameworks

and the application firmware.

The first thing to do is to deter-

mine how many and what types


port. When the number of de-

vices is determined, you can al-

locate the URBs and driver


tion is done via the modifica-

tion of a "personality" file

called fwxcfg.h.

Every keyboard, mouse or

hub will require one URB to

handle its recurring interrupt

in transfer. Additionally, URBs

are allocated and subsequently

released during enumeration

and other USB control trans-


/* */

/* interrupt_in_complete */

/* */

/* This function is called when we have received data on the interrupt in */

/* pipe on SIE1 from the keyboard or mouse */

/* */


static void interrupt_in_complete ( URB *urb )


if ( urb->status == SUCCESS )


/* ********** Process the HID report here. ********** */

/* check protocol field to determind whether if data is from a kybd */

if ( (urb->dev->inf_descr.bInterfaceProtocol ) == KEYBOARD_PROTOCOL)


if ( KybdChgd (urb->transfer_buffer) )


SendKybdReport (urb);



else if ( (urb->dev->inf_descr.bInterfaceProtocol) == MOUSE_PROTOCOL)


SendMouseReport (urb);





/* We need to resubmit this URE to the TD processor.

* Keep in mind that it is still on our active list.


resubmit t_urb; ( urb );

DBGLOG ( TRC_de3_intr_complete_5, 0XEE03 ) ;




fers. A good rule of thumb is to

allocate two URBs for each de-

vice supported by the system.

One of the allocated URBs will


transfer. The other will be for

any possible control transfers

that could occur during enu-

meration or device status

checking. Even though only

one control transfer can be pro-

cessed at a time, it is possible

for the frameworks to queue up


ber of supported URBs should

equal the number of supported

devices times two.

Next, you will need to create

a driver for the keyboards and

mice. Since these devices are

close in their USB functional-

ity, the same driver can be used

for both. You can call the driver

the hid_driver (human inter-

face device driver). The next

steps are to add the start, stop

and run functions and class

codes for the device. You will

also need to add the name of

the driver function to the file

drvrlist.h. The driver declara-

tion, including the hub and hid

drivers, will look like this:




The hid_driver start func-

tion will allocate a recurring

interrupt in transfer to get key-

board and mouse data. Code

inside of this function will get

the data and pass it on to the

application layer of the code.

The stop function will release


and notify the application layer



check for any incoming com-

mands from the application


Next, you will need to add

some code to the enumeration

notify functions. Enumeration

notify functions are callback

functions used by the enumera-

tion code to report the status of


to handle any possible enu-

meration errors. This code will

be used to pass information

about the newly enumerated

device to the application layer.

Hub support is easy here.

You do not have to add any code

nor write a driver since the

frameworks already includes a

driver. All that is needed is to

change the line in fwxcfg.h





#define FWX_INCLUDE_



project makefile. The frame-

works will take care of the rest.

Despite the disadvantage in

computing resources and expe-

rience with a USB host system

as compared to a PC, develop-


their embedded system quite

simply. There are a number of

available USB host ICs which

can be used to implement this

functionality. USB host stacks

and RTOS can either be pur-

chased or developed.

This article has demon-

strated the implementation of

an embedded USB host using

only one additional IC and no


ded USB host frameworks has

taken care of all of the lower

level details. Cypress' EZ-Host

USB host can support HID de-

vices and hubs with no addi-


rently capable of supporting up


hubs. More devices and levels

are easily achieved. The present

code size is approximately

22KB. All that needs to be done

is add the application-specific

code for a full system.

Comment on "Designing a USB embedded host contro..."
*  You can enter [0] more charecters.
*Verify code:


Visit Asia Webinars to learn about the latest in technology and get practical design tips.


Go to top             Connect on Facebook      Follow us on Twitter      Follow us on Orkut

Back to Top