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
This commit is contained in:
Joerg Wunsch 2003-07-24 21:26:28 +00:00
parent f621ec980e
commit 4e704ad695
9 changed files with 458 additions and 7 deletions

View File

@ -1,3 +1,14 @@
2003-07-24 Joerg Wunsch <j@uriah.heep.sax.de>
* 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 <troth@openavr.org>
* avr910.c (avr910_paged_write_flash): Add code to send the 'm'

12
NEWS
View File

@ -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 <rune.christensen@adslhome.dk>.
* Add support for the sp12 programmer. Submitted by
Larry Barello <larryba@barrello.net>
Version 4.1.0
* Add support for the Bascom SAMPLE programmer. Submitted by

View File

@ -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.

View File

@ -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

3
pgm.c
View File

@ -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;
}

4
pgm.h
View File

@ -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;

246
stk500.c
View File

@ -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;
}

View File

@ -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 ]***************************

126
term.c
View File

@ -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 <memtype> <addr> <N-Bytes>" },
@ -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 <b1> <b2> <b3> <b4>" },
{ "parms", cmd_parms, "display adjustable parameters (STK500 only)" },
{ "vtarg", cmd_vtarg, "set <V[target]> (STK500 only)" },
{ "varef", cmd_varef, "set <V[aref]> (STK500 only)" },
{ "fosc", cmd_fosc, "set <oscillator frequency> (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 <value>\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 <value>[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 <value>\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;