Description
This is Issue 650 moved from a Google Code project.
Added by 2011-09-22T20:33:15.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Original labels: Type-Defect, Priority-Medium
Original description
When attempting to burn a bootloader using either the IDE Burn Bootloader option
or any of the Makefiles down in the hardware/arduino/bootloaders/xxx
the fuses will be burned and the flash erased but the bootloader is not burned
resulting in a non operational chip.
This behavior is easily reproducible on both windows and Ubuntu linux.
It is probably an issue other OSs and
potentially an issue with other USB ISP programmers.
This is not a permissions issue or a libusb installation/configuration issue.
This is due to an interaction between how the burning tool
(IDE or Makefile) is using avrdude, avrdude itself, libusb and the OS.
The crux of the problem is that two avrdude commands are being used to burn
a bootloader. One command to set the fuses and erase the flash and another
to burn the bootloader to the flash.
The 2nd avrdude command is failing because it can't locate the USB device.
Digging deeper, the problem is that when the avrdude command finishes
using the USB device, it resets the USB device.
This reset cause the USB device to have to go
through enumeration again. This enumeration takes time. If another avrdude
command runs before the enumeration is complete, it will not see the USB
device on the USB bus.
The reset cannot be removed because for some reason if the USB device is
not reset, it will fail to communicate properly. There is probably some
other issue either in the OS or libusb itself that is causing this issue.
In my view this really is an avrdude command issue or at least an
issue that avrdude could resolve.
I went so far as to enter a bug for it on savannah:
https://savannah.nongnu.org/bugs/?34339
So far, it was not well received as the avrdude maintainer
considers this to be an OS issue rather than an avrdude issue.
There are some options to work around this.
- add a blind delay between the two avrdude commands (in IDE and Makefiles)
- Update the avrdude code to poll for the devices for a few seconds
rather than just look one time. - Alter the IDE and Makefiles to use a single avrdude command rather than two.
Add files used in Linux packages Arduino#1)
Currently, it looks like there already is a 1 second blind delay in the IDE
code down in AvrdudeUploader.java in the burnBootloader() function.
The problem is that 1 second is not long enough.
From my experimentation on some of my machines, on Ubuntu 10.10
2 seconds seems to work. While I didn't fully test this
on Windows to find the exact time needed,
I can say that on my older 1.6Ghz Dell, it takes longer
than 2 seconds for the enumeration to complete.
The problem with these blind delays is that it slows down things for everyone
since the full wait is always done and there is no way to really know what
the best value to pick is.
arduino/Arduino#2)
It is possible to modify the avrdude code to be smarter to try to
poll "a while" looking for USB devices rather than just look one time.
I modified the code in usb_libusb.c to do this (it is only 7 lines of code)
and placed a patch for it in the savannah bug noted above.
This update works great, it polls the USB every 1/10 of second until
it finds the desired USB device - using a maximum delay of 3 seconds
(Probably should up this to 5 seconds.)
The nice thing is it will now only delay as long
as needed and only the full time if truely there is a problem. On my Ubuntu 10.10
machine the delay is just over 1 second.
But given the initial reception for updating avrdude to compensate
for the USB device behavior, this type of change probabaly will not be
accepted or at least may be well beyond the uno 1.0 release timeframe.
arduino/Arduino#3)
Perhaps the best way to deal with the issue is to avoid it
completely by changing things to burn the fuses and the bootloader
in a single avrdude command.
It is a vary small change to modify the java code and the Makefiles
to use a single avrdude comman rather than two.
Not only will doing this avoid the issue, but it will speed up
the bootloader burning process by avoiding the overhead of a blind
delay and the overhead of a second avrdude command.
It may also help in some cases with AutoReset issues on non USB
devices as there will no longer be a port close and re-open between
setting the fuses and burning the bootloade since it would all
now be done with a single call to avrdude.
I modified the optiboot Makefile in westfw's latest optiboot working tree
to do this as an example.
(See attachment). It was a very small change and this change
can and probably should be propagated through all the other Makefiles as well.
It is very simple and impacts no other code.
The JAVA code can easily do the same.
So down in burnBootLoader() rather than call avrdude() and then
Thread.sleep(1000)
Just build up a single List for both the fuses and the bootloader
I've attached an untested attempt at what that could look like.