mirror of
https://github.com/avrdudes/avrdude.git
synced 2026-09-28 12:06:59 +03:00
Add -xdelay=n for -c wiring to modify sleep after dtr/rts reset
This commit is contained in:
@@ -1666,7 +1666,7 @@ query on flash prepared with -xnometadata yields useful results.
|
||||
.It Ar delay=<n>
|
||||
Add a <n> ms delay after reset. This can be useful if a board takes a
|
||||
particularly long time to exit from external reset. <n> can be negative,
|
||||
in which case the default 120 ms delay after issuing reset will be
|
||||
in which case the default 100 ms delay after issuing reset will be
|
||||
shortened accordingly.
|
||||
.It Ar strict
|
||||
Urclock has a faster, but slightly different strategy than -c arduino to
|
||||
@@ -1782,15 +1782,20 @@ Show help menu and exit.
|
||||
.El
|
||||
.It Ar Wiring
|
||||
When using the Wiring programmer type, the
|
||||
following optional extended parameter is accepted:
|
||||
following optional extended parameters are accepted:
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar snooze=<0..32767>
|
||||
.It Ar snooze=<n>
|
||||
After performing the port open phase, AVRDUDE will wait/snooze for
|
||||
.Ar snooze
|
||||
milliseconds before continuing to the protocol sync phase.
|
||||
No toggling of DTR/RTS is performed if
|
||||
.Ar snooze
|
||||
is greater than 0.
|
||||
.It Ar delay=<n>
|
||||
Add a <n> milliseconds delay after resetting the part through toggling the
|
||||
DTR/RTS lines. This can be useful if a board takes a particularly long
|
||||
time to exit from external reset. <n> can be negative, in which case the
|
||||
default 80 ms delay after issuing reset will be shortened accordingly.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
.El
|
||||
|
||||
@@ -1304,7 +1304,7 @@ yields useful results.
|
||||
@item @samp{delay=<n>}
|
||||
Add a <n> ms delay after reset. This can be useful if a board takes a
|
||||
particularly long time to exit from external reset. <n> can be negative,
|
||||
in which case the default 120 ms delay after issuing reset will be
|
||||
in which case the default 100 ms delay after issuing reset will be
|
||||
shortened accordingly.
|
||||
@item @samp{strict}
|
||||
Urclock has a faster, but slightly different strategy than -c arduino to
|
||||
@@ -1438,12 +1438,17 @@ Show help menu and exit.
|
||||
@cindex @code{-x} Wiring
|
||||
@item Wiring
|
||||
|
||||
The Wiring programmer type accepts the following extended parameter:
|
||||
The Wiring programmer type accepts the following extended parameters:
|
||||
@table @code
|
||||
@item @samp{snooze=@var{0..32767}}
|
||||
@item @samp{snooze=<n>}
|
||||
After performing the port open phase, AVRDUDE will wait/snooze for
|
||||
@var{snooze} milliseconds before continuing to the protocol sync phase.
|
||||
No toggling of DTR/RTS is performed if @var{snooze} > 0.
|
||||
@item @samp{delay=<n>}
|
||||
Add a <n> milliseconds delay after reset. This can be useful if a board
|
||||
takes a particularly long time to exit from external reset. <n> can be
|
||||
negative, in which case the default 80 ms delay after issuing reset will
|
||||
be shortened accordingly.
|
||||
@item @samp{help}
|
||||
Show help menu and exit.
|
||||
@end table
|
||||
|
||||
126
src/wiring.c
126
src/wiring.c
@@ -28,14 +28,13 @@
|
||||
* e.g. chip erase).
|
||||
* DTR and RTS signals are diddled to set the board into programming mode.
|
||||
*
|
||||
* Also includes an extended parameter to introduce a delay after opening
|
||||
* to accommodate multi-layered programmers/bootloaders. If the extended
|
||||
* parameter 'snooze' > 0, then no DTR/RTS toggle takes place, and
|
||||
* AVRDUDE will wait that amount of time in milliseconds before syncing.
|
||||
* Also includes an extended parameter to introduce a delay after opening to
|
||||
* accommodate multi-layered programmers/bootloaders. If the extended
|
||||
* parameter 'snooze' > 0, then no DTR/RTS toggle takes place, and AVRDUDE
|
||||
* will wait that amount of time in milliseconds before syncing. If the
|
||||
* extended parameter 'delay' is set then this number of milliseconds is
|
||||
* added to the usual delay of 80 ms after toggling DTR/RTS.
|
||||
*
|
||||
* Unfortunately, there is no way to easily chain private programmer data
|
||||
* when we "inherit" programmer types as we have (stk500v2). Sooooo, a
|
||||
* *cringe* global variable is used to store the snooze time.
|
||||
*/
|
||||
|
||||
#include "ac_cfg.h"
|
||||
@@ -55,84 +54,60 @@
|
||||
/*
|
||||
* Private data for this programmer.
|
||||
*/
|
||||
struct wiringpdata
|
||||
{
|
||||
/*
|
||||
* We just have the single snooze integer to carry around for now.
|
||||
*/
|
||||
int snoozetime;
|
||||
struct wiringpdata {
|
||||
int snoozetime, delay;
|
||||
};
|
||||
|
||||
|
||||
/* wiringpdata is our private data */
|
||||
/* pdata is stk500v2's private data (inherited) */
|
||||
|
||||
#define WIRINGPDATA(x) ((struct wiringpdata *)(x))
|
||||
#define WIRINGPDATA(pgm) ((struct wiringpdata *)(((struct pdata *)(pgm->cookie)) -> chained_pdata))
|
||||
|
||||
#define STK500V2PDATA(pgm) ((struct pdata *)(pgm->cookie))
|
||||
|
||||
|
||||
static void wiring_setup(PROGRAMMER * pgm)
|
||||
{
|
||||
void *mycookie;
|
||||
|
||||
/*
|
||||
* First, have STK500v2 backend allocate its own private data.
|
||||
*/
|
||||
static void wiring_setup(PROGRAMMER *pgm) {
|
||||
// First, have STK500v2 backend allocate its own private data
|
||||
stk500v2_setup(pgm);
|
||||
|
||||
/*
|
||||
* Now prepare our data
|
||||
*/
|
||||
if ((mycookie = malloc(sizeof(struct wiringpdata))) == 0) {
|
||||
pmsg_error("out of memory allocating private data\n");
|
||||
exit(1);
|
||||
}
|
||||
memset(mycookie, 0, sizeof(struct wiringpdata));
|
||||
WIRINGPDATA(mycookie)->snoozetime = 0;
|
||||
|
||||
/*
|
||||
* Store our own cookie in a safe place for the time being.
|
||||
*/
|
||||
STK500V2PDATA(pgm)->chained_pdata = mycookie;
|
||||
// Then prepare our data and store in a safe place for the time being
|
||||
((struct pdata *)(pgm->cookie))->chained_pdata = cfg_malloc(__func__, sizeof(struct wiringpdata));
|
||||
}
|
||||
|
||||
static void wiring_teardown(PROGRAMMER * pgm)
|
||||
{
|
||||
void *mycookie;
|
||||
|
||||
mycookie = STK500V2PDATA(pgm)->chained_pdata;
|
||||
|
||||
free(mycookie);
|
||||
|
||||
static void wiring_teardown(PROGRAMMER *pgm) {
|
||||
free(((struct pdata *)(pgm->cookie))->chained_pdata);
|
||||
stk500v2_teardown(pgm);
|
||||
}
|
||||
|
||||
static int wiring_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
const char *extended_param, *errstr;
|
||||
int rv = 0;
|
||||
void *mycookie = STK500V2PDATA(pgm)->chained_pdata;
|
||||
|
||||
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
|
||||
if (str_starts(extended_param, "snooze=")) {
|
||||
int newsnooze;
|
||||
if (sscanf(extended_param, "snooze=%i", &newsnooze) != 1 ||
|
||||
newsnooze < 0) {
|
||||
pmsg_error("invalid snooze time '%s'\n", extended_param);
|
||||
int val = str_int(extended_param+7, STR_INT32, &errstr);
|
||||
if(errstr || val < 0) {
|
||||
pmsg_error("-x%s: %s\n", extended_param, errstr? errstr: "snooze time cannot be negative");
|
||||
rv = -1;
|
||||
continue;
|
||||
}
|
||||
pmsg_notice2("wiring_parseextparms(): snooze time set to %d ms\n", newsnooze);
|
||||
WIRINGPDATA(mycookie)->snoozetime = newsnooze;
|
||||
|
||||
pmsg_notice2("%s(): snooze time set to %d ms\n", __func__, val);
|
||||
WIRINGPDATA(pgm)->snoozetime = val;
|
||||
continue;
|
||||
}
|
||||
if (str_eq(extended_param, "help")) {
|
||||
} else if (str_starts(extended_param, "delay=")) {
|
||||
int val = str_int(extended_param+6, STR_INT32, &errstr);
|
||||
if(errstr) {
|
||||
pmsg_error("-x%s: %s\n", extended_param, errstr);
|
||||
return -1;
|
||||
}
|
||||
pmsg_notice2("%s(): delay set to %d ms\n", __func__, val);
|
||||
WIRINGPDATA(pgm)->delay = val;
|
||||
continue;
|
||||
} else if (str_eq(extended_param, "help")) {
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -xsnooze=<arg> Wait <arg> [ms] before protocol sync after port open\n");
|
||||
msg_error(" -xsnooze=<arg> Wait snooze [ms] before protocol sync after port open\n");
|
||||
msg_error(" -xdelay=<arg> Add delay [ms] after reset, can be negative\n");
|
||||
msg_error(" -xhelp Show this help menu and exit\n");
|
||||
exit(0);
|
||||
}
|
||||
@@ -146,7 +121,6 @@ static int wiring_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
|
||||
static int wiring_open(PROGRAMMER *pgm, const char *port) {
|
||||
int timetosnooze;
|
||||
void *mycookie = STK500V2PDATA(pgm)->chained_pdata;
|
||||
union pinfo pinfo;
|
||||
|
||||
strcpy(pgm->port, port);
|
||||
@@ -154,43 +128,41 @@ static int wiring_open(PROGRAMMER *pgm, const char *port) {
|
||||
pinfo.serialinfo.cflags = SERIAL_8N1;
|
||||
serial_open(port, pinfo, &pgm->fd);
|
||||
|
||||
/* If we have a snoozetime, then we wait and do NOT toggle DTR/RTS */
|
||||
|
||||
if (WIRINGPDATA(mycookie)->snoozetime > 0) {
|
||||
timetosnooze = WIRINGPDATA(mycookie)->snoozetime;
|
||||
// If we have a snoozetime, then we wait and do NOT toggle DTR/RTS
|
||||
if (WIRINGPDATA(pgm)->snoozetime > 0) {
|
||||
timetosnooze = WIRINGPDATA(pgm)->snoozetime;
|
||||
|
||||
pmsg_notice2("wiring_open(): snoozing for %d ms\n", timetosnooze);
|
||||
while (timetosnooze--)
|
||||
usleep(1000);
|
||||
pmsg_notice2("wiring_open(): done snoozing\n");
|
||||
} else {
|
||||
/* Perform Wiring programming mode RESET. */
|
||||
/* This effectively *releases* both DTR and RTS. */
|
||||
/* i.e. both DTR and RTS rise to a HIGH logic level */
|
||||
/* since they are active LOW signals. */
|
||||
|
||||
// This code assumes a negative-logic USB to TTL serial adapter
|
||||
// Set RTS/DTR high to discharge the series-capacitor, if present
|
||||
pmsg_notice2("wiring_open(): releasing DTR/RTS\n");
|
||||
|
||||
serial_set_dtr_rts(&pgm->fd, 0);
|
||||
usleep(50*1000);
|
||||
|
||||
/* After releasing for 50 milliseconds, DTR and RTS */
|
||||
/* are asserted (i.e. logic LOW) again. */
|
||||
|
||||
// Pull the RTS/DTR line low to reset AVR
|
||||
pmsg_notice2("wiring_open(): asserting DTR/RTS\n");
|
||||
|
||||
serial_set_dtr_rts(&pgm->fd, 1);
|
||||
usleep(50*1000);
|
||||
usleep(20*1000);
|
||||
|
||||
/* Set high, so a direct connection to reset works. */
|
||||
// Set the RTS/DTR line back to high, so direct connection to reset works
|
||||
serial_set_dtr_rts(&pgm->fd, 0);
|
||||
|
||||
int delay = WIRINGPDATA(pgm)->delay;
|
||||
if((80+delay) > 0)
|
||||
usleep((80+delay)*1000); // Wait until board comes out of reset
|
||||
}
|
||||
|
||||
/* drain any extraneous input */
|
||||
// Drain any extraneous input
|
||||
stk500v2_drain(pgm, 0);
|
||||
|
||||
if (stk500v2_getsync(pgm) < 0)
|
||||
if (stk500v2_getsync(pgm) < 0) {
|
||||
pmsg_error("stk500v2_getsync() failed; try -xdelay=n with some n in [-80, 100]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user