Merge pull request #811 from dbuchwald/main

Added missing RTS/DTR management feature to serialupdi programmer
This commit is contained in:
Jörg Wunsch 2022-01-14 08:24:58 +01:00 committed by GitHub
commit b99687f33c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 112 additions and 14 deletions

View File

@ -1186,6 +1186,17 @@ line, and the XBee DIN pin (pin 3) must be connected to the MCU's
.Ql TXD .Ql TXD
line. line.
.El .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 .El
.Sh FILES .Sh FILES
.Bl -tag -offset indent -width /dev/ppi0XXX .Bl -tag -offset indent -width /dev/ppi0XXX

View File

@ -1067,6 +1067,18 @@ The remaining two necessary XBee-to-MCU connections are not selectable
the MCU's TXD line. the MCU's TXD line.
@end table @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 @end table
@page @page

View File

@ -55,6 +55,7 @@ static void serialupdi_setup(PROGRAMMER * pgm)
exit(1); exit(1);
} }
memset(pgm->cookie, 0, sizeof(updi_state)); memset(pgm->cookie, 0, sizeof(updi_state));
updi_set_rts_mode(pgm, RTS_MODE_DEFAULT);
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_16BIT); updi_set_datalink_mode(pgm, UPDI_LINK_MODE_16BIT);
} }
@ -184,6 +185,10 @@ static void serialupdi_close(PROGRAMMER * pgm)
if (serialupdi_leave_progmode(pgm) < 0) { if (serialupdi_leave_progmode(pgm) < 0) {
avrdude_message(MSG_INFO, "%s: Unable to leave NVM programming mode\n", progname); 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); updi_link_close(pgm);
} }
@ -582,6 +587,10 @@ static int serialupdi_initialize(PROGRAMMER * pgm, AVRPART * p)
} }
avrdude_message(MSG_INFO, "%s: UPDI link initialization OK\n", progname); 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) { if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {
/* let's try reset the connection */ /* let's try reset the connection */
@ -926,6 +935,35 @@ static int serialupdi_read_sib(PROGRAMMER * pgm, AVRPART *p, char *sib) {
return 0; 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) void serialupdi_initpgm(PROGRAMMER * pgm)
{ {
@ -936,6 +974,7 @@ void serialupdi_initpgm(PROGRAMMER * pgm)
*/ */
pgm->initialize = serialupdi_initialize; pgm->initialize = serialupdi_initialize;
pgm->parseextparams = serialupdi_parseextparms;
pgm->display = serialupdi_display; pgm->display = serialupdi_display;
pgm->enable = serialupdi_enable; pgm->enable = serialupdi_enable;
pgm->disable = serialupdi_disable; pgm->disable = serialupdi_disable;

View File

@ -39,9 +39,16 @@
#include "updi_constants.h" #include "updi_constants.h"
#include "updi_state.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) 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); serial_drain(&pgm->fd, 0);
/*
* set RTS/DTR mode if needed
*/
updi_set_rtsdtr_mode(pgm);
return 0; return 0;
} }
static void updi_physical_close(PROGRAMMER* pgm) static void updi_physical_close(PROGRAMMER* pgm)
{ {
serial_set_dtr_rts(&pgm->fd, 0);
serial_close(&pgm->fd); serial_close(&pgm->fd);
pgm->fd.ifd = -1; 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); avrdude_message(MSG_DEBUG, "%s: Sending double break\n", progname);
updi_physical_close(pgm); if (serial_setparams(&pgm->fd, 300, SERIAL_8E1) < 0) {
if (updi_physical_open(pgm, 300, SERIAL_8E1)==-1) {
return -1; return -1;
} }
buffer[0] = UPDI_BREAK; updi_set_rtsdtr_mode(pgm);
serial_send(&pgm->fd, buffer, 1);
serial_recv(&pgm->fd, buffer, 1);
msleep(100);
buffer[0] = UPDI_BREAK; buffer[0] = UPDI_BREAK;
serial_send(&pgm->fd, buffer, 1); serial_send(&pgm->fd, buffer, 1);
serial_recv(&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) int updi_physical_sib(PROGRAMMER * pgm, unsigned char * buffer, uint8_t size)

View File

@ -53,3 +53,13 @@ void updi_set_nvm_mode(PROGRAMMER * pgm, updi_nvm_mode mode)
{ {
((updi_state *)(pgm->cookie))->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;
}

View File

@ -61,11 +61,19 @@ typedef struct
char debug_version; char debug_version;
} updi_sib_info; } updi_sib_info;
typedef enum
{
RTS_MODE_DEFAULT,
RTS_MODE_LOW,
RTS_MODE_HIGH
} updi_rts_mode;
typedef struct typedef struct
{ {
updi_sib_info sib_info; updi_sib_info sib_info;
updi_datalink_mode datalink_mode; updi_datalink_mode datalink_mode;
updi_nvm_mode nvm_mode; updi_nvm_mode nvm_mode;
updi_rts_mode rts_mode;
} updi_state; } updi_state;
#ifdef __cplusplus #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); void updi_set_datalink_mode(PROGRAMMER * pgm, updi_datalink_mode mode);
updi_nvm_mode updi_get_nvm_mode(PROGRAMMER * pgm); updi_nvm_mode updi_get_nvm_mode(PROGRAMMER * pgm);
void updi_set_nvm_mode(PROGRAMMER * pgm, updi_nvm_mode mode); 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 #ifdef __cplusplus
} }