From 4e704ad695dab075ec3178c0e7276e68351ff808 Mon Sep 17 00:00:00 2001 From: Joerg Wunsch Date: Thu, 24 Jul 2003 21:26:28 +0000 Subject: [PATCH] Add support for displaying and changing the various STK500 operational parameters. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@336 81a1dc3b-b13d-400b-aceb-764788c761c2 --- ChangeLog | 11 +++ NEWS | 12 +++ avrdude.1 | 34 ++++++- doc/avrdude.texi | 27 ++++++ pgm.c | 3 + pgm.h | 4 + stk500.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++- stk500_private.h | 2 +- term.c | 126 ++++++++++++++++++++++++ 9 files changed, 458 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index ad374d29..ca90aadd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2003-07-24 Joerg Wunsch + + * avrdude.1 + * doc/avrdude.texi + * pgm.c + * pgm.h + * stk500.c + * stk500_private.h + * term.c: Add support for displaying and setting the various + operational parameters of the STK500 (Vtarget, Varef, clock). + 2003-05-13 Theodore A. Roth * avr910.c (avr910_paged_write_flash): Add code to send the 'm' diff --git a/NEWS b/NEWS index 7497a64d..51c56bab 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,18 @@ Approximate change log for AVRDUDE by version. ---------------------------------------------------------------------- +Current: + + * Add support for displaying and setting the various STK500 operational + parameters (Vtarget, Varef, Master clock). + + * Add 'picoweb' programming cable programmer. + Contributed by Rune Christensen . + + * Add support for the sp12 programmer. Submitted by + Larry Barello + + Version 4.1.0 * Add support for the Bascom SAMPLE programmer. Submitted by diff --git a/avrdude.1 b/avrdude.1 index 030bd906..34f0af92 100644 --- a/avrdude.1 +++ b/avrdude.1 @@ -19,7 +19,7 @@ .\" .\" $Id$ .\" -.Dd DATE January 11, 2002 +.Dd DATE July 24, 2003 .Os .Dt AVRDUDE 1 .Sh NAME @@ -112,6 +112,9 @@ been code-protected previously, of course) and store the data in a file. Finally, a ``terminal'' mode is available that allows one to interactively communicate with the MCU, and to display or program individual memory cells. +On the STK500 programmer, several operational parameters (target supply +voltage, target Aref voltage, master clock) can be examined and changed +from within terminal mode as well. .Ss Options In order to control all the different operation modi, a number of options need to be specified to @@ -398,6 +401,35 @@ does not implement the command. Display the device signature bytes. .It Ar part Display the current part settings. +.It Ar vtarg voltage +Set the target's supply voltage to +.Ar voltage +Volts. +.Em Only supported on the STK500 programmer. +.It Ar varef voltage +Set the adjustable voltage source to +.Ar voltage +Volts. +This voltage is normally used to drive the target's +.Em Aref +input on the STK500. +.Em Only supported on the STK500 programmer. +.It Ar fosc freq Ns Op M Ns \&| Ns k +Set the master oscillator to +.Ar freq +Hz. +An optional trailing letter +.Ar \&M +multiplies by 1E6, a trailing letter +.Ar \&k +by 1E3. +.Em Only supported on the STK500 programmer. +.It Ar fosc off +Turn the master oscillator off. +.Em Only supported on the STK500 programmer. +.It Ar parms +Display the current voltage and master oscillator parameters. +.Em Only supported on the STK500 programmer. .It Ar \&? .It Ar help Give a short on-line summary of the available commands. diff --git a/doc/avrdude.texi b/doc/avrdude.texi index f1c0bf35..9f3f59a2 100644 --- a/doc/avrdude.texi +++ b/doc/avrdude.texi @@ -555,6 +555,33 @@ Leave terminal mode and thus AVRDUDE. @end table +@noindent +In addition, the following commands are supported on the STK500 +programmer: + +@table @code + +@item vtarg @var{voltage} +Set the target's supply voltage to @var{voltage} Volts. + +@item varef @var{voltage} +Set the adjustable voltage source to @var{voltage} Volts. +This voltage is normally used to drive the target's +@emph{Aref} input on the STK500. + +@item fosc @var{freq}[@var{M}|@var{k}] +Set the master oscillator to @var{freq} Hz. +An optional trailing letter @var{M} +multiplies by 1E6, a trailing letter @var{k} by 1E3. + +@item fosc off +Turn the master oscillator off. + +@item parms +Display the current voltage and master oscillator parameters. + +@end table + @c @c Node @c diff --git a/pgm.c b/pgm.c index 68363046..8ee45779 100644 --- a/pgm.c +++ b/pgm.c @@ -93,6 +93,9 @@ PROGRAMMER * pgm_new(void) pgm->write_byte = NULL; pgm->read_byte = NULL; pgm->read_sig_bytes = NULL; + pgm->set_vtarget = NULL; + pgm->set_varef = NULL; + pgm->set_fosc = NULL; return pgm; } diff --git a/pgm.h b/pgm.h index 2c12480f..b0297965 100644 --- a/pgm.h +++ b/pgm.h @@ -72,6 +72,10 @@ typedef struct programmer_t { int (*read_byte) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m, unsigned long addr, unsigned char * value); int (*read_sig_bytes) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m); + void (*print_parms) (struct programmer_t * pgm); + int (*set_vtarget) (struct programmer_t * pgm, double v); + int (*set_varef) (struct programmer_t * pgm, double v); + int (*set_fosc) (struct programmer_t * pgm, double v); char config_file[PATH_MAX]; /* config file where defined */ int lineno; /* config file line number */ } PROGRAMMER; diff --git a/stk500.c b/stk500.c index a3da7f99..6b746dc9 100644 --- a/stk500.c +++ b/stk500.c @@ -47,7 +47,8 @@ extern int do_cycles; static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value); - +static int stk500_setparm(PROGRAMMER * pgm, unsigned parm, unsigned value); +static void stk500_print_parms1(PROGRAMMER * pgm, char * p); static int stk500_send(PROGRAMMER * pgm, char * buf, size_t len) { @@ -538,7 +539,19 @@ static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p) } } - return pgm->program_enable(pgm, p); + pgm->program_enable(pgm, p); + + /* + * Return success even if program_enable() failed. Otherwise, if + * someone has turned off the STK500 oscillator (or set it to an + * unreasonably slow master clock), they were hosed at this point, + * since to reset fosc to a reasonable value, they at least need to + * get avrdude to start up in terminal mode. The luser has already + * seen a "failed to enter programming mode" message in that case, + * and he also needs to specify -F at program startup since the + * device ID bytes cannot be read in this situation. + */ + return 0; } @@ -874,6 +887,107 @@ static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, } +static int stk500_set_vtarget(PROGRAMMER * pgm, double v) +{ + unsigned uaref, utarg; + + utarg = (unsigned)((v + 0.049) * 10); + + if (stk500_getparm(pgm, Parm_STK_VADJUST, &uaref) != 0) { + fprintf(stderr, + "%s: stk500_set_vtarget(): cannot obtain V[aref]\n", + progname); + return -1; + } + + if (uaref > utarg) { + fprintf(stderr, + "%s: stk500_set_vtarget(): reducing V[aref] from %.1f to %.1f\n", + progname, uaref / 10.0, v); + if (stk500_setparm(pgm, Parm_STK_VADJUST, utarg) + != 0) + return -1; + } + return stk500_setparm(pgm, Parm_STK_VTARGET, utarg); +} + + +static int stk500_set_varef(PROGRAMMER * pgm, double v) +{ + unsigned uaref, utarg; + + uaref = (unsigned)((v + 0.049) * 10); + + if (stk500_getparm(pgm, Parm_STK_VTARGET, &utarg) != 0) { + fprintf(stderr, + "%s: stk500_set_varef(): cannot obtain V[target]\n", + progname); + return -1; + } + + if (uaref > utarg) { + fprintf(stderr, + "%s: stk500_set_varef(): V[aref] must not be greater than " + "V[target] = %.1f\n", + progname, utarg / 10.0); + return -1; + } + return stk500_setparm(pgm, Parm_STK_VADJUST, uaref); +} + + +static int stk500_set_fosc(PROGRAMMER * pgm, double v) +{ +#define fbase 7372800U + unsigned prescale, cmatch, fosc; + static unsigned ps[] = { + 1, 8, 32, 64, 128, 256, 1024 + }; + int idx, rc; + + if (v <= 0.0) { + prescale = cmatch = 0; + goto setclock; + } + if (v > fbase / 2) { + const char *unit; + if (v > 1e6) { + v /= 1e6; + unit = "MHz"; + } else if (v > 1e3) { + v /= 1e3; + unit = "kHz"; + } else + unit = "Hz"; + fprintf(stderr, + "%s: stk500_set_fosc(): f = %.3f %s too high, using %.3f MHz\n", + progname, v, unit, fbase / 2e6); + fosc = fbase / 2; + } else + fosc = (unsigned)v; + + for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) { + if (fosc >= fbase / (256 * ps[idx] * 2)) { + /* this prescaler value can handle our frequency */ + prescale = idx + 1; + cmatch = (unsigned)(fbase / (2 * v * ps[idx])); + break; + } + } + if (idx == sizeof(ps) / sizeof(ps[0])) { + fprintf(stderr, "%s: stk500_set_fosc(): f = %u Hz too low, %u Hz min\n", + progname, fosc, fbase / (256 * 1024 * 2)); + return -1; + } + setclock: + if ((rc = stk500_setparm(pgm, Parm_STK_OSC_PSCALE, prescale)) != 0 + || (rc = stk500_setparm(pgm, Parm_STK_OSC_CMATCH, cmatch)) != 0) + return rc; + + return 0; +} + + static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value) { unsigned char buf[16]; @@ -930,21 +1044,141 @@ static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value) } +static int stk500_setparm(PROGRAMMER * pgm, unsigned parm, unsigned value) +{ + unsigned char buf[16]; + int tries = 0; + + retry: + tries++; + buf[0] = Cmnd_STK_SET_PARAMETER; + buf[1] = parm; + buf[2] = value; + buf[3] = Sync_CRC_EOP; + + stk500_send(pgm, buf, 4); + + stk500_recv(pgm, buf, 1); + if (buf[0] == Resp_STK_NOSYNC) { + if (tries > 33) { + fprintf(stderr, "\n%s: stk500_setparm(): can't get into sync\n", + progname); + return -1; + } + stk500_getsync(pgm); + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + fprintf(stderr, + "\n%s: stk500_setparm(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -2; + } + + stk500_recv(pgm, buf, 1); + if (buf[0] == Resp_STK_OK) + return 0; + + parm = buf[0]; /* if not STK_OK, we've been echoed parm here */ + stk500_recv(pgm, buf, 1); + if (buf[0] == Resp_STK_FAILED) { + fprintf(stderr, + "\n%s: stk500_setparm(): parameter 0x%02x failed\n", + progname, parm); + return -3; + } + else { + fprintf(stderr, + "\n%s: stk500_setparm(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -3; + } +} + + static void stk500_display(PROGRAMMER * pgm, char * p) { - unsigned maj, min, hdw; + unsigned maj, min, hdw, topcard; stk500_getparm(pgm, Parm_STK_HW_VER, &hdw); stk500_getparm(pgm, Parm_STK_SW_MAJOR, &maj); stk500_getparm(pgm, Parm_STK_SW_MINOR, &min); + stk500_getparm(pgm, Param_STK500_TOPCARD_DETECT, &topcard); fprintf(stderr, "%sHardware Version: %d\n", p, hdw); fprintf(stderr, "%sFirmware Version: %d.%d\n", p, maj, min); + if (topcard < 3) { + const char *n = "Unknown"; + + switch (topcard) { + case 1: + n = "STK502"; + break; + + case 2: + n = "STK501"; + break; + } + fprintf(stderr, "%sTopcard : %s\n", p, n); + } + stk500_print_parms1(pgm, p); return; } +static void stk500_print_parms1(PROGRAMMER * pgm, char * p) +{ + unsigned vtarget, vadjust, osc_pscale, osc_cmatch; + + stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget); + stk500_getparm(pgm, Parm_STK_VADJUST, &vadjust); + stk500_getparm(pgm, Parm_STK_OSC_PSCALE, &osc_pscale); + stk500_getparm(pgm, Parm_STK_OSC_CMATCH, &osc_cmatch); + + fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0); + fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0); + fprintf(stderr, "%sOscillator : ", p); + if (osc_pscale == 0) + fprintf(stderr, "Off\n"); + else { + int prescale = 1; + double f = 3.6864e6; + const char *unit; + + switch (osc_pscale) { + case 2: prescale = 8; break; + case 3: prescale = 32; break; + case 4: prescale = 64; break; + case 5: prescale = 128; break; + case 6: prescale = 256; break; + case 7: prescale = 1024; break; + } + f /= prescale; + f /= (osc_cmatch + 1); + if (f > 1e6) { + f /= 1e6; + unit = "MHz"; + } else if (f > 1e3) { + f /= 1000; + unit = "kHz"; + } else + unit = "Hz"; + fprintf(stderr, "%.3f %s\n", f, unit); + } + + return; +} + + +static void stk500_print_parms(PROGRAMMER * pgm) +{ + stk500_print_parms1(pgm, ""); +} + + void stk500_initpgm(PROGRAMMER * pgm) { strcpy(pgm->type, "STK500"); @@ -975,7 +1209,9 @@ void stk500_initpgm(PROGRAMMER * pgm) */ pgm->paged_write = stk500_paged_write; pgm->paged_load = stk500_paged_load; + pgm->print_parms = stk500_print_parms; + pgm->set_vtarget = stk500_set_vtarget; + pgm->set_varef = stk500_set_varef; + pgm->set_fosc = stk500_set_fosc; pgm->page_size = 256; } - - diff --git a/stk500_private.h b/stk500_private.h index 8c56bd62..7efe866c 100644 --- a/stk500_private.h +++ b/stk500_private.h @@ -86,7 +86,7 @@ #define Parm_STK_PARAMODE 0x94 // ' ' - TRUE or FALSE #define Parm_STK_POLLING 0x95 // ' ' - TRUE or FALSE #define Parm_STK_SELFTIMED 0x96 // ' ' - TRUE or FALSE - +#define Param_STK500_TOPCARD_DETECT 0x98 // ' ' - Detect top-card attached // *****************[ STK status bit definitions ]*************************** diff --git a/term.c b/term.c index fb66a678..01a4ffdd 100644 --- a/term.c +++ b/term.c @@ -66,6 +66,14 @@ int cmd_quit (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); int cmd_send (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); +int cmd_parms (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); + +int cmd_vtarg (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); + +int cmd_varef (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); + +int cmd_fosc (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); + struct command cmd[] = { { "dump", cmd_dump, "dump memory : %s " }, @@ -75,6 +83,10 @@ struct command cmd[] = { { "sig", cmd_sig, "display device signature bytes" }, { "part", cmd_part, "display the current part information" }, { "send", cmd_send, "send a raw command : %s " }, + { "parms", cmd_parms, "display adjustable parameters (STK500 only)" }, + { "vtarg", cmd_vtarg, "set (STK500 only)" }, + { "varef", cmd_varef, "set (STK500 only)" }, + { "fosc", cmd_fosc, "set (STK500 only)" }, { "help", cmd_help, "help" }, { "?", cmd_help, "help" }, { "quit", cmd_quit, "quit" } @@ -497,6 +509,120 @@ int cmd_quit(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) } +int cmd_parms(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) +{ + if (pgm->print_parms == NULL) { + fprintf(stderr, + "%s (parms): the %s programmer does not support " + "adjustable parameters\n", + progname, pgm->type); + return -1; + } + pgm->print_parms(pgm); + + return 0; +} + + +int cmd_vtarg(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) +{ + int rc; + double v; + char *endp; + + if (argc != 2) { + fprintf(stderr, "Usage: vtarg \n"); + return -1; + } + v = strtod(argv[1], &endp); + if (endp == argv[1]) { + fprintf(stderr, "%s (vtarg): can't parse voltage \"%s\"\n", + progname, argv[1]); + return -1; + } + if (pgm->set_vtarget == NULL) { + fprintf(stderr, "%s (vtarg): the %s programmer cannot set V[target]\n", + progname, pgm->type); + return -2; + } + if ((rc = pgm->set_vtarget(pgm, v)) != 0) { + fprintf(stderr, "%s (vtarg): failed to set V[target] (rc = %d)\n", + progname, rc); + return -3; + } + return 0; +} + + +int cmd_fosc(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) +{ + int rc; + double v; + char *endp; + + if (argc != 2) { + fprintf(stderr, "Usage: fosc [M|k] | off\n"); + return -1; + } + v = strtod(argv[1], &endp); + if (endp == argv[1]) { + if (strcmp(argv[1], "off") == 0) + v = 0.0; + else { + fprintf(stderr, "%s (fosc): can't parse frequency \"%s\"\n", + progname, argv[1]); + return -1; + } + } + if (*endp == 'm' || *endp == 'M') + v *= 1e6; + else if (*endp == 'k' || *endp == 'K') + v *= 1e3; + if (pgm->set_fosc == NULL) { + fprintf(stderr, + "%s (fosc): the %s programmer cannot set oscillator frequency\n", + progname, pgm->type); + return -2; + } + if ((rc = pgm->set_fosc(pgm, v)) != 0) { + fprintf(stderr, "%s (fosc): failed to set oscillator_frequency (rc = %d)\n", + progname, rc); + return -3; + } + return 0; +} + + +int cmd_varef(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) +{ + int rc; + double v; + char *endp; + + if (argc != 2) { + fprintf(stderr, "Usage: varef \n"); + return -1; + } + v = strtod(argv[1], &endp); + if (endp == argv[1]) { + fprintf(stderr, "%s (varef): can't parse voltage \"%s\"\n", + progname, argv[1]); + return -1; + } + if (pgm->set_varef == NULL) { + fprintf(stderr, "%s (varef): the %s programmer cannot set V[aref]\n", + progname, pgm->type); + return -2; + } + if ((rc = pgm->set_varef(pgm, v)) != 0) { + fprintf(stderr, "%s (varef): failed to set V[aref] (rc = %d)\n", + progname, rc); + return -3; + } + return 0; +} + + int cmd_help(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { int i;