arduino / ArduinoCore-avr

The Official Arduino AVR core
https://www.arduino.cc
1.24k stars 1.05k forks source link

Burning bootloader with AVR dragon using either IDE or Makefiles bricks AVR. [imported] #222

Open cmaglie opened 11 years ago

cmaglie commented 11 years ago

This is Issue 650 moved from a Google Code project. Added by 2011-09-22T20:33:15.000Z by bperry...@gmail.com. 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.

  1. add a blind delay between the two avrdude commands (in IDE and Makefiles)
  2. Update the avrdude code to poll for the devices for a few seconds rather than just look one time.
  3. Alter the IDE and Makefiles to use a single avrdude command rather than two. arduino/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.

WestfW commented 9 years ago

Fixed in the optiboot repository in v6.0: https://code.google.com/p/optiboot/issues/detail?id=46 (for the optiboot makefile *_isp targets. It doesn't fix the arduino IDE's use of avrdude.)

bperrybap commented 9 years ago

Can we get some movement on this? It is going on 4 years now and the patch to fix it in avrdude is still not being accepted into the mainline avrdude project source. It could be fixed in avrdude in the Arduino version of the avrdude code or the Arduino IDE could be changed to do the operation in a single command rather than 2 commands which avoids the problem which is what the optiboot makefile now does.

Either of these fixes is very small and easy to test. While fixing it in avrdude is where it really should be fixed, it may be more desirable to alter the IDE to work around the avrdude bug instead to avoid having to maintain a modified version of avrdude and also ensure that the IDE works with the unpatched versions of avrdude.

This is not just an AVR dragon issue. Here is a recent thread that is experiencing this same issue on a different Atmel programming device: http://forum.arduino.cc/index.php?topic=316061

I wish avrdude would be fixed but Joerg does not seem to want to fix this in avrdude but rather have it fixed in libusb, but yet it is avrdude that resets the USB when it is exits and then it is avrdude code that is not waiting for the USB enumeration to complete after the USB is reset which is what creates the issue.

bperrybap commented 7 years ago

2 more years have passed and this is still an issue. The fix is a mere 7 lines of code to avrdude.

nmaas87 commented 5 years ago

Any update on this?

per1234 commented 5 years ago

Related issue: https://github.com/arduino/ArduinoCore-avr/issues/9

And possibly: https://github.com/arduino/Arduino/issues/2986

At the time https://github.com/arduino/ArduinoCore-avr/issues/9 was submitted, I looked into the possibility of working around the problem by combining the "erase" and "bootloader" actions into a single command but I couldn't verify that it worked because I don't own a Dragon.

nmaas87 commented 5 years ago

@per1234 I do own one, so I could help with that, just need to know what I should do ;).

per1234 commented 5 years ago

@nmaas87 I don't have time to work on it right now, but I'll give you a ping once work slows down for me after Christmas to see if we can work together on this.

If Arduino ends up not being interested in adding official support for the Dragon, I should be able to make a 3rd party hardware package (installable via Boards Manager) that adds a Dragon programmer to the Arduino IDE.

nmaas87 commented 5 years ago

@per1234 That sounds awesome to me :). Thank you very much!

nmaas87 commented 2 years ago

@per1234 made some PoC at that time: https://github.com/per1234/InoAVRDragon