Author Topic: USB Sleep and Resume interrupts  (Read 14258 times)

Offline dkg

  • Newbie
  • *
  • Posts: 48
    • View Profile
USB Sleep and Resume interrupts
« on: July 13, 2010, 05:12:05 PM »
Hi Mark,

We have a problem where we are getting repeated USB Suspends with no intervening USB Resumes.

Looking at the code in the ISR, I see the Sleep interrupt clears both the Sleep and Resume interrupt bits. I am wondering if the reason we are not seeing the Resume is that the resume state was asserted between the time the interrupt status was captured at the beginning of the ISR and the point where it is cleared by the code for the Sleep interrupt.

Why do you clear both bits in the Sleep interrupt code (and the Resume interrupt code for that matter).

Thanks,
Dave G.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: USB Sleep and Resume interrupts
« Reply #1 on: July 13, 2010, 08:18:30 PM »
Hi Dave

A suspend state is 3ms of idle USB bus and the resume state is 10ms of inverted idle USB bus. This means that there should be at least 10ms between an suspend state (sleep) and a resume.

The driver expects either a suspend or a resume and activates the expected interrupt accordingly. In activating (often also as a consequence of the alternative interrupt having just occurred) the interrupt that just occurred is cleared and also any pending interrupt for the new change are reset before activating the alternative monitoring. This clearing of possible pending interrupts ensures than there is nothing waiting (from an old event) and so should make the technique unconditional on the past. [Note that it is usually good practice to clear possible pending interrupts when enabling specific interrupt sources].

In this case, due to the relatively long minimum time between these two interrupts, there should be no risk of clearing an interrupt in the same moment as it is occurring.

Finally, the methods used by different USB controllers are usually extremely different. This means that some techniques used are the result of lots of experimentation (reading the user's manual alone is not usually adequate to understand the internal workings) and also based on references from the semiconductor manufacturers. In the case of the suspend and resume interrupts the method used was based heavily on the Freescale reference which enables just one of the two state change interrupts at a time - based on the speed of interrupt detection and processing compared to maximum speed of state changes this did seem to be a suitable solution, so was followed.

I haven't seen problems with this yet - could you explain how you are testing? On the other hand I wouldn't expect any detrimental effects when the alternative interrupt is not cleared (just clearing the interrupt that has taken place) but don't understand at the moment why the exact solution should be critical (based on the description above) - it would be interesting in case you can identify a difference in behavior due to this.

Regards

Mark

Offline dkg

  • Newbie
  • *
  • Posts: 48
    • View Profile
Re: USB Sleep and Resume interrupts
« Reply #2 on: July 13, 2010, 08:29:46 PM »
Hi Mark,

The USB interface is giving us the sleep interrupt (USB Suspend) when the USB cable is near an EMI source (in this case it was an unshielded motor cable). I have debug messages print out in the USB application when processing a USB Suspend and USB Resume. I also now have internal counters (similar to the Eithernet counters) for USB events. We never see a resume but we see lots of suspends. And when that happens, we cannot re-establish USB communications without unplugging/plugging the USB cable presumably because the endpoints on the Coldfire end are still in a suspend state.

The Windows host computer never indicates a lost connection due to the noise. So we have a couple questions here. First, is the USB interface on our Coldfire-based device extra-sensitive to noise due to a design error or is it something we have to live with? Second, is this problem with missing resumes going to catch us when a temporary noise situation occurs and we can't recover communications without the cable pull. Although the unshielded motor cable is an extreme case, we all know that communications has to deal with spurious noise-induced errors and we want to be able to recover from it.

Dave G.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: USB Sleep and Resume interrupts
« Reply #3 on: July 13, 2010, 10:59:06 PM »
Hi Dave

An active full-speed USB connection will have the host sending a start of frame once every 1ms.

If interference is causing a suspend (sleep) it means that the interference has resulted in the device seeing the idle condition for longer than 3ms. Since this was not induced by the host the device will be in suspend mode but the host will still be sending the USB framework (start of frames every 1ms).

The device will be waiting for the resume state to be detected, which is an inverted idle period of longer than 10ms. Since the host is however still sending actively this will never be detected.

I therefore think that such a state is not recoverable without the host sending a resume state, which means that it needs to stop the active state (eg. send a real suspend) and then send a real resume - alternatively it could send a reset and re-enumerate, which is effectively what happens when unplugging and plugging again. Some classes will be sending data as well and will recognise that the device has a problem and automatically reset to try to recover (after a certain timeout).

Consequently I don't think that USB can tolerate such levels of interference. What I don't know is whether the level of interference is the problem (i.e. so much energy that the screening and differential mode are inadequate) or whether it is due to a weakness (eg. inadequate screening, badly connected cable earthing, or sensitivity in the circuitry). Make sure that the USB cable screen is not connected to 0V of the board but instead connected to the housing - this is a common mistake according to to an EMC tester that corrected a design of mine once - sometimes I also see ferrite beads in the grounding path, plus ESD protection on the lines.

Regards

Mark

Offline dkg

  • Newbie
  • *
  • Posts: 48
    • View Profile
Re: USB Sleep and Resume interrupts
« Reply #4 on: July 14, 2010, 03:00:28 PM »
Mark,

I am a little confused about this. If the device is waiting for an "inverted idle period" wouldn't that be happening because it will eventually see a start of frame every 1mSec coming from the host again? Or does the device need to see a resume state packet sent from the host?

How is it the device can be entering a sleep state multiple times without first resuming?

Our hardware guys are looking at the interface circuit to see if there is an error that is causing the noise sensitivity.

Dave G.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: USB Sleep and Resume interrupts
« Reply #5 on: July 14, 2010, 03:56:14 PM »
Hi Dave

An idle period is defined as >= 3ms of D+ at high potential and D- at low potential (for full-speed operation). When the host sends start of frames once very 1ms this should stop this being detected (that is also why it sends these all the time).

Interference must therefore be causing this state to appear to the device because it has moved to the sleep state (the interrupt now enables the detection of resume and disables further detection of suspend).

I wouldn't think that multiple suspend interrupts without resume interrupts between then should be possible since only one of these interrupt is enabled at a time and they operate as a ping-pong mechanism. Therefore I would check carefully that this is happening as you say.

An inverted idle period is >= 10ms of D+ at low potential and D- at high potential (). If the host is sending start of frames every ms this would effectively stop the resume state from being recognised; also between the start-of-frames the state of the bus is equivalent to the idle state.

This tells me that the interference is managing to cause the idle state to be recognised but not a following resume state. The resume state would require an inverted interference and also for this state to be present longer. The differential mode that USB uses should be quite resistant to interference and I would first expect data loss to occur (in bulk-mode this would results in repetitions). For the receiver to detect either idle or resume states it sounds as though the start of frames are not seen, which suggests the input is saturated in some way. Furthermore I could imaging that interference can much more easily cause the idle state to be detected by killing the host's transmission for a short time. This means that the lines are automatically in the idle state and so the suspend can be detected if three start-of-frames in a row are lost. It seems to me to be much more difficult for interference to generate the inverted idle state because it must both kill the host's start-of-frame transmissions and also invert both of the driven line states for longer than 10ms - this would be much more difficult to get to occur due to transient interference.

I hope that something is found in the HW to make it immune to the disturbances since I still don't think that USB can recover from such a situation.

Regards

Mark

Offline dkg

  • Newbie
  • *
  • Posts: 48
    • View Profile
Re: USB Sleep and Resume interrupts
« Reply #6 on: July 14, 2010, 04:12:24 PM »
Hi Mark,

Based on our USB event counters (and debug messages), we are definitely getting multiple suspend interrupts without a resume interrupt. In one test (before the motor encoder cable was grounded properly) our counters showed over 700 suspends with 0 resumes. I know the resume counter works because I have seen it count on normal resume states.

I don't see in the code where you are disabling the Sleep interrupt. You do enable/disable the Resume interrupt. Here is the snippet I have in USB_DRV.c:
Code: [Select]
           if (ucUSB_Int_status & SLEEP) {                              // suspend state detected - 3ms of idle USB bus detected (low speed D+ = 0, D- = 1 / high speed D+ = 1, D- = 0)
                INT_STAT = (SLEEP | RESUME);                             // reset flag
                INT_ENB |= RESUME_EN;                                    // enable resume interrupt
                fnUSB_handle_frame(USB_SUSPEND_DETECTED, 0, 0, 0);       // generic handler routine
            }
            if (ucUSB_Int_status & RESUME) {                             // resume detected - 10ms inverted idle USB bus state (low speed D+ = 1, D- = 0 / high speed D+ = 0, D- = 1)
            INT_STAT = (SLEEP | RESUME);                             // reset flag
                INT_ENB &= ~RESUME_EN;                                   // disable resume interrupt
                fnUSB_handle_frame(USB_RESUME_DETECTED, 0, 0, 0);        // generic handler routine
            }

I also hope it is a hardware issue ;)

Dave G.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: USB Sleep and Resume interrupts
« Reply #7 on: July 14, 2010, 04:50:04 PM »
Hi Dave

My mistake. The resume is enabled only when going to sleep but the sleep is not disabled, therefore there can be multiple sleep interrupt without a resume in between.

I don't know whether this is an issue in normal situations but I suppose the sleep interrupt could disable itself when enabling the resume interrupt. is enabled. Then you would get just one sleep interrupt. Presumable however never a resume interrupt though...

I suppose that the sleep interrupt triggers when the 3ms idle period is detected and re-triggers when there was a change before further detection. This change could however be any noise so I don't think there is any real significance of it arriving multiple times apart from the fact that the idle state really does get detected quite a lot.

Regards

Mark


Offline dkg

  • Newbie
  • *
  • Posts: 48
    • View Profile
Re: USB Sleep and Resume interrupts
« Reply #8 on: July 15, 2010, 01:46:13 PM »
Hi Mark,

So the issue of multiple suspends without a resume is possible and presumably only caused by the noise issue with the motor cable. It didn't make a difference when I tried clearing just the one interrupt state.

Our hardware guys say the interface design already implemented your suggestions except the ferrite beads. They will be testing that in the future.

I guess the only other thing we can say is that there is no practical way to recover from a suspend caused by noise other than a cable pull or having the host simulate a cable pull with a reset.

Thanks,
Dave G.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: USB Sleep and Resume interrupts
« Reply #9 on: July 15, 2010, 03:47:59 PM »
Hi Dave

That is my 'tentative' conclusion as well. I don't think that the USB protocol is robust enough to survive catastrophic interference.

Maybe this is a reason why it has not found widespread acceptance in industrial projects (?)

To get a workable solution don't forget to also try cable filtering, like using ferrite clamps since these are good at attenuating transients on the line. Try positioning one on the USB cable as close to the device as possible. Also don't exclude that the host may be being disturbed too, so a ferrite clamp on the host end may also make a difference.

Regards

Mark


Offline aaronlawrence

  • Jr. Member
  • **
  • Posts: 66
    • View Profile
Re: USB Sleep and Resume interrupts
« Reply #10 on: July 23, 2010, 06:31:18 AM »
Hello all,
Just noticed this topic.
We also have a lot of problems with EMC immunity and our USB connection.

I don't understand why the host is unable to detect the device has gone to sleep. Isn't it constantly accessing the device if it wants to send something by sending an IN token? It would expect to get either data or a NAK, if it gets neither it should be able to judge there's a problem...
I suppose if it were a one-way only (OUT tokens only) then maybe there's no response to Start of Frame, normally...


Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: USB Sleep and Resume interrupts
« Reply #11 on: July 23, 2010, 11:04:03 PM »
Hi Aaron

I think that the class used could play an important role.

The CDC class doesn't send any data when not being used (although it has an interrupt endpoint which I have never actually seen being used for anything...) and so the host probably doesn't have the chance to detect in what state the device is in - it is sending just the USB framework and doesn't expect any responses (although the interrupt endpoint could possibly detect something (?)).

When other classes are in operation there can be a lot of information exchanged even when there is no other activity. The host then recognises that there is a problem with a device and may reset it to try to cure it (thsi is however a detection at a higher level that detecting missing NAKs, for example).

However, the host is often outside the control of the embedded system that the device is a part of and so what a host does when it detects that a device is sleeping is also something that is probably not well specified - it could be operating system and driver version dependent. This is therefore something that can hardly be relied on.

I noticed that my Logitec CAM (with USB connection) has a ferrite integrated in the cable at the host end....

Regards

Mark

P.S. Since the host puts a device to sleep and doesn't normally expect a device going to sleep of its own accord I could well imaging that PC host drivers don't consider this case.