Page 1 of 2

AVR_USB timing out?

Posted: Mon Mar 10, 2008 11:49 pm
by queuetue
I've build a device based on the powerswitch demo on an atmega324p, and it works very nicely - until I leave it alone for 10 to 15 minutes. Then, when I try to run the commandline app from ubuntu linux, I get:

Warning: cannot query manufacturer for device: error sending control message: Timer expired


Hitting the reset switch or disconnecting and reconnecting the device allows it to work again. I have a flasher running in the main app, so I can tell the avr is still powered and running.

Does anyone have any ideas why it would stop working?

Posted: Tue Mar 11, 2008 11:09 am
by christian
If you get a timeout, this probably means that USB communication is unreliable (too many retries). This may happen if the USB interrupt is serviced too late, e.g. because you have another interrupt which has to finish before the USB interrupt routine can run.

Please make sure that all other interrupts are declared with __attribute__ ((interrupt)) so that they can be interrupted.

Posted: Tue Mar 11, 2008 3:35 pm
by queuetue
It seemed fine overnight last night - could it be a brownout issue? I know the long reset period at startup is supposed to overcome that, but I don't think it can e timing issues - the avr is hardly doing anything but usb right now, with no other interrupts in use.

Posted: Tue Mar 11, 2008 7:12 pm
by christian
Brownout means that the supply voltage is close to the minimum operating voltage of the device. I doubt this. The long delay at the beginning of main() has nothing to do with brownout, it is there to ensure that the host sees a device reconnect at every reset so that enumeration is started. This affects brownout resets and watchdog resets, of course.

It is still possible that an electrical parameter is close to the limit, e.g. the voltage levels on D+ and D- or timing delays due to the capacitance of the Zener diodes (if you use zeners). If you run off the RC oscillator, it may also be an oscillator frequency drift.

Posted: Fri Mar 14, 2008 4:37 pm
by Guest
I happened to have the uart hooked up on debug level 1 when it did this "timeout" thing on me. All i see (after normal debugging for my app, then 20 minutes of silence) was three restarts from avr-usb while I was not using the device. After those restarts, the device is no longer working until I do a reset. The restarts happened before I tried to communicate with the app.

Does this shed any light? I'll put it on debug level 2 and try to capture another event.

Posted: Sat Mar 15, 2008 1:47 pm
by christian
If your firmware restarts at main(), you must have some kind of reset. This can be a brownout-reset, a watchdog reset or a spike on the supply line or RESET line which causes a hardware reset.

If the device goes through a reset, it starts with USB address 0. The host must start an enumeration in order to assign a new USB address, otherwise it addresses the device under its old address. An enumeration is done when the host sees a disconnect on the USB. We therefore have a USB disconnect (D+ and D- = 0) in main(). This disconnect should last for at least several 100 ms so that the host detects it reliably. Old reference projects had only a couple of milliseconds and many example projects still have this short disconnect period. They may fail to enumerate after a reset and thus become inaccessible.

If you see a hardware reset, you should look out for the cause of that, of course. It may be a nearby fluorescent lamp which causes a spike on RESET, a missing decoupling capacitor on the supply or something like that.

Posted: Sun Mar 16, 2008 5:47 pm
by queuetue
I've removed the zeners and the problem appears to have gone away. If I ever need to put them back in for compatability, I suspect I have a voltage level issue I will need to resolve.

Posted: Sun Mar 16, 2008 11:29 pm
by christian
What zener diodes did you use? Low power 3.6 V types should give enough voltage with the pull-up resistor on D- so that the device is detected. If you go below the threshold of I think 1.7 V, the host may not detect the device or see a disconnect every now and then.

Another possibility is the capacitance of the zeners. High power types have a big capacitance which may distort the timing.

Posted: Sun Mar 16, 2008 11:52 pm
by queuetue
They were 500mw D0-35 1n5227b zeners.

Posted: Mon Mar 17, 2008 12:37 pm
by christian
That should be OK. Maybe the pull-up is too high?

same problem here

Posted: Fri Mar 28, 2008 12:41 pm
by xtremely
hi
I got the same problem here. I removed the zener diodes, but my device is still not reachable after about half an hour.
If your firmware restarts at main(), you must have some kind of reset. This can be a brownout-reset, a watchdog reset or a spike on the supply line or RESET line which causes a hardware reset.

So it is normal that my device might dsconnect and then connect again without getting into trouble with the client program sending commands to the device?

This disconnect should last for at least several 100 ms so that the host detects it reliably. Old reference projects had only a couple of milliseconds and many example projects still have this short disconnect period.


in the code I can see this part:

Code: Select all

int main(void) {
    uchar i, j;
    odDebugInit();
    DDRD = ~0;                  /* output SE0 for USB reset */
    PORTD = 0x00;               /* no pullups on USB pins */
    DDRC = 0xff;                /* all outputs */
    PORTC = 0x00;

    j = 0;
    while (--j) {               /* USB Reset by device only required on
                                   Watchdog Reset */
        i = 0;
        while (--i);            /* delay >10ms for USB reset */
    }
    DDRD = ~USBMASK;            /* all outputs except USB data */
    TCCR0 = 5;                  /* set prescaler to 1/1024 */
    usbInit();
    sei();

should I try to replace the while (--i); with a delay for about 200ms? (sry but i'm quite new to microcontrollers and programming stuff)

Posted: Fri Mar 28, 2008 2:56 pm
by christian
So it is normal that my device might dsconnect and then connect again without getting into trouble with the client program sending commands to the device?

No, this is not normal. But IF you get these resets, you can at least fight the symptom and write the firmware, driver and application so that a reconnect is possible.

We now recommend the following sequence (requires the newest driver version so that usbDevice[Dis]connect() works as it should):

Code: Select all

int main(void)
{
    uchar i;
    usbInit();
    /* enforce USB re-enumerate: */
    usbDeviceDisconnect();  /* do this while interrupts are disabled */
    for(i=0;--i;){          /* fake USB disconnect for > 250 ms */
        _delay_ms(1);
    }
    usbDeviceConnect();
    ....
    sei();
    for(;;){ /* main loop */
        usbPoll();
        ....
    }
}

Posted: Tue Apr 08, 2008 9:45 am
by iphi
If you use new AVR chip types make sure to switch off the watchdog timer before reenumeration as the late AVR MCUs don't switch off the watchdog on reset. If the watchdog is still running after a reset, reenumeration will fail.

See my posting here for details:
http://forums.obdev.at/viewtopic.php?t=1202

Tom

Re: same problem here

Posted: Mon Apr 14, 2008 8:14 pm
by spiff
xtremely wrote:

Code: Select all

    while (--j) {               /* USB Reset by device only required on
                                   Watchdog Reset */
        i = 0;
        while (--i);            /* delay >10ms for USB reset */
    }


I have seen many problems with this construction after switching to a newer avr-gcc (based on gcc4). The delay loops get optimized away. Use _delay_ms from util/delay.h instead.

Posted: Mon Apr 14, 2008 8:16 pm
by christian
Newer versions of PowerSwitch use the delay function (eith a much longer delay, BTW) instead.