World s simplest usb host application
This presentation is the property of its rightful owner.
Sponsored Links
1 / 33

World’s Simplest USB Host Application PowerPoint PPT Presentation


  • 64 Views
  • Uploaded on
  • Presentation posted in: General

World’s Simplest USB Host Application. Lane Hauck [email protected] Question. How simple can embedded host firmware be? Let’s figure out a really simple (but useful) interface and write the code. EZ-USB. SL-811. Development. USB Host. Board. Controller. USB. Keypad. D[7..0]. CS#.

Download Presentation

World’s Simplest USB Host Application

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


World s simplest usb host application

World’s Simplest USB Host Application

Lane Hauck

[email protected]


Question

Question

  • How simple can embedded host firmware be?

  • Let’s figure out a really simple (but useful) interface and write the code.


A usb point solution

EZ-USB

SL-811

Development

USB Host

Board

Controller

USB

Keypad

D[7..0]

CS#

CS#

RD#

RD#

8051

USB D+D-

WR#

WR#

A0

A0

PB1

M/S#

PB0

RES#

PA0

Scope Trigger

A USB “Point Solution”

Host

Firmware

Demo


Usb enumeration

USB Enumeration

  • Detect device

  • Detect speed

  • Issue USB bus reset

  • Get Descriptor: Device

  • Set Address

  • Get Descriptor: Configuration

  • Get String: Product

  • Set Configuration


Assumptions save code initial conditions are known

Assumptions save codeInitial conditions are known

  • Detect deviceIt’s plugged in

  • Detect speedLow speed

  • Issue USB bus reset

  • Get Descriptor: Device

  • Set Address

  • Get Descriptor: Configuration

  • Get String: Product

  • Set Configuration


How about the descriptors

How about the descriptors?

  • They’re fixed (hardwired) in the keypad

  • They are the same every time we ask for them

    • With a “Get_Descriptor” request

  • If we know them in advance, we can save the code that asks for and interprets them

  • Device assumptions save code

    • But limit our code to a specific device


Assumptions save code the keypad s device descriptor

Assumptions save codeThe keypad’s device descriptor


Assumptions save code the keypad s device descriptor1

Assumptions save codeThe keypad’s device descriptor


Assumptions save code config interface descriptors

Assumptions save codeConfig. & interface descriptors


Assumptions save code config interface descriptors1

Assumptions save codeConfig. & interface descriptors


Assumptions save code endpoint hid descriptors

Assumptions save codeEndpoint & HID descriptors

Note: In HID version 1.1 the order of these descriptors is HID, Endpoint.


Assumptions save code endpoint hid descriptors1

Assumptions save codeEndpoint & HID descriptors

Note: In HID version 1.1 the order of these descriptors is HID, Endpoint.


Assumptions save code hid report descriptor

Assumptions save codeHID Report descriptor

  • It’s complicated

    • The HID spec is 100 pages long and handles such issues as how to report controls attached to various body parts.

    • It helps an application discover the capabilities of any Human-Interface Device attached to a PC without prior knowledge of the device.

  • All we really need to know:

    • Keystroke data is delivered in 3-byte packets, with the keypress code in the third byte.

  • We could deduce this by deciphering the HID descriptor, or by watching a little bus traffic.


What we know in advance

What we know in advance

  • It’s a low-speed HID (keypad)

    • It reports data on EP1-IN

      • Which is an INTERRUPT endpoint with an 8-byte MaxPacketSize

  • It responds to IN requests with a 3-byte payload.

  • The keycode is in the third byte


Init code simplifies to this

Init. code simplifies to this

  • Detect device

  • Detect speed

  • Issue USB bus reset

  • Get Descriptor: Device

  • Set Address

  • Get Descriptor: Configuration

  • Get String: Product

  • Set Configuration


Operation code is simple

Operation code is simple

  • Send 1 msec “keep alive” pulses (EOP) so the keypad doesn’t suspend.

    • Automatic, just initialize the 811H chip

  • Whenever we feel like it, send an IN token.

    • If the keypad has a new keycode to report, it responds with a DATA PID and 3 bytes of data.

    • If it doesn’t, it sends a NAK PID.

  • If we get data, use it.

    • 811H chip automatically ACKS the transfer


Our in request keypad has no new data

Our IN RequestKeypad has no new data

Sync

IN

AD

EP

CRC5

Host (us)

00000001

10010110

0000001

0001

xy

Sync

NAK

Keypad

00000001

10100101


Our in request keypad reports a new keystroke

Our IN RequestKeypad reports a new keystroke

Sync

IN

AD

EP

CRC5

Host (us)

00000001

10010110

0000001

0001

xy

Data

Sync

DATA0/1

CRC16

Keypad

00000001

10010110

A

B

C

wxyz

Sync

ACK

Host (us)

00000001

01001011


Code 1 initialize the 811h and usb

Code-1Initialize the 811H and USB

void main(void) {

BYTEresult;

// set up the EZ-USB chip to talk to the 811 chip and provide a scope trigger

PORTCCFG = 0xC0;// enable RD, WR pins

OEB= 0x03;// PB0 is SL811 RESET, PB1 is Host/Slave pin)

OEA= 0x01;// PA0 is scope trigger

SCOPE_LO;// initialize scope trigger

// Reset the SL811H chip

OUTB= 0x00;// PB1=0 means we're the host

delay(1000);

OUTB= 0x01;// remove reset, keep PB1 LOW for SLAVE

// SL811 initialization

wr811(BUFADR,0x10); // start of SETUP/IN internal data buffer

wr811(BUFLEN,0x08); // reserve 8 bytes

// (1) Reset the USB device. This makes it listen to address 0.

wr811(CTL1,USB_RESET);// Speed=1(L), JKFORCE=1, SOFEN=1

delay(10000);// about 18 milliseconds

wr811(CTL1,USB_OPERATE);

// Enable sending 1 msec EOP's (the low-speed version of SOF's)

wr811(SOFCT_L, 0xE0);// Set the SOF generator time constant

wr811(SOFCT_H, 0x2E | 0xC0);// 1 msec SOF rate, b7=HOST, b6=POLSWAP


Review control ctl transfer

H

H

P

S

D

C

A

E

C

E

A

8 bytes

R

A

H is Host

P is Peripheral

D

N

R

SETUP

T

T

Setup

C

C

D

D

C

U

A

Data

1

K

R

P

5

P

0

6

Data Packet

Token Packet

H/S Pkt

H

P

H

D

C

A

E

C

A

R

A

I

D

N

R

Payload

DATA

T

C

C

N

D

D

C

Data

A

1

K

R

P

5

1

6

Token Packet

H/S Pkt

Data Packet

H

H

P

H

H

P

D

D

C

C

A

E

C

A

E

C

O

A

O

A

R

N

R

A

D

N

R

D

N

R

U

T

U

T

C

A

C

C

HANDSHAKE

D

D

C

D

D

C

T

A

T

A

1

K

1

K

R

P

5

R

P

5

1

1

6

6

TokenPacket

H/S Pkt

H/S Pkt

Token Packet

Data Pkt

Data Pkt

(Operation not completed)

(Operation completed)

Review:CONTROL (CTL) transfer

Set_Address & Set_Configuration data is contained in the SETUP stage, so no DATA stage is required.


Code 2 issue set address ctl transfer

Code-2Issue Set_Address CTL transfer

// (2) Issue a SET_ADDRESS USB request, setting the peripheral address to 1

// From the USB spec, Chapter 9, here is the data for a "SET_ADDRESS" request:

// Note: every SL811_DATA load increments an internal SL811 address pointer

SL811_ADDR = 0x10;// next SL811_DATA byte goes here

SL811_DATA=0x00;// bmRequestType (h->d,std request,device is recipient)

SL811_DATA=0x05;// bRequest (SET_ADDRESS)

SL811_DATA=0x01;// wValueL (device address)--we're setting it to ONE

SL811_DATA=0x00;// wValueH (zero)

SL811_DATA=0x00;// wIndexL (zero)

SL811_DATA=0x00;// wIndexH (zero)

SL811_DATA=0x00;// wLengthL (zero)

SL811_DATA=0x00;// wLengthH (zero)

wr811(FNADDR,0x00);// USB address zero

wr811(PID_EP,SETUP_PID | 0x00);// SETUP PID, EP0

result=go(0x07);// DIREC=1(out), ENAB=1, ARM=1

// STATUS stage is a no-data IN to EP0

wr811(PID_EP,IN_PID | 0x00);// IN PID, EP0

result=go(0x03);// Don't sync to SOF, DIREC=0(in), ENAB, ARM


Code 2 on the wire

Code-2On the wire

// (2) Issue a SET_ADDRESS USB request, setting the peripheral address to 1

// From the USB spec, Chapter 9, here is the data for a "SET_ADDRESS" request:

// Note: every SL811_DATA load increments an internal SL811 address pointer

SL811_ADDR = 0x10;// next SL811_DATA byte goes here

SL811_DATA=0x00;// bmRequestType (h->d,std request,device is recipient)

SL811_DATA=0x05;// bRequest (SET_ADDRESS)

SL811_DATA=0x01;// wValueL (device address)--we're setting it to ONE

SL811_DATA=0x00;// wValueH (zero)

SL811_DATA=0x00;// wIndexL (zero)

SL811_DATA=0x00;// wIndexH (zero)

SL811_DATA=0x00;// wLengthL (zero)

SL811_DATA=0x00;// wLengthH (zero)

wr811(FNADDR,0x00);// USB address zero

wr811(PID_EP,SETUP_PID | 0x00);// SETUP PID, EP0

result=go(0x07);// DIREC=1(out), ENAB=1, ARM=1

// STATUS stage is a no-data IN to EP0

wr811(PID_EP,IN_PID | 0x00);// IN PID, EP0

result=go(0x03);// Don't sync to SOF, DIREC=0(in), ENAB, ARM

D-

PA0


Code 2 catc trace

Code-2CATC trace

// (2) Issue a SET_ADDRESS USB request, setting the peripheral address to 1

// From the USB spec, Chapter 9, here is the data for a "SET_ADDRESS" request:

// Note: every SL811_DATA load increments an internal SL811 address pointer

SL811_ADDR = 0x10;// next SL811_DATA byte goes here

SL811_DATA=0x00;// bmRequestType (h->d,std request,device is recipient)

SL811_DATA=0x05;// bRequest (SET_ADDRESS)

SL811_DATA=0x01;// wValueL (device address)--we're setting it to ONE

SL811_DATA=0x00;// wValueH (zero)

SL811_DATA=0x00;// wIndexL (zero)

SL811_DATA=0x00;// wIndexH (zero)

SL811_DATA=0x00;// wLengthL (zero)

SL811_DATA=0x00;// wLengthH (zero)

wr811(FNADDR,0x00);// USB address zero

wr811(PID_EP,SETUP_PID | 0x00);// SETUP PID, EP0

result=go(0x07);// DIREC=1(out), ENAB=1, ARM=1

// STATUS stage is a no-data IN to EP0

wr811(PID_EP,IN_PID | 0x00);// IN PID, EP0

result=go(0x03);// Don't sync to SOF, DIREC=0(in), ENAB, ARM


Code 3 issue set config ctl transfer

Code-3Issue Set_Config. CTL Transfer

// (3) Send a CONTROL transfer to select configuration #1. Until we do this

// the device is in an "unconfigured" state and probably won't send data.

// Again, from USB spec Chapter 9:

SL811_ADDR = 0x10;// reset pointer to beginning of internal buffer.

SL811_DATA=0x00;// bmRequestType (h->d,std request,device is recipient)

SL811_DATA=0x09;// bRequest (SET_CONFIGURATION)

SL811_DATA=0x01;// wValueL (configuration = 1)

SL811_DATA=0x00;// wValueH (zero)

SL811_DATA=0x00;// wIndexL (zero)

SL811_DATA=0x00;// wIndexH (zero)

SL811_DATA=0x00;// wLengthL (zero)

SL811_DATA=0x00;// wLengthH (zero)

wr811(FNADDR,0x01);// now talking to USB device at address 1

wr811(PID_EP,SETUP_PID | 0x00);// OR in the endpoint (zero)

result=go(0x07);// DIREC=1(out), ENAB=1, ARM=1

// STATUS stage is a no-data IN to EP0

wr811(PID_EP,IN_PID | 0x00);// IN PID, EP0

result=go(0x03);// DIREC=0(in), ENAB=1, ARM=1


Code 3 on the wire

Code-3On the wire

// (3) Send a CONTROL transfer to select configuration #1. Until we do this

// the device is in an "unconfigured" state and probably won't send data.

// Again, from USB spec Chapter 9:

SL811_ADDR = 0x10;// reset pointer to beginning of internal buffer.

SL811_DATA=0x00;// bmRequestType (h->d,std request,device is recipient)

SL811_DATA=0x09;// bRequest (SET_CONFIGURATION)

SL811_DATA=0x01;// wValueL (configuration = 1)

SL811_DATA=0x00;// wValueH (zero)

SL811_DATA=0x00;// wIndexL (zero)

SL811_DATA=0x00;// wIndexH (zero)

SL811_DATA=0x00;// wLengthL (zero)

SL811_DATA=0x00;// wLengthH (zero)

wr811(FNADDR,0x01);// now talking to USB device at address 1

wr811(PID_EP,SETUP_PID | 0x00);// OR in the endpoint (zero)

result=go(0x07);// DIREC=1(out), ENAB=1, ARM=1

// STATUS stage is a no-data IN to EP0

wr811(PID_EP,IN_PID | 0x00);// IN PID, EP0

result=go(0x03);// DIREC=0(in), ENAB=1, ARM=1

D-

PA0


Code 3 catc trace

Code-3CATC trace

// (3) Send a CONTROL transfer to select configuration #1. Until we do this

// the device is in an "unconfigured" state and probably won't send data.

// Again, from USB spec Chapter 9:

SL811_ADDR = 0x10;// reset pointer to beginning of internal buffer.

SL811_DATA=0x00;// bmRequestType (h->d,std request,device is recipient)

SL811_DATA=0x09;// bRequest (SET_CONFIGURATION)

SL811_DATA=0x01;// wValueL (configuration = 1)

SL811_DATA=0x00;// wValueH (zero)

SL811_DATA=0x00;// wIndexL (zero)

SL811_DATA=0x00;// wIndexH (zero)

SL811_DATA=0x00;// wLengthL (zero)

SL811_DATA=0x00;// wLengthH (zero)

wr811(FNADDR,0x01);// now talking to USB device at address 1

wr811(PID_EP,SETUP_PID | 0x00);// OR in the endpoint (zero)

result=go(0x07);// DIREC=1(out), ENAB=1, ARM=1

// STATUS stage is a no-data IN to EP0

wr811(PID_EP,IN_PID | 0x00);// IN PID, EP0

result=go(0x03);// DIREC=0(in), ENAB=1, ARM=1


Code 4 ping the keypad display new data

Code-4Ping the keypad, display new data

// (4) Send constant IN requests to Addr 1, EP1

wr811(PID_EP,IN_PID | 0x01);// set up for IN PIDS to endpoint 1

while(1) {

SL811_ADDR = 0x10;// reset pointer to beginning of internal bufferwaitframes(4);// send the IN requests every n milliseconds

result=go(0x03);// DIREC=0(in), ENAB=1, ARM=1

if (result & 0x01)// look only for ACK

display_hex(rd811(0x12)); }// KB value is in third byte of 3-byte packet


Entire startup sequence

Entire startup sequence

D-

EOP

PA0

Set

Address

Handshake

IN:

Dev=1, EP=1

Handshake

Set Config


Keypad naks then ready

Keypad NAKS, then ready


Code 5 housekeeping

Code-5Housekeeping

void wr811(BYTE address, BYTE value)

{

SL811_ADDR = address;

SL811_DATA = value;

}

BYTE rd811(BYTE address)

{

SL811_ADDR = address;

return SL811_DATA;

}

BYTE go(BYTE cmd){// Launch an 811H operation.

SCOPE_HI;

wr811(INTSTATUS,0x01);// clear the DONE bit

wr811(CTL,cmd);// start the operation

delay(100);

while(rd811(INTSTATUS) & 0x01==0) { }// spin while "done" bit is low

SCOPE_LO;

return rd811(PKTSTAT);}// return the status of this transfer


Code size

* * * * * * * C O D E M E M O R Y * * * * * * *

CODE 0000H 0003H ABSOLUTE

0003H 00FDH *** GAP ***

CODE 0100H 00DDH UNIT ?PR?MAIN?MINHOST

CODE 01DDH 008CH UNIT ?C_C51STARTUP

CODE 0269H 003FH UNIT ?PR?_DISPLAY_HEX?MINHOST

CODE 02A8H 0037H UNIT ?PR?_WAITFRAMES?MINHOST

CODE 02DFH 0027H UNIT ?PR?_GO?MINHOST

CODE 0306H 0014H UNIT ?C_INITSEG

CODE 031AH 000FH UNIT ?PR?_WR811?MINHOST

CODE 0329H 000BH UNIT ?PR?_DELAY?MINHOST

CODE 0334H 0009H UNIT ?PR?_RD811?MINHOST

350 bytes

Code Size


Creeping elegance

Creeping Elegance

  • Detect device plug-in

  • Put the device to sleep (suspend)

    • Easy—just disable 1 msec EOP’s

  • Wake up the device (resume)

    • Start sending EOP’s again

  • Operate through a hub

    • Keep track of more than one device address


Resources www usb org

Resources: www.usb.org

  • Tools

  • USBCV Beta 2 - Windows 2000 and Windows XP only

  • The installation utility, USBCVBeta2.msi (11 MB), contains USB Command Verifier (USBCV) version 0.9.0.6. USBCV is the new compliance test tool which evaluates High, Full and Low-speed USB devices for conformance to the USB Device Framework (Chapter 9), Hub device class (Chapter 11), and HID specifications. USBCV is a replacement for USBCheck and is the preferred compliance tool to be used at this time. The final release of USBCV is expected to occur no later than Q2 2002. At that time USBCheck will be made obsolete and removed from this site. Users are encouraged to immediately use USBCV along with or instead of USBCheck. Until USBCheck is made obsolete, test results from either tool are considered by the compliance team to have equal weight. This version of USBCV was posted on 1/22/02. This software release will only work on Windows 2000 and Windows XP. Please check the release notes and accompanying documentations for details on using USBCV and how to provide the USB-IF feedback on issues and suggestions. This software is provided courtesy of Intel Corporation.


  • Login