Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added missing RTS/DTR management feature to serialupdi programmer #811

Merged
merged 8 commits into from
Jan 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/avrdude.1
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,17 @@ line, and the XBee DIN pin (pin 3) must be connected to the MCU's
.Ql TXD
line.
.El
.It Ar serialupdi
Extended parameters:
.Bl -tag -offset indent -width indent
.It Ar 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.
.Pp
When not provided, driver/OS default value will be used.
.El
.El
.Sh FILES
.Bl -tag -offset indent -width /dev/ppi0XXX
Expand Down
12 changes: 12 additions & 0 deletions src/doc/avrdude.texi
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 39 additions & 0 deletions src/serialupdi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -184,6 +185,10 @@ static void serialupdi_close(PROGRAMMER * pgm)
if (serialupdi_leave_progmode(pgm) < 0) {
avrdude_message(MSG_INFO, "%s: Unable to leave NVM programming mode\n", progname);
}
if (updi_get_rts_mode(pgm) != RTS_MODE_DEFAULT) {
avrdude_message(MSG_INFO, "%s: Releasing DTR/RTS handshake lines\n", progname);
}

updi_link_close(pgm);
}

Expand Down Expand Up @@ -582,6 +587,10 @@ static int serialupdi_initialize(PROGRAMMER * pgm, AVRPART * p)
}
avrdude_message(MSG_INFO, "%s: UPDI link initialization OK\n", progname);

if (updi_get_rts_mode(pgm) != RTS_MODE_DEFAULT) {
avrdude_message(MSG_INFO, "%s: Forcing serial DTR/RTS handshake lines %s\n", progname, updi_get_rts_mode(pgm) == RTS_MODE_LOW ? "LOW" : "HIGH");
}

if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {

/* let's try reset the connection */
Expand Down Expand Up @@ -926,6 +935,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)
{
Expand All @@ -936,6 +974,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;
Expand Down
34 changes: 25 additions & 9 deletions src/updi_link.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}

updi_set_rtsdtr_mode(pgm);

buffer[0] = UPDI_BREAK;

serial_send(&pgm->fd, buffer, 1);
serial_recv(&pgm->fd, buffer, 1);

msleep(100);
usleep(100*1000);

buffer[0] = UPDI_BREAK;

serial_send(&pgm->fd, buffer, 1);
serial_recv(&pgm->fd, buffer, 1);

updi_physical_close(pgm);
if (serial_setparams(&pgm->fd, pgm->baudrate? pgm->baudrate: 115200, SERIAL_8E2) < 0) {
return -1;
}

updi_set_rtsdtr_mode(pgm);

return updi_physical_open(pgm, pgm->baudrate? pgm->baudrate: 115200, SERIAL_8E2);
return 0;
}

int updi_physical_sib(PROGRAMMER * pgm, unsigned char * buffer, uint8_t size)
Expand Down
10 changes: 10 additions & 0 deletions src/updi_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
10 changes: 10 additions & 0 deletions src/updi_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
Expand Down