General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
-
queuetue
- Posts: 7
- Joined: Thu Feb 21, 2008 12:59 am
Post
by queuetue » Mon Mar 10, 2008 11:49 pm
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?
-
christian
- Objective Development
- Posts: 1443
- Joined: Thu Nov 09, 2006 11:46 am
Post
by christian » Tue Mar 11, 2008 11:09 am
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.
-
queuetue
- Posts: 7
- Joined: Thu Feb 21, 2008 12:59 am
Post
by queuetue » Tue Mar 11, 2008 3:35 pm
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.
-
christian
- Objective Development
- Posts: 1443
- Joined: Thu Nov 09, 2006 11:46 am
Post
by christian » Tue Mar 11, 2008 7:12 pm
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.
-
Guest
Post
by Guest » Fri Mar 14, 2008 4:37 pm
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.
-
christian
- Objective Development
- Posts: 1443
- Joined: Thu Nov 09, 2006 11:46 am
Post
by christian » Sat Mar 15, 2008 1:47 pm
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.
-
queuetue
- Posts: 7
- Joined: Thu Feb 21, 2008 12:59 am
Post
by queuetue » Sun Mar 16, 2008 5:47 pm
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.
-
christian
- Objective Development
- Posts: 1443
- Joined: Thu Nov 09, 2006 11:46 am
Post
by christian » Sun Mar 16, 2008 11:29 pm
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.
-
queuetue
- Posts: 7
- Joined: Thu Feb 21, 2008 12:59 am
Post
by queuetue » Sun Mar 16, 2008 11:52 pm
They were 500mw D0-35 1n5227b zeners.
-
christian
- Objective Development
- Posts: 1443
- Joined: Thu Nov 09, 2006 11:46 am
Post
by christian » Mon Mar 17, 2008 12:37 pm
That should be OK. Maybe the pull-up is too high?
-
xtremely
Post
by xtremely » Fri Mar 28, 2008 12:41 pm
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)
-
christian
- Objective Development
- Posts: 1443
- Joined: Thu Nov 09, 2006 11:46 am
Post
by christian » Fri Mar 28, 2008 2:56 pm
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();
....
}
}
-
iphi
- Rank 2
- Posts: 68
- Joined: Mon Jun 25, 2007 11:37 am
Post
by iphi » Tue Apr 08, 2008 9:45 am
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
-
spiff
- Rank 1
- Posts: 24
- Joined: Tue Apr 17, 2007 1:00 am
- Location: Virum, Denmark
-
Contact:
Post
by spiff » Mon Apr 14, 2008 8:14 pm
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.
-
christian
- Objective Development
- Posts: 1443
- Joined: Thu Nov 09, 2006 11:46 am
Post
by christian » Mon Apr 14, 2008 8:16 pm
Newer versions of PowerSwitch use the delay function (eith a much longer delay, BTW) instead.