Tech Articles

ULPI interface

 

Tips for creating a FPGA ULPI USB interface.

 

There are a number of USB PHYs that have a UTMI+ Low Pin Interface (ULPI) interface that are readily interfaced to an FPGA.  Incidentally ULPI is an acronym within an acronym within a further acronym, where UTMI+ stands for USB 2.0 Transceiver Macrocell Interface and USB is short for the ubiquitous Universal Serial Bus.

 

There are two reference documents that are essential to understanding this interface and its quirks.

 

The first: Universal Serial Bus Specification Revision 2.0 that can be obtained from http://www.usb.org/developers/docs/usb20_docs/

 

And the second: UTMI+ Low Pin Interface Specification, Revision 1.1 from

http://www.ulpi.org/documents.html

 

Since we later discuss a memory stick so this article outlines a command used in this article.

USB Mass Storage Class – Bulk Only Transport 1.0 and can be found at

http://www.usb.org/developers/devclass_docs/

 

This link also outlines other classes.

 

The USB 2.0 interface is capable of 3 speeds:

HS (High Speed) - 480 Mbps

FS (Full Speed) - 12 Mbps and

LS (Low Speed) - 1.5 Mbps

The use of High Speed and Full Speed is perhaps unfortunate and can catch out the unwary.

 

It is useful to be reminded that any interface claiming conformance USB 2.0 does not necessarily mean that such an interface automatically is capable of running at High Speed (480 Mbs).  It is merely a refinement of a standard that includes Low, Fast and now High Speed USB interfaces.

 

The ULPI interface corresponds to the following pins:

 

nRESET

I

CFG

I

DIR

O

NXT

O

STP

I

CS

I

DATA[7:0]

I/O

 

The ULPI/USB device must be initialised. We have chosen a TI TUSB1210 where a low signal applied to nRESET will set the internal registers to their default values. nRESET must be applied for a minimum of 200ns.

 

The PHY has a number of internal registers associated with various modes and interface speeds. We need only worry about two of the registers if we intend to setup the PHY as a peripheral.

 

The following diagram illustrates a write to a register:

 

 

Figure 1 TXCMD register write

       

And the following a read from a register:

 

 

Figure 2 Register Read

 

A TXCMD byte must be sent preceding any data or write to a register according to the table below.

 

Transmit command byte (TX CMD)

Byte Name

Command Code data(7:6)

Command Payload data(5:0)

Command Description

Special

00b

 

000000b

(NOOP)

 

No operation. 00h is the idle value of the data bus. The Link drives NOOP by default.  

XXXXXXb

(RSVD)

 

 

Reserved command space. Values other than those above will give undefined behaviour.

Transmit

01b

000000b

(NOPID)

 

Transmit USB data that does not have a PID, such as chirp and resume signalling. The PHY starts transmitting on the USB beginning with the next data byte.

00XXXXb

(PID)

 

Transmit USB packet. data(3:0) indicates USB packet identifier PID(3:0).

XXXXXXb

(RSVD)

 

Reserved Command space. Values other than those above will give undefined behaviour.

RegWrite

10b

101111b

(EXTW)

 

Extended register write command. 8-bit address available in the next cycle.

XXXXXXb

(REGW)

 

Register write command with 6-bit immediate address.

RegRead

11b

101111b

(EXTR)

 

Extended register read command. 8-bit address available in the next cycle.

 

 

XXXXXXb

(REGR)

 

 

 

Register read command with 6-bit immediate address.

 

 

When the DIR signal is asserted and the NXT signal stays low a RXCMD byte is received that generally represents the PHY status.  This is useful to determine the state of the D- and D+ lines to determine if the peripheral has been connected to a host.

 

 

Receive Command Byte (RX CMD)

data

Name

Description and Value

1:0

LineState

UTMI+ LineState signals.

data(0) = LineState(0) (DP)

data(1) = LineState(1) (DM)

3:2

 

Vbus State

 

Encoded Vbus Voltage state

Value

VBUS Voltage

SessEnd

SessValid

VbusValid

00

VBUS < VB_SESS_END

1

0

0

01

VB_SESS_END ≤ VBUS < VSESS_VLD

0

0

0

10

VSESS_VLD ≤ VBUS < VA_VBUS_VLD

X

1

0

11

VA_VBUS_VLD ≤ VBUS

X

X

1

5:4

RxEvent

Encoded UTMI event signals       

Value

RxActive

Rx Error

HostDisconnect

00

0

0

0

01

1

0

0

11

1

1

0

10

X

X

1

6

ID

Set to the value of IdGnd (UTMI+ IdDig). Valid 50ms after IdPullup is set to 1b.

7

Alt_int

Asserted when a non-USB interrupt occurs. This bit must be set when an unmasked event occurs on any bit in the Carkit Interrupt Latch register. The Link must read the Carkit Interrupt Latch register to determine the source of the interrupt.

 

 

These are the signals we should expect after reset has been released on the PHY

 

 

 

 

Figure 3- ULPI signals after reset

 

One significant aspect of reset is the toggling of DIR and a receipt of a RXCMD byte from the PHY.  Once that is detected then we may move forward. The IDLE state is where the Link places 0x00 onto the Data lines. We use a registered DIR signal (so that it is delayed by one clock) as an enable for the driving of data from the FPGA.

 

We must then initialise the peripheral.  High-speed capable devices initially attach as full-speed devices where DP is pulled up to Vbus through a 1.5k resistor.

 

 

Line State is decoded as follows in LS and FS modes:

LineState[1:0]

DP (D+)

DM (D-)

State

00

SE0

0

0

USB Reset

01

J (FS idle)

1

0

J State

10

K (LS idle)

0

1

K State

11

SE1

1

1

SE1

 

Line State is decoded as follows in HS mode:

LineState[1:0]

DP (D+)

DM (D-)

State

00

SE0

0

0

HS Squelch asserted

01

J

1

0

HS Squelch de-asserted

10

K

0

1

Invalid State

11

SE1

1

1

Invalid State

 

In HS Chirp state:

LineState[1:0]

DP (D+)

DM (D-)

State

00

SE0

0

0

HS Squelch asserted

01

J

1

0

HS Squelch de-asserted and HS receiver = 1

10

K

0

1

HS Squelch de-asserted and HS receiver = 0

11

SE1

1

1

Invalid State

 

The lesser bit LineState[0] represent DP (D+), and LineState[1] represent DM (D-).

 

The sequence of events:

Apply reset for more than 200ns.  The PHY will pull DIR high to ensure the Link will not drive data lines.

Wait for DIR to go low.

Wait for a RXCMD, ie a toggle of the DIR pin.

 

The peripheral must start as a FS device by pulling DP high through an internal resister controlled by FUNC_CTRL register. First we must disable OTG features by writing x”00” to the OTG_CTRL (x”0a) register.  A TXCMD byte of x”8a” is sent then a data byte of x”00” as per Figure 1.

 

Send x”45” to FUNC_CTRL (x”04”) where this sets the peripheral device in the Fast Speed mode by making D+ high and D- low ( LineState “01” – J).

 

The PHY should respond with a RXCMD showing a LineState of J (“01”, FS Idle).

 

 

 

Attaching peripheral to the host

 

An outline of the High Speed initialisation and handshake process is shown in Figure 4

 

  1. 1If the peripheral is attached to the Host, or now becomes attached to the Host, the Host should wait 100 ms for a stable LineState of “01” and then drive both D+ and D- low. This is the SE0 level and the PHY should produce a RXCMD to confirm a LineState  SE0 (“00”).. 

 

  1. 2In order to signal to the Host the peripheral is capable of High Speed the device must signal a “K” (a LineState of “10”) chirp for a minimum of 1.0ms by writing x”54” to FUNC_CTRL (x”04”), then writing a NOPID TXCMD and data of x”00”. After, say 1.5ms, we drive STP to a “1” for a single clock to end the chirp. 

 

  1. 3The Host then sends a sequence of alternating J and K signals and once the peripheral detects these J and K signals it can then set the PHY to receive and transmit High Speed serial data. 

 

  1. 4This can be accomplished by writing x”41” to FUNC_CTRL (x”04”). 

 

  1. 5We have a peripheral in HS mode. 

 

An excerpt from the UTMI document is below to describe the initialisation process.

 

Hi-Speed Detection Handshake (Chirp)

Hi-Speed Detection Handshake, or Chirp, is shown below though not to scale, and not all RX CMD updates are shown. Bus turnaround cycles are also not shown, and must occur for one cycle after every assertion and de-assertion of dir. The following sequence of events must be followed.

1. FS/LS Detect – The host detects a peripheral attachment as low speed if D- is high and as full speed if D+ is high. If a host detects a low speed peripheral, it does not follow the remainder of this protocol.

2. Host Drives – If a host detects a full speed peripheral, it resets the peripheral by writing to the Function Control register and setting XcvrSelect = 00b (HS) and TermSelect = 0b which drives SE0 on the bus (D+ and D- connected to ground via 45Ω). The host also sets OpMode = 10b for correct chirp transmit and receive11. The start of SE0 is labelled T0. The peripheral PHY asserts dir and informs the Link of the LineState change using an RX CMD.

3. Peripheral Responds – After detecting SE0 for no less than 2.5us, if the peripheral is Hi-Speed capable, the peripheral Link sets XcvrSelect to 00b (HS) and OpMode to 10b (chirp), and follows this immediately with a TX CMD (NOPID), transmitting a chirp K for no less than 1ms. and the chirp K must end it no more than 7ms after reset time T0. If the peripheral is in Low Power Mode, it must wake up its clock within 5.6ms, leaving 200us for the Link to start transmitting the chirp K, and 1.2ms for the chirp K to complete (worst case with 10% slow clock).

4. Host Responds – If the host does not detect the peripheral chirp, it must continue the assertion of SE0 until the end of reset. If the host detects the peripheral chirp K for no less than 2.5us, then no more than 100us after the bus leaves the chirp K state, the host sends a TX CMD (NOPID) with an alternating sequence of chirp K’s and J’s. Each individual chirp K or J must last no less than 40us and no longer than 60us.

5. HS Idle – The peripheral must detect a minimum of chirp K-J-K-J-K-J. Each individual chirp K and J must be detected for at least 2.5us. After seeing that minimum sequence, the peripheral Link sets TermSelect = 0b and OpMode = 00b. The peripheral is now in Hi-Speed mode and sees !squelch (01b) on LineState. When the peripheral sees squelch (10b) on LineState, it knows the host has completed chirp and waits for Hi-Speed USB traffic to begin. After transmitting the chirp sequence, the host changes OpMode to 00b and begins sending USB packets.

 

 

Figure 4 High Speed Initialisation and handshake

 

 

 

 

 

We now receive High Speed SOFs every 125us.  

 

The USB 2.0 reference document states in section 9.1.1.3 states “After the device has been powered, it must not respond to any bus transactions until it has received a reset from the bus. After receiving a reset, the device is then addressable at the default address.”  However, if you attach a peripheral to a Windows 7 machine after initialisation to High Speed, you will see a SETUP PID and a Get Descriptor (Device) transaction.  The devices we have seen respond with the full transaction though some start off replying with NAKs.

 

As already intimated, on a Windows machine a peripheral will receive a SETUP PID as per either of the two diagrams below.  Generally for High Speed it will be the latter.

 

 

Figure 5 Receiving data from Host (DIR initially low)

 

 

Figure 6 Receiving data from Host (DIR already high)

 

A convenient USB peripheral is a USB memory stick.  This is a generic no-name device but its Vendor ID gives it away as being a NetCom Technology (HK) Ltd.  For identifying Vendor IDs these can be found at:

http://www.usb.org/developers/tools/

 

If I connect this device to a host I get the following transaction:

 

 

Transaction

Host

Direction

Device

Data

Get Descriptor (Device)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 00 01 00 00 40 00 DD 94

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4b 12 01 00 02 00 00 00 40 44 86 0b 80 00 01 01 02 03 01 38 e6

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

42

 

The PID here is a Packet Identifier and Packet ID should not be confused with Product ID.

A Packet ID is just 4 bits, where the Data[3:0] denotes the packet being sent. Data[7:4] are the complement of this. The first PID sent after connecting the cable should be a Start of Frame (SOF) token and be seen as x”a5”.

 

PID Type

PID Name

PID[3:0]

Description

Token

OUT

“0001” (x”1”)

Address + endpoint number in host -> function

transaction

IN

“1001” (x”9”)

Address + endpoint number in function -> host

transaction

SOF

“0101” (x”5”)

Start of frame marker and frame number

SETUP

“1101” (x”d”)

Address + endpoint number in host -> function

transaction for setup to a control endpoint

Data

DATA0

“0011” (x”3”)

Data packet PID even

DATA1

“1011” (x”b”)

Data packet PID odd

Handshake

ACK

“0010” (x”2”)

Receiver accepts error free data packet

NAK

“1010” (x”a”)

Rx device cannot accept data or Tx device cannot send data

STALL

“1110” (x”e”)

Endpoint is stalled

Special

PRE

“1100” (x”c”)

Host-issued preamble. Enables downstream bus traffic to LS devices.

ERR

“1100” (x”c”)

(Handshake) Split Transaction Error Handshake (reuses PRE value)

SPLIT

“1000” (x”8”)

High-speed Split Transaction Token (see Section 8.4.2)

PING

“0100” (x”4”)

High-speed flow control probe for a bulk/control

endpoint (see Section 8.5.1)

Reserved

“0000” (x”0”)

Reserved PID

Table 1 : Packet Identifier types

It’s worth noting that data is sent LSB first.

 

Sync

PID

Frame No.

CRC5

EOP

 

8 bits

11 bits

5 bits

 

SOF Packet

 

SOF packets are sent by the Host every 1 ms on Full Speed links. On High Speed links each 1 ms period is split into 8 microframes and a SOF is sent at the beginning of each microframe.  Each of these microframe SOFs within this 1 ms period will have the same Frame Number.

 

The Host must now reset the peripheral by stopping any further communication including stop sending any further SOFs.  Where there has been 3.0ms of IDLE state without taffic the device must enter Full Speed Idle mode where the High Speed terminations are removed and the pullup on D- is enabled.

 

Where the host pulls down both D+ and D- then this is a Reset. Where the Host releases both lines allowing a LineState of “01” then the peripheral is placed in Suspend mode. It is unfortunate that the ULPI reference document makes little mention of the Reset procedure.

The Reset procedure:

  1. 1When there has been no activity on either D+ or D- lines, the peripheral must leave the High Speed state and enter the Fast Speed state with an active pullup on the D+ signal by writing x”45” to FUNC_CTRL (x”04”) register. 

  2. 2If after 500µs the Linestate[1:0] is “00” then the host is applying a reset to the peripheral and continue as stage 3 in the initialisation process.  Note: if the line is anything other than “00” then the peripheral should be placed in Suspend mode. 

 

 

 

We should expect the following transactions from a Scandisk memory stick as per USB Simply Buffered (USB) - Device Enumeration by Shakthi Kannan.

 

The steps involved in USB device enumeration are as follows:

  1. 1SetAddress 

  2. 2GetDescriptor (Device) 

  3. 3GetDescriptor (Configuration) 

  4. 4GetDescriptor (String Language Ids) 

  5. 5GetDescriptor (String 3) 

  6. 6SetConfiguration 

 

 

Transaction

Host

 

Device

 

Set Address

Setup transaction

Setup

 

 

2D 00 10

Data0

 

 

C3 00 05 01 00 00 00 00 00 EB 25

 

 

ACK

42

IN transaction

IN

 

 

69 00 10

 

 

DATA1

4B 00 00

ACK

 

 

D2

Get Descriptor (Device)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 00 01 00 00 12 00 E0 F4

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 12 01 00 02 00 00 00 40 44 86 0B 80 00 01 01 02 03 01 38 E6

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

42

Get Descriptor (Config 1)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 00 02 00 00 FF 00 E9 A4

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 09 02 20 00 01 01 00 80 FA 09 04 00 00 02 08 06 50 00 07 05 82 02 00 02 00 07 05 01 02 00 02 00 8C 69

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

D2

Get Descriptor (String 3 -1)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 03 03 09 04 FF 00 96 0A

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 22 03 31 00 30 00 4A 00 32 00 31 00 34 00 30 00 30 00 30 00 30 00 30 00 30 00 33 00 36 00 38 00 42 00 B3 51

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

42

Get Descriptor (String Language IDs)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 00 03 00 00 FF 00 D4 64

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 04 03 09 04 78

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

42

Get Descriptor (String 2)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 02 03 09 04 FF 00 97 DB

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 3E 03 55 00 53 00 42 00 20 00 46 00 6C 00 61 00 73 00 68 00 20 00 44 00 69 00 73 00 6B 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20  00 20 00 20 00 20 00 20 00 20 00 3E BB

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

42

Get Descriptor (Device)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 00 01 00 00 12 00 E0 F4

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 12 01 00 02 00 00 00 40 44 86 0B 80 00 01 01 02 03 01 38 E6

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

42

Get Descriptor (Config 2)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 00 02 00 00 09 00 AE 04

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 09 02 20 00 01 01 00 80 FA E2 FB

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

D2

Get Descriptor (Config 3)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 00 02 00 00 20 00 B1 94

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 09 02 20 00 01 01 00 80 FA 09 04 00 00 02 08 06 50 00 07 05 82 02 00 02 00 07 05 01 02 00 02 00 8C 69

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

D2

Get Descriptor (String Language IDs 2)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 00 03 00 00 02 00 94 F4

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 04 03 BC 8E

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

42

Get Descriptor (String Language IDs 3)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 00 03 00 00 04 00 97 54

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 04 03 09 04 09 78

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

42

Get Descriptor (String 3 - 2)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 03 03 09 04 02 00 D6 9A

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 22 03 A6 EE

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

42

Get Descriptor (String 3 - 3)

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 80 06 03 03 09 04 22 00 CF 5A

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 22 03 31 00 30 00 4A 00 32 00 31 00 34 00 30 00 30 00 30 00 30 00 30 00 30 00 33 00 36 00 38 00 42 00 B3 51

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

42

Set Configuration

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 00 09 01 00 00 00 00 00 27 25

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 00 00

ACK

 

 

D2

Get Max LUN

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 A1 FE 00 00 00 00 01 00 6A 1F

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 00 40 BF

ACK

 

 

D2

OUT transaction

OUT

 

 

E1 01 E8

DATA1

 

 

4B 00 00

 

 

ACK

D2

Clear  Feature

Setup transaction

Setup

 

 

2D 01 E8

Data0

 

 

C3 02 01 00 00 82 00 00 00 06 95

 

 

ACK

42

IN transaction

IN

 

 

69 01 E8

 

 

DATA1

4B 00 00

ACK

 

 

D2

 

 

 

 

  1. 1.SetAddress 

 

    1. 1.1.SETUP 

The first packet we receive after a reset is an x”2d”, a setup packet of the following format:

 

PID (d)

!PID(2)

Function Address

Endpoint

CRC

4

4

7

4

5

 

The first Token packet is “2d 00 10” where the Host provides the device a temporary address of b“000_0000”.

 

    1. 1.2.DATA0 

The next packet starts with “c3” indicating a DATA0 packet.

 

PID (3)

!PID(c)

SETUP Data

CRC

4

4

64

16

 

Where the SETUP Data is:

Description

bmRequestType

bRequest

wValue

wIndex

wLength

Length in bytes

1

1

2

2

2

 

This setup packet we receive is “c3 00 05 06 00 00 00 00 00 ea 92”

 

bmRequestType has the following fields

Description

D7

D6..D5

D4……..D0

Length in bits

1

2

5

 

D7: Data transfer direction

0 = Host-to-device

1 = Device-to-host

D6..D5: Type

0 = Standard

1 = Class

2 = Vendor

3 = Reserved

D4..D0: Recipient

0 = Device

1 = Interface

2 = Endpoint

3 = Other

4..31 = Reserved

 

The device address is limited to 127, with 0 being that of an uninitialized peripheral.  A peripheral may have one or a number of endpoints depending on its architecture.  The functional address is set by the host with the SET_ADDRESS packet as per the table below:

 

 

bmRequest

Type

1 byte

bRequest

 

1 byte

wValue

 

2 bytes

wIndex

 

2 bytes

wLength

 

2 bytes

Data

00000000

00000001

00000010

0x01 CLEAR_FEATURE

Feature Selector

Zero Interface

Endpoint

0

None

10000000

0x08 GET_CONFIGURATION

0

0

1

Configuration

Value

10000000

0x06 GET_DESCRIPTOR

Descriptor Type and

Descriptor Index

0 or Language

ID

Descriptor

Length

Descriptor

10000001

0x0a GET_INTERFACE

0

Interface

1

Alternate Interface

10000000

0x00 GET_STATUS

0

Zero Interface

Endpoint

2

Device, Interface,

or Endpoint status

00000000

0x05 SET_ADDRESS

Device Address

0

0

None

00000000

0x09 SET_CONFIGURATION

Configuration Value

0

0

None

00000000

0x07 SET_DESCRIPTOR

Descriptor Type and

Descriptor Index

0 or Language

ID

Descriptor

Length

Descriptor

00000000

00000001

00000010

0x03 SET_FEATURE

Feature Selector

Zero Interface

Endpoint

0

None

00000001

0x0B SET_INTERFACE

Alternate

Interface

0

None

10000001

0x0C SYNCH_FRAME

0

Endpoint

2

Frame Number

 

 

Before moving on, we need to compute and check the CRC-5 value. A polynomial of x5 + x2 + 1 is used.  There a number of sites that compute the CRC from 8 bit data and an example is:

http://www.easics.be/webtools/crctool

 

This creates a downloadable function.  However its implementation is not so intuitive. Most of these functions expect a little endian byte so we have to swap the bit ordering.  Furthermore when calculating the CRC the answer must be inverted and byte order swapped.

 

The CRC must be preloaded with x”1f” and in this case the endian nature of the 8 bit data should be reversed as D(7) is the first serial bit, ie the LSB).  It is worth noting that some generator functions have D(0) as the LSB.

 

After performing a CRC-5 on the data and the CRC bits, the result should be “01100”.  The CRC-5 is not performed on the PID.

 

It is important to wait a short time before the device sends an ACK. Note the ULPI interface requires 4D to be sent and not 2D. The ULPI string “4D” is converted by the PHY to “2D”.

 

 

    1. 1.3.ACK 

The device returns an ACK.

 

    1. 1.4.IN 

The Host should send an IN token “69 00 10” which says it is ready to receive data.

 

    1. 1.5.DATA1 

The device send a DATA1 packet “4B 00 00”, a null packet.

 

    1. 1.6.ACK 

The Host returns anACK.

 

 

  1. 2.GetDescriptor (Device) 

 

    1. 2.1.SETUP 

The host sends a SETUP packet - 2D 01 E8

 

 

    1. 2.2.DATA0 

The host sends a DATA0 packet of C3 80 06 00 01 00 00 12 00 E0 F4. This request is for a device to host direction, indicated by the second byte of  “80”, sending the device a GET_DESCRIPTOR indicated by the third byte “06”.  Byte 4 is 01 indicating the Descriptor type is DEVICE. Byte 7 is “12” indicating that the host is expecting 18 bytes.

 

 

    1. 2.3.ACK 

The Device returns an ACK

 

    1. 2.4.IN 

The Host should send an IN token “69 01 E8” which says it is ready to receive data.

 

    1. 2.5.DATA1 

The device send a DATA1 packet “4B 12 01 00 02 00 00 00 40 44 86 0B 80 00 01 01 02 03 01 38 E6”.  A description of this packet is:

 

Offset

Field

Size

Value

Description

0

bLength

1

Number

Length of this descriptor (bytes)

1

bDescriptorType

1

Constant

DEVICE descriptor type

2

bcdUSB

2

BCD

USB Specification Release Number in BCD format (210H)

4

bDeviceClass

1

Class

Class code (by USB-IF)

5

bDeviceSubClass

1

SubClass

Subclass code (by USB-IF)

6

bDeviceProtocol

1

Protocol

Protocol code (by USB-IF)

7

bMaxPacketSize0

1

Number

Maximum packet size for endpoint zero (8, 16, 32 or 64)

8

idVendor

2

ID

Vendor ID (by USB-IF)

10

idProduct

2

ID

Product ID (by manufacturer)

12

bcdDevice

2

BDC

Device release number in BCD

14

iManufacturer

1

Index

Index of string descriptor describing manufacturer

15

iProduct

1

Index

Index of string descriptor describing product

16

iSerialNumber

1

Index

Index of string descriptor describing the

device's serial number

17

bNumConfigurations

1

Number

Number of possible configurations

 

 

    1. 2.6.ACK 

The Host responds with an ACK “D2”.

 

Note: If the bcdUSB field is different to the current link speed, the host will try and renegotiate the speed.  This can fool the unwary to wonder why no ACK has been received. You might see the characteristic chirp after sending the DATA1 packet!

 

 

    1. 2.7.OUT 

The Host send an OUT packet, E1 01 E8.

 

    1. 2.8.DATA1 

The Host sends a DATA1 packet “4B 00 00”, a null packet.

 

    1. 2.9.ACK 

The Device sends a “42” packet.

 

 

  1. 3.GetDescriptor (Configuration (1)) 

 

    1. 3.1.SETUP 

The host sends a SETUP packet - 2D 01 E8

 

    1. 3.2.DATA0 

The host sends a DATA0 packet C3 80 06 00 02 00 00 FF 00 E9 A4. This request is for a device to host direction, indicated by the second byte of “80”, sending the device a GET_DESCRIPTOR indicated by the third byte “06”.  Byte 4 is 02 indicating the Descriptor type is CONFIGURATION and the Descriptor index is 0. The length of requested data is 255 indicated by byte 7, though in practice the peripheral will only send as many bytes as necessary up to this maximum.

 

    1. 3.3.ACK 

The Device returns an ACK 42

 

    1. 3.4.IN 

The Host should send an IN token “69 01 E8” which says it is ready to receive data.

 

    1. 3.5.DATA1 

 

The device send a DATA1 packet “4B 09 02 20 00 01 01 00 80 FA 09 04 00 00 02 08 06 50 00 07 05 82 02 00 02 00 07 05 01 02 00 02 00 8C 69”.  

The first 9 bytes in this case is the Configuration Descriptor:

 

Offset

Field

Size

Value

Hex

0

bLength

1

9 (bytes)

0x09

1

bDescriptorType

1

CONFIGURATION descriptor (2)

0x02

2

wTotalLength

2

32 (bytes)

0x0020

4

bNumInterfaces

1

1

0x01

5

bConfigurationValue

1

1

0x01

6

iConfiguration

1

0

0x00

7

bmAttributes

1

Bus Powered

0x80

8

bMaxPower

2

500 mA

0xFA

 

 

Next follows then Interface Descriptor (9 bytes):

 

Offset

Field

Size

Value

Hex

0

bLength

1

9 (bytes)

0x09

1

bDescriptorType

1

INTERFACE descriptor (4)

0x04

2

bInterfaceNumber

1

0

0x00

3

bAlternateSetting

1

0

0x00

4

bNumEndpoints

1

2

0x02

5

bInterfaceClass

1

Mass Storage(08)

0x08

6

bInterfaceSubClass

1

SCSI transparent command set(06)

0x06

7

bInterfaceProtocol

1

Bulk-Only Transport(50)

0x50

8

iInterface

2

0

0x00

 

 

And then details of the two Endpoints (7 bytes each):

 

 

Offset

Field

Size

Value

Hex

0

bLength

1

7 (bytes)

0x07

1

bDescriptorType

1

ENDPOINT descriptor (5)

0x05

2

bEndpointAddress

1

IN endpoint (D7), first endpoint (D0)

0x82

3

bmAttributes

1

Data endpoint (D5...D4),

No synchronization (D3...D2),

Bulk transfer type (D1...D0)

0x02

4

wMaxPacketSize

2

512 bytes

0x0200

6

bInterval

1

0

0x00

 

 

Offset

Field

Size

Value

Hex

0

bLength

1

7 (bytes)

0x07

1

bDescriptorType

1

ENDPOINT descriptor (5)

0x05

2

bEndpointAddress

1

IN endpoint (D7), first endpoint (D0)

0x01

3

bmAttributes

1

Data endpoint (D5...D4),

No synchronization (D3...D2),

Bulk transfer type (D1...D0)

0x02

4

wMaxPacketSize

2

512 bytes

0x0200

6

bInterval

1

0

0x00

 

 

    1. 3.6.ACK 

The Host responds with an ACK “D2”.

 

    1. 3.7.OUT 

The Host send an OUT packet, E1 01 E8.

 

    1. 3.8.DATA1 

The Host sends a DATA1 packet “4B 00 00”, a null packet.

 

    1. 3.9.ACK 

The Device sends a “42” packet.

 

 

  1. 4.GetDescriptor (String 3) 

 

    1. 4.1.SETUP 

The host sends a SETUP packet - 2D 01 E8

 

    1. 4.2.DATA0 

The host sends a DATA0 packet C3 80 06 03 03 09 04 FF 00 96 0A. This request is for a device to host direction, indicated by the second byte of “80”, sending the device a GET_DESCRIPTOR indicated by the third byte “06”.  Byte 4 is 03 indicating the Descriptor type is String and the Descriptor index is 3. The length of requested data is 255 bytes indicated by byte 7.

 

    1. 4.3.ACK 

The Device returns an ACK 42

 

    1. 4.4.IN 

The Host should send an IN token “69 01 E8” which says it is ready to receive data.

 

    1. 4.5.DATA1 

The Device sends 4B 22 03 31 00 30 00 4A 00 32 00 31 00 34 00 30 00 30 00 30 00 30 00 30 00 30 00 33 00 36 00 38 00 42 00 B3 51.  A description of this packet:

 

Offset

Field

Size

Value

Hex

0

bLength

1

34 bytes

0x22

1

bDescriptorType

1

STRING descriptor

0x03

2

bString

2

1

0x0031

4

bString

2

0

0x0030

6

bString

2

J

0x004A

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

28

bString

2

6

0x0036

30

bString

2

8

0x0038

32

bString

2

B

0x0042

 

 

    1. 4.6.ACK 

The Host responds with an ACK “D2”.

 

    1. 4.7.OUT 

The Host send an OUT packet, E1 01 E8.

 

    1. 4.8.DATA1 

The Host sends a DATA1 packet “4B 00 00”, a null packet.

 

    1. 4.9.ACK 

The Device sends a “42” packet.

 

  1. 5.Get Descriptor (String Language IDs - 1) 

 

    1. 5.1.SETUP 

The host sends a SETUP packet - 2D 01 E8

 

    1. 5.2.DATA0 

The host sends a DATA0 packet C3 80 06 00 03 00 00 FF 00 D4 64. This request is for a device to host direction, indicated by the second byte of  “80”, sending the device a GET_DESCRIPTOR indicated by the third byte “06”.  Byte 4 is 03 indicating the Descriptor type is String and the Descriptor index is 0. The length of requested data is 255 bytes indicated by byte 7.

 

    1. 5.3.ACK 

The Device returns an ACK 42

 

    1. 5.4.IN 

The Host should send an IN token “69 01 E8” which says it is ready to receive data.

 

    1. 5.5.DATA1 

The Device sends 4B 04 03 09 04 09 78

 

Offset

Field

Size

Value

Hex

0

bLength

1

4 bytes

0x04

1

bDescriptorType

1

STRING descriptor

0x03

2

wLANGID[0]

2

English (US)

0x0409

 

    1. 5.6.ACK 

The Host responds with an ACK “D2”.

 

    1. 5.7.OUT 

The Host send an OUT packet, E1 01 E8.

 

    1. 5.8.DATA1 

The Host sends a DATA1 packet “4B 00 00”, a null packet.

 

    1. 5.9.ACK 

The Device sends a “42” packet.

 

 

  1. 6.GetDescriptor (String 2) 

 

    1. 6.1.SETUP 

The host sends a SETUP packet - 2D 01 E8

 

    1. 6.2.DATA0 

The host sends a DATA0 packet C3 80 06 02 03 09 04 FF 00 97 DB. This request is for a device to host direction, indicated by the second byte of  “80”, sending the device a GET_DESCRIPTOR indicated by the third byte “06”.  Byte 4 is 03 indicating the Descriptor type is String and the Descriptor index is 0. The length of requested data is 255 bytes indicated by byte 7.

 

    1. 6.3.ACK 

The Device returns an ACK 42

 

    1. 6.4.IN 

The Host should send an IN token “69 01 E8” which says it is ready to receive data.

 

    1. 6.5.DATA1 

The Device sends 4B 3E 03 55 00 53 00 42 00 20 00 46 00 6C 00 61 00 73 00 68 00 20 00 44 00 69 00 73 00 6B 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20  00 20 00 20 00 20 00 20 00 20 00 3E BB.  A description of this packet:

 

Offset

Field

Size

Value

Hex

0

bLength

1

62 bytes

0x3E

1

bDescriptorType

1

STRING descriptor

0x03

2

bString

2

U

0x0055

4

bString

2

S

0x0053

6

bString

2

B

0x0042

8

bString

2

<space>

0x0020

10

bString

2

F

0x0046

12

bString

2

l

0x006C

14

bString

2

a

0x0061

16

bString

2

s

0x0073

18

bString

2

h

0x0068

20

bString

2

<space>

0x0020

22

bString

2

D

0x0044

.

.

.

.

.

.

.

.

.

.

 

    1. 6.6.ACK 

The Host responds with an ACK “D2”.

 

    1. 6.7.OUT 

The Host send an OUT packet, E1 01 E8.

 

    1. 6.8.DATA1 

The Host sends a DATA1 packet “4B 00 00”, a null packet.

 

    1. 6.9.ACK 

The Device sends a “42” packet.

 

 

  1. 7.GetDescriptor (Device) 

This request is a repeat of Paragraph 2.

 

  1. 8.GetDescriptor (Configuration (2)) 

This is essentially the same as Paragraph 3, except the Host is only asking for the periphal’s Configuration Descriptor, ie the first 9 bytes.

 

  1. 9.GetDescriptor (Configuration (3)) 

This is essentially the same as Paragraph 3, where the Host is requesting all the Configuration information.  Note that the Host is asking for 32 bytes of data, ie the actual length of the Configuration Descriptor.

 

  1. 10.Get Descriptor (String Language IDs - 2) 

This is a repeat of Paragraph 4.

 

  1. 11.GetDescriptor (String 3 - 2) 

This is a repeat of Paragraph 5 except only the first 2 bytes are being requested, being the string length and String Descriptor.

 

  1. 12.GetDescriptor (String 3 - 3) 

This is a repeat of Paragraph 5 for the full string.

 

 

  1. 13.GetMaxLUN 

 

    1. 13.1.SETUP 

The host sends a SETUP packet - 2D 01 E8

 

    1. 13.2.DATA0 

The host sends a DATA0 packet C3 A1 FE 00 00 00 00 01 00 6A 1F. The device may implement several logical units that share common device characteristics.  This retrieves the number of logical units in the peripheral and is specific to the USB Mass Storage Class.

 

 

bmRequest Type

1 byte

bRequest

1 byte

wValue

2 bytes

wIndex

2 bytes

wLength

2 bytes

Data

10100001

0xFE

0x0000

Interface

0x0001

None

 

 

    1. 13.3.ACK 

The Device returns an ACK 42

 

    1. 13.4.IN 

The Host should send an IN token “69 01 E8” which says it is ready to receive data.

 

    1. 13.5.DATA1 

The Device sends 4B 00 40 BF.  Our device has no multiple LUNs and so says “0x00”.  It is confusing where if there were 4 LUNs the reply would be 0x03, numbered 0 to 3.

 

    1. 13.6.ACK 

The Host responds with an ACK “D2”.

 

    1. 13.7.OUT 

The Host send an OUT packet, E1 01 E8.

 

    1. 13.8.DATA1 

The Host sends a DATA1 packet “4B 00 00”, a null packet.

 

    1. 13.9.ACK 

The Device sends a “42” packet.

 

 

  1. 14.Clear Feature 

This request is used to clear or disable a specific feature.

 

    1. 14.1.SETUP 

The host sends a SETUP packet - 2D 01 E8

 

    1. 14.2.DATA0 

The host sends a DATA0 packet C3 02 01 00 00 82 00 00 00 06 95.

 

bmRequest Type

1 byte

bRequest

1 byte

wValue

2 bytes

wIndex

2 bytes

wLength

2 bytes

Data

00000000B

00000001B

00000010B

CLEAR_FEATURE

(0x02)

Feature

Selector

Zero

Interface

Endpoint

0x0000

None

 

 

    1. 14.3.ACK 

The Device returns an ACK 42

 

    1. 14.4.IN 

The Host should send an IN token “69 01 E8” which says it is ready to receive data.

 

    1. 14.5.DATA1 

The Device sends a null reply 4B 00 00.

 

    1. 14.6.ACK 

The Host responds with an ACK “D2”.

 

    1. 14.7.OUT 

The Host send an OUT packet, E1 01 E8.

 

    1. 14.8.DATA1 

The Host sends a DATA1 packet “4B 00 00”, a null packet.

 

    1. 14.9.ACK 

The Device sends a “42” packet.

 

 

The device will now be recognised by the host.

 

 

An important consideration is that RXCMD packets can interrupt and abort register reads and writes.  Depending of the timing of events there are a number of variations.  

 

 

Figure 7 TXCMD cycle aborted by a RXCMD

 

For a TXCMD applied to the data bus the PHY can abort register write by pulling DIR at the same time the PHY would assert NXT.  The register write must be aborted and sent again after Data returns to the idle state.

 

Conclusion.

 

I wrote this to gain an understanding of the USB port and how to emulate a peripheral. I hope it is useful to others as I could find little information about the initialisation process.

 

Any improvements or suggestions are invited.

 

 

© Mike Perkins 17/08/2104