diff --git a/src/arduino.c b/src/arduino.c index 70072da7..73a0bd70 100644 --- a/src/arduino.c +++ b/src/arduino.c @@ -37,6 +37,45 @@ #include "stk500.h" #include "arduino.h" +static int arduino_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) { + const char *extended_param; + int attempts; + int rv = 0; + + for (LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) { + extended_param = ldata(ln); + + if (sscanf(extended_param, "attempts=%2d", &attempts) == 1) { + PDATA(pgm)->retry_attempts = attempts; + pmsg_info("setting number of retry attempts to %d\n", attempts); + continue; + } + + if(str_starts(extended_param, "no_autoreset")) { + if(!str_eq(extended_param, "no_autoreset")) { + pmsg_error("invalid -xno_autoreset value %s. Use -xno_autoreset\n", extended_param); + rv = -1; + break; + } + PDATA(pgm)->autoreset = false; + continue; + } + + if (str_eq(extended_param, "help")) { + msg_error("%s -c %s extended options:\n", progname, pgmid); + msg_error(" -xattempts= Specify no. connection retry attempts\n"); + msg_error(" -xno_autoreset Don't toggle RTS/DTR lines on port open to prevent a hardware reset\n"); + msg_error(" -xhelp Show this help menu and exit\n"); + return LIBAVRDUDE_EXIT; + } + + pmsg_error("invalid extended parameter '%s'\n", extended_param); + rv = -1; + } + + return rv; +} + /* read signature bytes - arduino version */ static int arduino_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m) { unsigned char buf[32]; @@ -85,28 +124,28 @@ static int arduino_open(PROGRAMMER *pgm, const char *port) { return -1; } - // This code assumes a negative-logic USB to TTL serial adapter - // Set RTS/DTR high to discharge the series-capacitor, if present - serial_set_dtr_rts(&pgm->fd, 0); - /* - * Long wait needed for optiboot: otherwise the second of two bootloader - * calls in quick succession fails: - * - * avrdude -c arduino -qqp m328p -U x.hex; avrdude -c arduino -qqp m328p -U x.hex - */ - usleep(250 * 1000); - // Pull the RTS/DTR line low to reset AVR - serial_set_dtr_rts(&pgm->fd, 1); - // Max 100 us: charging a cap longer creates a high reset spike above Vcc - usleep(100); - // Set the RTS/DTR line back to high, so direct connection to reset works - serial_set_dtr_rts(&pgm->fd, 0); + if(PDATA(pgm)->autoreset) { + // This code assumes a negative-logic USB to TTL serial adapter + // Set RTS/DTR high to discharge the series-capacitor, if present + serial_set_dtr_rts(&pgm->fd, 0); + /* + * Long wait needed for optiboot: otherwise the second of two bootloader + * calls in quick succession fails: + * + * avrdude -c arduino -qqp m328p -U x.hex; avrdude -c arduino -qqp m328p -U x.hex + */ + usleep(250 * 1000); + // Pull the RTS/DTR line low to reset AVR + serial_set_dtr_rts(&pgm->fd, 1); + // Max 100 us: charging a cap longer creates a high reset spike above Vcc + usleep(100); + // Set the RTS/DTR line back to high, so direct connection to reset works + serial_set_dtr_rts(&pgm->fd, 0); - usleep(100 * 1000); + usleep(100 * 1000); + } - /* - * drain any extraneous input - */ + // Drain any extraneous input stk500_drain(pgm, 0); if (stk500_getsync(pgm) < 0) @@ -115,7 +154,7 @@ static int arduino_open(PROGRAMMER *pgm, const char *port) { return 0; } -static void arduino_close(PROGRAMMER * pgm) +static void arduino_close(PROGRAMMER *pgm) { serial_close(&pgm->fd); pgm->fd.ifd = -1; @@ -131,9 +170,12 @@ void arduino_initpgm(PROGRAMMER *pgm) { stk500_initpgm(pgm); strcpy(pgm->type, "Arduino"); + PDATA(&pgm)->autoreset = true; // Auto-reset enabled by default + pgm->read_sig_bytes = arduino_read_sig_bytes; pgm->open = arduino_open; pgm->close = arduino_close; + pgm->parseextparams = arduino_parseextparms; cx->avr_disableffopt = 1; // Disable trailing 0xff removal } diff --git a/src/stk500.c b/src/stk500.c index d3a4b0b6..a7c5657e 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -116,7 +116,7 @@ int stk500_getsync(const PROGRAMMER *pgm) { for (attempt = 0; attempt < max_sync_attempts; attempt++) { // Restart Arduino bootloader for every sync attempt - if (str_eq(pgm->type, "Arduino") && attempt > 0) { + if (PDATA(pgm)->autoreset && attempt > 0) { // This code assumes a negative-logic USB to TTL serial adapter // Pull the RTS/DTR line low to reset AVR: it is still high from open()/last attempt serial_set_dtr_rts(&pgm->fd, 1); diff --git a/src/stk500.h b/src/stk500.h index 6c9b8188..50984a51 100644 --- a/src/stk500.h +++ b/src/stk500.h @@ -60,6 +60,9 @@ struct pdata { double fosc_data; unsigned xtal; // Set STK500 XTAL frequency + + // Flag to enable/disable autoreset for the arduino programmer + bool autoreset; }; #define PDATA(pgm) ((struct pdata *)(pgm->cookie))