diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 06a40219..784e5a56 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1067,6 +1067,18 @@ The remaining two necessary XBee-to-MCU connections are not selectable the MCU's ‘TXD’ line. @end table +@item serialupdi +Extended parameters: +@table @code +@item @samp{rtsdtr=low|high} +Forces RTS/DTR lines to assume low or high state during the whole +programming session. Some programmers might use this signal to +indicate UPDI programming state, but this is strictly hardware +specific. + +When not provided, driver/OS default value will be used. +@end table + @end table @page diff --git a/src/serialupdi.c b/src/serialupdi.c index 839d7d81..32fffb99 100644 --- a/src/serialupdi.c +++ b/src/serialupdi.c @@ -55,6 +55,7 @@ static void serialupdi_setup(PROGRAMMER * pgm) exit(1); } memset(pgm->cookie, 0, sizeof(updi_state)); + updi_set_rts_mode(pgm, RTS_MODE_DEFAULT); updi_set_datalink_mode(pgm, UPDI_LINK_MODE_16BIT); } @@ -926,6 +927,35 @@ static int serialupdi_read_sib(PROGRAMMER * pgm, AVRPART *p, char *sib) { return 0; } +static int serialupdi_parseextparms(PROGRAMMER * pgm, LISTID extparms) +{ + LNODEID ln; + const char *extended_param; + char rts_mode[5]; + int rv = 0; + + for (ln = lfirst(extparms); ln; ln = lnext(ln)) { + extended_param = ldata(ln); + + if (sscanf(extended_param, "rtsdtr=%4s", rts_mode) == 1) { + if (strcasecmp(rts_mode, "low") == 0) { + updi_set_rts_mode(pgm, RTS_MODE_LOW); + } else if (strcasecmp(rts_mode, "high") == 0) { + updi_set_rts_mode(pgm, RTS_MODE_HIGH); + } else { + avrdude_message(MSG_INFO, "%s: RTS/DTR mode must be LOW or HIGH\n", progname); + return -1; + } + continue; + } + + avrdude_message(MSG_INFO, "%s: serialupdi_parseextparms(): invalid extended parameter '%s'\n", + progname, extended_param); + rv = -1; + } + + return rv; +} void serialupdi_initpgm(PROGRAMMER * pgm) { @@ -936,6 +966,7 @@ void serialupdi_initpgm(PROGRAMMER * pgm) */ pgm->initialize = serialupdi_initialize; + pgm->parseextparams = serialupdi_parseextparms; pgm->display = serialupdi_display; pgm->enable = serialupdi_enable; pgm->disable = serialupdi_disable; diff --git a/src/updi_link.c b/src/updi_link.c index 157c81b2..f87f8a83 100644 --- a/src/updi_link.c +++ b/src/updi_link.c @@ -39,9 +39,16 @@ #include "updi_constants.h" #include "updi_state.h" -static void msleep(int tms) +static void updi_set_rtsdtr_mode(PROGRAMMER* pgm) { - usleep(tms * 1000); + updi_rts_mode rts_mode = updi_get_rts_mode(pgm); + + if (rts_mode == RTS_MODE_DEFAULT) { + return; + } + + serial_set_dtr_rts(&pgm->fd, 0); + serial_set_dtr_rts(&pgm->fd, rts_mode == RTS_MODE_LOW ? 1 : 0); } static int updi_physical_open(PROGRAMMER* pgm, int baudrate, unsigned long cflags) @@ -65,11 +72,17 @@ static int updi_physical_open(PROGRAMMER* pgm, int baudrate, unsigned long cflag */ serial_drain(&pgm->fd, 0); + /* + * set RTS/DTR mode if needed + */ + updi_set_rtsdtr_mode(pgm); + return 0; } static void updi_physical_close(PROGRAMMER* pgm) { + serial_set_dtr_rts(&pgm->fd, 0); serial_close(&pgm->fd); pgm->fd.ifd = -1; } @@ -124,28 +137,31 @@ static int updi_physical_send_double_break(PROGRAMMER * pgm) avrdude_message(MSG_DEBUG, "%s: Sending double break\n", progname); - updi_physical_close(pgm); - - if (updi_physical_open(pgm, 300, SERIAL_8E1)==-1) { - + if (serial_setparams(&pgm->fd, 300, SERIAL_8E1) < 0) { return -1; } - buffer[0] = UPDI_BREAK; - - serial_send(&pgm->fd, buffer, 1); - serial_recv(&pgm->fd, buffer, 1); - - msleep(100); + updi_set_rtsdtr_mode(pgm); buffer[0] = UPDI_BREAK; serial_send(&pgm->fd, buffer, 1); serial_recv(&pgm->fd, buffer, 1); - updi_physical_close(pgm); + usleep(100*1000); - return updi_physical_open(pgm, pgm->baudrate? pgm->baudrate: 115200, SERIAL_8E2); + buffer[0] = UPDI_BREAK; + + serial_send(&pgm->fd, buffer, 1); + serial_recv(&pgm->fd, buffer, 1); + + if (serial_setparams(&pgm->fd, pgm->baudrate? pgm->baudrate: 115200, SERIAL_8E2) < 0) { + return -1; + } + + updi_set_rtsdtr_mode(pgm); + + return 0; } int updi_physical_sib(PROGRAMMER * pgm, unsigned char * buffer, uint8_t size) diff --git a/src/updi_state.c b/src/updi_state.c index 63d80f46..2ca583c7 100644 --- a/src/updi_state.c +++ b/src/updi_state.c @@ -53,3 +53,13 @@ void updi_set_nvm_mode(PROGRAMMER * pgm, updi_nvm_mode mode) { ((updi_state *)(pgm->cookie))->nvm_mode = mode; } + +updi_rts_mode updi_get_rts_mode(PROGRAMMER * pgm) +{ + return ((updi_state *)(pgm->cookie))->rts_mode; +} + +void updi_set_rts_mode(PROGRAMMER * pgm, updi_rts_mode mode) +{ + ((updi_state *)(pgm->cookie))->rts_mode = mode; +} diff --git a/src/updi_state.h b/src/updi_state.h index d4e39d4c..a8a2702a 100644 --- a/src/updi_state.h +++ b/src/updi_state.h @@ -61,11 +61,19 @@ typedef struct char debug_version; } updi_sib_info; +typedef enum +{ + RTS_MODE_DEFAULT, + RTS_MODE_LOW, + RTS_MODE_HIGH +} updi_rts_mode; + typedef struct { updi_sib_info sib_info; updi_datalink_mode datalink_mode; updi_nvm_mode nvm_mode; + updi_rts_mode rts_mode; } updi_state; #ifdef __cplusplus @@ -77,6 +85,8 @@ updi_datalink_mode updi_get_datalink_mode(PROGRAMMER * pgm); void updi_set_datalink_mode(PROGRAMMER * pgm, updi_datalink_mode mode); updi_nvm_mode updi_get_nvm_mode(PROGRAMMER * pgm); void updi_set_nvm_mode(PROGRAMMER * pgm, updi_nvm_mode mode); +updi_rts_mode updi_get_rts_mode(PROGRAMMER * pgm); +void updi_set_rts_mode(PROGRAMMER * pgm, updi_rts_mode mode); #ifdef __cplusplus }