After researching the problem I resorted to the following workaround.
I wrote a Python wrapper for avrdude that detects if "-P PORT" option is present in the arguments and performs a soft reset as expected by Arduino Micro/Leonardo. Then the wrapper calls the real avrdude passing all the arguments.
Feel free to post updates here if you find a way to improve the script. The initial version probably misses some possible avrdude usage scenarios and might not handle all errors. For example, one strange thing happens when Eclipse AVR plugin runs avrdude with "-c?" option to get the list of supported programmers. When executed (even from the command line) avrdude returns the list but for some reason exits with a non-zero exit code. So error handling of subprocess.check_call had to be commented out.
Solution has been tested on Ubuntu 11.10 running Eclipse Juno, Arduino IDE 1.0.2 (Eclipse AVR plugin uses its tools), avrdude version 5.11 and Arduino Micro board. Just rename the real avrdude as avrdude.orig and copy paste the code to a new avrdude file. No more hardware resets before uploading the code!
- Code: Select all
#!/usr/bin/env python
import sys
import subprocess
import serial
import argparse
import time
# path to the real avrdude
AVRDUDE_PATH="/opt/arduino-1.0.2/hardware/tools"
# real name of avrdude
AVRDUDE_NAME="avrdude.orig"
# prepare argument parser to understand -P PORT
parser = argparse.ArgumentParser()
parser.add_argument("-P", dest="port")
# parse only known parameters
args = parser.parse_known_args()
# if port argument is present perform soft reset
if args[0].port:
try: # try to initiate serial port connection on PORT with 1200 baudrate
ser = serial.Serial(
port=args[0].port,
baudrate=1200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
except serial.SerialException, e:
print "pySerial error: " + str(e) + "\n"
sys.exit(1)
try: # try to open PORT
ser.isOpen()
except serial.SerialException:
print "pySerial error: " + str(e) + "\n"
sys.exit(1)
# and close it immediately signaling to bootloader that flashing is imminent
ser.close()
# wait 2 second to ensure Arduino is ready
time.sleep(2)
# args is a tuple with parsed -P PORT and the rest of the arguments, so it needs to be join back
avrdude_args=" ".join(str(x) for x in args[1]) + " -P" + args[0].port
else: # if no port argument is present
# join all other arguments to be ready for avrdude invokation
avrdude_args=" ".join(str(x) for x in args[1])
try: # try to invoke avrdude passing all the options
subprocess.check_call(AVRDUDE_PATH + "/" + AVRDUDE_NAME + " " + avrdude_args, shell=True)
except subprocess.CalledProcessError, e: pass
# print "avrdude error:\n", e.output
# sys.exit(2)
sys.exit()