Author Topic: enumeration problem only through hub  (Read 21451 times)

BTalex

  • Member
  • ***
  • Posts: 1
enumeration problem only through hub
« on: July 09, 2011, 07:50:00 pm »
My MIDI devices have enumerated and operated properly on any PC or Mac I have tried to this point, and no custom driver is required because I'm using a standard USB MIDI definition.  Also, I change the serial number in the descriptor for every single chip I burn (PIC18F2550) so that multiple units can be connected to a single computer.  That has worked out well so far.

There is one anomaly however, which is that connecting one unit or multiple units through a USB hub (always a powered hub, even though my devices use very little current) results in enumeration only a percentage of the time.  I have tinkered with different delay loops at the start of my code and it seems I am honing in on a better percentage of successful enumerations through the hub, but I'd rather be 100% with this.  As a note, connecting multiple units directly to USB ports on the computers always works out with no problem.

Does anyone have any idea why something like this would be happening?

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: enumeration problem only through hub
« Reply #1 on: July 09, 2011, 08:44:39 pm »
Capturing the failure in a hardware analyzer will show where it's failing. If you don't have a hardware analyzer, use whatever debugging tools you have to find out which request fails.

For full and low speed devices on a 2.0 system, the 2.0 hub communicates upstream at high speed and converts to full and low speed downstream. Thus the timing may vary compared to connecting directly to the host's UCHI or OHCI controller.

Jan

Ron Hemphill

  • Member
  • ***
  • Posts: 19
Re: enumeration problem only through hub
« Reply #2 on: July 14, 2011, 05:34:14 pm »
Jan is correct, to solve this problem you'll need more information.  Some questions to answer:
 - Is this a HS, FS, or LS device?
 - Is the reset occurring, and is the device responding to it properly?
 - Is it making it to the default state, and then to the address state?

Also, do you have the same enumeration problem whether the hub is running on Windows or Mac?  Knowing this might help narrow the problem to a hardware enumeration issue, rather than a host software issue.

Guido Koerber

  • Frequent Contributor
  • ****
  • Posts: 72
Re: enumeration problem only through hub
« Reply #3 on: July 18, 2011, 04:00:36 am »
Take a close look at the timing of the data packets. The sequence of the packets is much faster when you use a USB 2.0 host with a USB 2.0 hub to connect a low or full speed device. Possibly you have a race condition in your protocol stack, much likely something like clearing the status of ACKing data too late so you miss some packets.

Barry Twycross

  • Frequent Contributor
  • ****
  • Posts: 263
Re: enumeration problem only through hub
« Reply #4 on: July 18, 2011, 01:30:45 pm »
I wouldn't mind seeing the trace files.

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: enumeration problem only through hub
« Reply #5 on: July 18, 2011, 03:11:52 pm »
Fix your device firmware so the device endpoint never NAKs or ignores Setup packets. See 8.5.3 in the USB 2.0 spec.

Jan

Tsuneo

  • Frequent Contributor
  • ****
  • Posts: 145
Re: enumeration problem only through hub
« Reply #6 on: July 19, 2011, 01:12:37 am »
Hi Vince,

Are you using Microchip USB device stack?
The old versions of the stack had this issue. Microchip has fixed it in the recent versions (v2.5 and later).

Tight timing occurs at SETUP transaction after a control read transfer, like Get_Descriptor, which finishes with OUT transaction as STATUS stage. To respond to this SETUP, PIC firmware has to arm the EP0 OUT endpoint immediately after the last OUT transaction. When the firmware can't arm EP0 OUT in time, incomplete SETUP transaction without ACK occurs. When a FS device connects to host over a HS hub, SETUP transaction comes at next micro-frame after the last OUT, in the worst case.

In the recent stack versions, Microchip has applied ping-pong on EP0 OUT to fix this issue. When the stack arms EP0 OUT for the last STATUS stage, it arms another ping-pong buffer for the next SETUP, too. In this way, this timing issue was solved.

The stack applies this fix when FULL_PING_PONG (default) or EP0_OUT_ONLY is enabled.

Code: [Select]
usb_config.h

//Make sure only one of the below "#define USB_PING_PONG_MODE"
//is uncommented.
//#define USB_PING_PONG_MODE USB_PING_PONG__NO_PING_PONG
#define USB_PING_PONG_MODE USB_PING_PONG__FULL_PING_PONG
//#define USB_PING_PONG_MODE USB_PING_PONG__EP0_OUT_ONLY
//#define USB_PING_PONG_MODE USB_PING_PONG__ALL_BUT_EP0

"Microchip Application Libraries" includes a MIDI example. It gives a good staring point for your migration.

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en547784

Tsuneo

Tsuneo

  • Frequent Contributor
  • ****
  • Posts: 145
Re: enumeration problem only through hub
« Reply #7 on: July 28, 2011, 01:52:20 am »
Quote
I have added a kick-start (below) to my code and now the device enumerates every time directly or through a hub to Windows or Mac, but there is a new issue.

It isn't a new issue, you are still trapped in the PIC SETUP timing issue.
Your workaround (delayed start) suppresses your firmware activity other than control transfer process, until Set_Configuration comes on the "enumeration". In this way, you gave timing priority to the control transfer process until Set_Configuration.

But as you said, "enumeration" doesn't always finish with Set_Configuration. Rather, it is rare case for OS class drivers. Usually, more requests come from host after Set_Configuration. For example,
- Windows HID driver puts Get_Descriptor( Report Descriptor ) and Set_Idle just after Set_Configuration.
- Windows CDC driver puts Get_Line_Coding and Set_Control_Line_State
- Most of OS puts Get_Max_LUN for MSC
- MacOSX often puts many Get_Descriptor( String ) for most of classes.
etc.

For the radical solution of this timing issue, apply ping-pong buffers to the PIC EP0 OUT. But it's beyond modification of stack users. Request it to the provider of the PIC USB device stack for better implementation. I believe the PIC SIE designer has added EP0_OUT_ONLY ping-pong option for this purpose. It is the responsibility of USB stack programmers to apply this option.



Other than PIC, this SETUP timing issue potentially occurs on a couple of other SIE designs, which require firmware intervention to accept the next SETUP transaction after the last control transfer. For instances,
- Freescale MC9S08JM/MM, MCF51JM
- ST Micro STM32F102-3, STR71/73/91
- TI MSP430x5xx/x6xx

Usually, USB device stacks for these MCUs apply hardware interrupt to process USB events. Therefore, this timing issue is hidden. But it'll be revealed under heavy piled-up interrupts, which disturbs USB interrupt more than 100us. Stress test is recommended for critical applications.

Fortunately, the majority of SIEs are well designed on this aspect. The SIEs on these MCUs always accept SETUP transaction automatically, and the SIEs notify it to firmware. The firmware on these chips enjoys easy timing on SETUP handling.
- Atmel AT90USB, SAM7X, SAM3U
- Cypress EZ-USB FX2
- NXP LPC ARM family
- Renesas uPD78F, H8SX, SH2/3
- SiLabs C8051F32x/34x
- ST Micro STM32F105-7
- TI Stellaris LM3S5x/9x

Tsuneo
« Last Edit: July 28, 2011, 03:11:45 am by Tsuneo »

Barry Twycross

  • Frequent Contributor
  • ****
  • Posts: 263
Re: enumeration problem only through hub
« Reply #8 on: August 01, 2011, 07:15:24 pm »
For Mac, now the Strings aren't coming through during enumeration.  Even though GetDescriptors for Device, Config and String 1,2,3 are successful during the beginning of the process the host tries to get the strings again later and I see things like:

"GetDescriptor (String Lang IDs)
The host requested less bytes than available
SetupRequest.wLength: 2
Available length: 4"

I don't understand this because I thought that step (String 0) requires 4 bytes, but the host is only asking for 2.

The device's place is not to think, but to do exactly what the host asks of it. There are clear rules as to what a device has to do in response to a get descriptor, section 9.4.3 specifically "If the descriptor is longer than the wLength field, only the initial bytes of the descriptor are returned."

I suspect (without looking at the source) its because the Get_Descriptor(string 0) uses the same GetStringDescriptor method as all other string descriptors, which first looks at the length of the descriptor (2 byte request), then requests the whole descriptor.