EmbeddedRelated.com
Forums

lpc2378 USB enumeration woes

Started by asa386 April 30, 2013
trying to come to terms with my usb firmware. enumeration errors I am currently seeing take place just after the HOST pc sends me the SET ADDRESS command. I set the value but HOST pc flags an error.

The exchange (dumped from the serial port looks like this)
as seen on my lpc2378 usb device - (my firmware code) is:

---host initiated reset---
80 06 00 01 00 00 40 00
---host initiated reset---
00 05 07 00 00 00 00 00
usb_dev_addr = 07
---host initiated reset---
80 06 00 01 00 00 40 00
---host initiated reset---
00 05 08 00 00 00 00 00
usb_dev_addr = 08
---host initiated reset---
00 05 09 00 00 00 00 00
usb_dev_addr = 09
---host initiated reset---
00 05 0: 00 00 00 00 00

from linux usbmon (usb monitor) running on the USB host

Ci:1:000:0 s 80 06 0100 0000 0040 64 <
Ci:1:000:0 0 18 = 12011001 00000008 dec0edfe 00010102 0301
Co:1:000:0 s 00 05 0007 0000 0000 0
Co:1:000:0 -32 0
Co:1:000:0 s 00 05 0007 0000 0000 0
Co:1:000:0 -32 0
Ci:1:000:0 s 80 06 0100 0000 0040 64 <
Ci:1:000:0 0 18 = 12011001 00000008 dec0edfe 00010102 0301
Co:1:000:0 s 00 05 0008 0000 0000 0
Co:1:000:0 -32 0
Co:1:000:0 s 00 05 0008 0000 0000 0
I am at a loss as to what I could be doing wrong. The exchange beginning with reset (which correctly happens after I pull D+ down) starts with the get_device descriptor command, I obviously respond correctly which triggers the set_address command.

I understand that afterwards all communication will take place on or with the new address. But the HOST pc never quite sees it.

I am pretty certain I am setting the device address and enabling it correctly via the SIE.
Barring a USB protocol analyzer there is no way to be absolutely sure. This particular register on the SIE is write only.

I am hoping someone here familiar with usb enumeration can shed some light. Perhaps the handshake at that point requires me to follow with a status response/zero length packet ... Ill be tearing through the USB Architecture book later this week for a clue.

Thanks in advance

An Engineer's Guide to the LPC2100 Series

Hi,

Some things came into my mind :
- is your usb interrupt based or is it "directly" e.g. in your main
loop ? If interrupt based then it can be done but do it for instance
with buffering and semaphores. This way you have more control of what
is coming through the control endpoint.
- at which point do you print these control endpoint messages to the
console (I hope you donot do this in e.g. an interrupt : a serial
port is way to slow even if the bitrate is at 921Kb) ?
When the usb device is addressed then the host pc is asking again
for the device descriptor and configuration descriptor. Check in usbmon
that you indeed sent both complete replies of your usb device. I found
out that this is very likely the culprit.
By the way : the host pc is requesting these descriptors 3 times : both
on GNU/Linux and win$ for reasons I donot know. The Mac is doing things
more directly.

Br,

Armand
On 04/30/2013 05:38 AM, asa386 wrote:
> trying to come to terms with my usb firmware. enumeration errors I am currently seeing take place just after the HOST pc sends me the SET ADDRESS command. I set the value but HOST pc flags an error.
>
> The exchange (dumped from the serial port looks like this)
> as seen on my lpc2378 usb device - (my firmware code) is:
>
> ---host initiated reset---
> 80 06 00 01 00 00 40 00
> ---host initiated reset---
> 00 05 07 00 00 00 00 00
> usb_dev_addr = 07
> ---host initiated reset---
> 80 06 00 01 00 00 40 00
> ---host initiated reset---
> 00 05 08 00 00 00 00 00
> usb_dev_addr = 08
> ---host initiated reset---
> 00 05 09 00 00 00 00 00
> usb_dev_addr = 09
> ---host initiated reset---
> 00 05 0: 00 00 00 00 00
>

On the usbmon log, the first SET_ADDRESS fails

Ci:1:000:0 s 80 06 0100 0000 0040 64 <---- GET_DESCRIPTOR(DEVICE)
Ci:1:000:0 0 18 = 12011001 00000008 dec0edfe 00010102 0301
Co:1:000:0 s 00 05 0007 0000 0000 0 <---- SET_ADDRESS(7)
Co:1:000:0 -32 0 <---- error

On the other hand, the debug print of your firmware receives the SET_ADDRESS request correctly. It suggests that your firmware doesn't return STATUS stage to this SET_ADDRESS request.

Did you put ZLT (Zero-Length Transaction, formerly, ZLP) to the EP0 IN, as the STATUS stage, just after SET_ADDRESS request comes?

Tsuneo

--- In l..., "asa386" wrote:
>
> trying to come to terms with my usb firmware. enumeration errors I am currently seeing take place just after the HOST pc sends me the SET ADDRESS command. I set the value but HOST pc flags an error.
>
> The exchange (dumped from the serial port looks like this)
> as seen on my lpc2378 usb device - (my firmware code) is:
>
> ---host initiated reset---
> 80 06 00 01 00 00 40 00
> ---host initiated reset---
> 00 05 07 00 00 00 00 00
> usb_dev_addr = 07
> ---host initiated reset---
> 80 06 00 01 00 00 40 00
> ---host initiated reset---
> 00 05 08 00 00 00 00 00
> usb_dev_addr = 08
> ---host initiated reset---
> 00 05 09 00 00 00 00 00
> usb_dev_addr = 09
> ---host initiated reset---
> 00 05 0: 00 00 00 00 00
>
> from linux usbmon (usb monitor) running on the USB host
>
> Ci:1:000:0 s 80 06 0100 0000 0040 64 <
> Ci:1:000:0 0 18 = 12011001 00000008 dec0edfe 00010102 0301
> Co:1:000:0 s 00 05 0007 0000 0000 0
> Co:1:000:0 -32 0
> Co:1:000:0 s 00 05 0007 0000 0000 0
> Co:1:000:0 -32 0
> Ci:1:000:0 s 80 06 0100 0000 0040 64 <
> Ci:1:000:0 0 18 = 12011001 00000008 dec0edfe 00010102 0301
> Co:1:000:0 s 00 05 0008 0000 0000 0
> Co:1:000:0 -32 0
> Co:1:000:0 s 00 05 0008 0000 0000 0
> I am at a loss as to what I could be doing wrong. The exchange beginning with reset (which correctly happens after I pull D+ down) starts with the get_device descriptor command, I obviously respond correctly which triggers the set_address command.
>
> I understand that afterwards all communication will take place on or with the new address. But the HOST pc never quite sees it.
>
> I am pretty certain I am setting the device address and enabling it correctly via the SIE.
> Barring a USB protocol analyzer there is no way to be absolutely sure. This particular register on the SIE is write only.
>
> I am hoping someone here familiar with usb enumeration can shed some light. Perhaps the handshake at that point requires me to follow with a status response/zero length packet ... Ill be tearing through the USB Architecture book later this week for a clue.
>
> Thanks in advance
>

> - is your usb interrupt based or is it "directly" e.g. in your main
> loop ? If interrupt based then it can be done but do it for
> instance with buffering and semaphores. This way you have more

all communication via usb is done inside the handler. control endpoints will be port based I/O (since there is no dma support for it on the lpc2378) and non control endpoints are dma based - with a fifo buffering scheme I have put into play. but am not there yet

> - at which point do you print these control endpoint messages to the
> console (I hope you donot do this in e.g. an interrupt : a serial
> port is way to slow even if the bitrate is at 921Kb) ?

actually it is. theres a few
#ifdef DEBUG
lpclib_printf();
#endif

lines scattered about the code and just a few inside the handler. The uart is run at 115200 but its driven by the FIQ high priority timer handler and its buffered.

basically calls to lpclib_printf()/lpclib_putc() put that characters in a queue and update the read/write pointers and immediately return. The timer handler - when called (1ms resolution) just looks to see if the uart tx fifo is empty and just writes out 0-16 bytes from the queue into it and returns
> When the usb device is addressed then the host pc is asking again
> for the device descriptor and configuration descriptor. Check in
> usbmon that you indeed sent both complete replies of your usb
> device. I found out that this is very likely the culprit.

The HOST doesnt seem to have sent anything to the new bus address it assigned to my usb device.

Last night I decided to put down $400 and purchase the beagle12 TotalPhase usb hardware sniffer. I expect to be doing a lot of work on USB in the next few months so I can probably justify this investment even if for not its for hobby work.

It should shed some light as to whats happening on the bus.
> By the way : the host pc is requesting these descriptors 3 times :
> both on GNU/Linux and win$ for reasons I donot know. The Mac is
> doing things more directly.

I used Linux' usbmon to capture the output of my 8gb usb stick just to see ... it came back with

Ci:1:000:0 s 80 06 0100 0000 0040 64 <
Ci:1:000:0 0 18 = 12010002 00000040 4b154565 00020102 0301
Co:1:000:0 s 00 05 0079 0000 0000 0
Co:1:000:0 0 0

So its possible (like you hinted above) the buffered printfs might be having an impact on the handshake process. I ll remove them and gauge the effect. But the reason I doubt they are a cause are because of dump indicating timely response to get_device_descriptor requests

> Ci:1:000:0 s 80 06 0100 0000 0040 64 <---- GET_DESCRIPTOR(DEVICE)
> Ci:1:000:0 0 18 = 12011001 00000008 dec0edfe 00010102 0301
> Co:1:000:0 s 00 05 0007 0000 0000 0 <---- SET_ADDRESS(7)
> Co:1:000:0 -32 0 <---- error
>
> On the other hand, the debug print of your firmware receives the
> SET_ADDRESS request correctly. It suggests that your firmware doesn't
> return STATUS stage to this SET_ADDRESS request.
>
> Did you put ZLT (Zero-Length Transaction, formerly, ZLP) to the EP0
> IN, as the STATUS stage, just after SET_ADDRESS request comes?

No I didnt do this. I was under the impression that such was handled by the SIE - serial interface engine and I need only get involved for data transmission and reception.

Need to look into this. Thanks