stk500.c, term.c, doc/avrdude.texi, avrdude.1: added "sck"-command to the terminal mode. This command allows slowing down of the SCK of STK500-programmers.

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@427 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
hinni 2004-07-07 08:59:07 +00:00
parent 10272c5a55
commit bcb78e8e05
6 changed files with 95 additions and 9 deletions

View File

@ -1,3 +1,9 @@
2004-07-07 Jan-Hinnerk Reichert <hinni@despammed.com>
* stk500.c, term.c, doc/avrdude.texi, avrdude.1:
added "sck"-command to the terminal mode.
This command allows slowing down of the SCK of
STK500-programmers.
2004-07-05 Jan-Hinnerk Reichert <hinni@despammed.com> 2004-07-05 Jan-Hinnerk Reichert <hinni@despammed.com>
* *.c, *.h: Removed unnecessary includes of * *.c, *.h: Removed unnecessary includes of
config.h config.h

View File

@ -434,6 +434,11 @@ by 1E3.
.It Ar fosc off .It Ar fosc off
Turn the master oscillator off. Turn the master oscillator off.
.Em Only supported on the STK500 programmer. .Em Only supported on the STK500 programmer.
.It Ar sck period
Set the SCK clock period to
.Ar period
microseconds.
.Em Only supported on the STK500 programmer.
.It Ar parms .It Ar parms
Display the current voltage and master oscillator parameters. Display the current voltage and master oscillator parameters.
.Em Only supported on the STK500 programmer. .Em Only supported on the STK500 programmer.

View File

@ -753,6 +753,9 @@ multiplies by 1E6, a trailing letter @var{k} by 1E3.
@item fosc off @item fosc off
Turn the master oscillator off. Turn the master oscillator off.
@item sck @var{period}
Set the SCK clock period to @var{period} microseconds.
@item parms @item parms
Display the current voltage and master oscillator parameters. Display the current voltage and master oscillator parameters.

1
pgm.h
View File

@ -79,6 +79,7 @@ typedef struct programmer_t {
int (*set_vtarget) (struct programmer_t * pgm, double v); int (*set_vtarget) (struct programmer_t * pgm, double v);
int (*set_varef) (struct programmer_t * pgm, double v); int (*set_varef) (struct programmer_t * pgm, double v);
int (*set_fosc) (struct programmer_t * pgm, double v); int (*set_fosc) (struct programmer_t * pgm, double v);
int (*set_sck_period) (struct programmer_t * pgm, double v);
char config_file[PATH_MAX]; /* config file where defined */ char config_file[PATH_MAX]; /* config file where defined */
int lineno; /* config file line number */ int lineno; /* config file line number */
} PROGRAMMER; } PROGRAMMER;

View File

@ -41,6 +41,7 @@
#include "stk500_private.h" #include "stk500_private.h"
#include "serial.h" #include "serial.h"
#define STK500_XTAL 7372800U
extern int verbose; extern int verbose;
extern char * progname; extern char * progname;
@ -889,7 +890,6 @@ static int stk500_set_varef(PROGRAMMER * pgm, double v)
static int stk500_set_fosc(PROGRAMMER * pgm, double v) static int stk500_set_fosc(PROGRAMMER * pgm, double v)
{ {
#define fbase 7372800U
unsigned prescale, cmatch, fosc; unsigned prescale, cmatch, fosc;
static unsigned ps[] = { static unsigned ps[] = {
1, 8, 32, 64, 128, 256, 1024 1, 8, 32, 64, 128, 256, 1024
@ -898,7 +898,7 @@ static int stk500_set_fosc(PROGRAMMER * pgm, double v)
prescale = cmatch = 0; prescale = cmatch = 0;
if (v > 0.0) { if (v > 0.0) {
if (v > fbase / 2) { if (v > STK500_XTAL / 2) {
const char *unit; const char *unit;
if (v > 1e6) { if (v > 1e6) {
v /= 1e6; v /= 1e6;
@ -910,22 +910,22 @@ static int stk500_set_fosc(PROGRAMMER * pgm, double v)
unit = "Hz"; unit = "Hz";
fprintf(stderr, fprintf(stderr,
"%s: stk500_set_fosc(): f = %.3f %s too high, using %.3f MHz\n", "%s: stk500_set_fosc(): f = %.3f %s too high, using %.3f MHz\n",
progname, v, unit, fbase / 2e6); progname, v, unit, STK500_XTAL / 2e6);
fosc = fbase / 2; fosc = STK500_XTAL / 2;
} else } else
fosc = (unsigned)v; fosc = (unsigned)v;
for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) { for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) {
if (fosc >= fbase / (256 * ps[idx] * 2)) { if (fosc >= STK500_XTAL / (256 * ps[idx] * 2)) {
/* this prescaler value can handle our frequency */ /* this prescaler value can handle our frequency */
prescale = idx + 1; prescale = idx + 1;
cmatch = (unsigned)(fbase / (2 * fosc * ps[idx])) - 1; cmatch = (unsigned)(STK500_XTAL / (2 * fosc * ps[idx])) - 1;
break; break;
} }
} }
if (idx == sizeof(ps) / sizeof(ps[0])) { if (idx == sizeof(ps) / sizeof(ps[0])) {
fprintf(stderr, "%s: stk500_set_fosc(): f = %u Hz too low, %u Hz min\n", fprintf(stderr, "%s: stk500_set_fosc(): f = %u Hz too low, %u Hz min\n",
progname, fosc, fbase / (256 * 1024 * 2)); progname, fosc, STK500_XTAL / (256 * 1024 * 2));
return -1; return -1;
} }
} }
@ -938,6 +938,38 @@ static int stk500_set_fosc(PROGRAMMER * pgm, double v)
} }
/* This code assumes that each count of the SCK duration parameter
represents 8/f, where f is the clock frequency of the STK500 master
processors (not the target). This number comes from Atmel
application note AVR061. It appears that the STK500 bit bangs SCK.
For small duration values, the actual SCK width is larger than
expected. As the duration value increases, the SCK width error
diminishes. */
static int stk500_set_sck_period(PROGRAMMER * pgm, double v)
{
int dur;
double min, max;
min = 8.0 / STK500_XTAL;
max = 255 * min;
dur = v / min + 0.5;
if (v < min) {
dur = 1;
fprintf(stderr,
"%s: stk500_set_sck_period(): p = %.1f us too small, using %.1f us\n",
progname, v / 1e-6, dur * min / 1e-6);
} else if (v > max) {
dur = 255;
fprintf(stderr,
"%s: stk500_set_sck_period(): p = %.1f us too large, using %.1f us\n",
progname, v / 1e-6, dur * min / 1e-6);
}
return stk500_setparm(pgm, Parm_STK_SCK_DURATION, dur);
}
static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value) static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value)
{ {
unsigned char buf[16]; unsigned char buf[16];
@ -1081,12 +1113,13 @@ static void stk500_display(PROGRAMMER * pgm, char * p)
static void stk500_print_parms1(PROGRAMMER * pgm, char * p) static void stk500_print_parms1(PROGRAMMER * pgm, char * p)
{ {
unsigned vtarget, vadjust, osc_pscale, osc_cmatch; unsigned vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget); stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget);
stk500_getparm(pgm, Parm_STK_VADJUST, &vadjust); stk500_getparm(pgm, Parm_STK_VADJUST, &vadjust);
stk500_getparm(pgm, Parm_STK_OSC_PSCALE, &osc_pscale); stk500_getparm(pgm, Parm_STK_OSC_PSCALE, &osc_pscale);
stk500_getparm(pgm, Parm_STK_OSC_CMATCH, &osc_cmatch); stk500_getparm(pgm, Parm_STK_OSC_CMATCH, &osc_cmatch);
stk500_getparm(pgm, Parm_STK_SCK_DURATION, &sck_duration);
fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0); fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0); fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0);
@ -1095,7 +1128,7 @@ static void stk500_print_parms1(PROGRAMMER * pgm, char * p)
fprintf(stderr, "Off\n"); fprintf(stderr, "Off\n");
else { else {
int prescale = 1; int prescale = 1;
double f = 3.6864e6; double f = STK500_XTAL / 2;
const char *unit; const char *unit;
switch (osc_pscale) { switch (osc_pscale) {
@ -1118,6 +1151,8 @@ static void stk500_print_parms1(PROGRAMMER * pgm, char * p)
unit = "Hz"; unit = "Hz";
fprintf(stderr, "%.3f %s\n", f, unit); fprintf(stderr, "%.3f %s\n", f, unit);
} }
fprintf(stderr, "%sSCK period : %.1f us\n", p,
sck_duration * 8.0e6 / STK500_XTAL + 0.05);
return; return;
} }
@ -1155,5 +1190,6 @@ void stk500_initpgm(PROGRAMMER * pgm)
pgm->set_vtarget = stk500_set_vtarget; pgm->set_vtarget = stk500_set_vtarget;
pgm->set_varef = stk500_set_varef; pgm->set_varef = stk500_set_varef;
pgm->set_fosc = stk500_set_fosc; pgm->set_fosc = stk500_set_fosc;
pgm->set_sck_period = stk500_set_sck_period;
pgm->page_size = 256; pgm->page_size = 256;
} }

35
term.c
View File

@ -78,6 +78,8 @@ int cmd_varef (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
int cmd_fosc (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); int cmd_fosc (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
int cmd_sck (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
struct command cmd[] = { struct command cmd[] = {
{ "dump", cmd_dump, "dump memory : %s <memtype> <addr> <N-Bytes>" }, { "dump", cmd_dump, "dump memory : %s <memtype> <addr> <N-Bytes>" },
@ -91,6 +93,7 @@ struct command cmd[] = {
{ "vtarg", cmd_vtarg, "set <V[target]> (STK500 only)" }, { "vtarg", cmd_vtarg, "set <V[target]> (STK500 only)" },
{ "varef", cmd_varef, "set <V[aref]> (STK500 only)" }, { "varef", cmd_varef, "set <V[aref]> (STK500 only)" },
{ "fosc", cmd_fosc, "set <oscillator frequency> (STK500 only)" }, { "fosc", cmd_fosc, "set <oscillator frequency> (STK500 only)" },
{ "sck", cmd_sck, "set <SCK period> (STK500 only)" },
{ "help", cmd_help, "help" }, { "help", cmd_help, "help" },
{ "?", cmd_help, "help" }, { "?", cmd_help, "help" },
{ "quit", cmd_quit, "quit" } { "quit", cmd_quit, "quit" }
@ -597,6 +600,38 @@ int cmd_fosc(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
} }
int cmd_sck(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
{
int rc;
double v;
char *endp;
if (argc != 2) {
fprintf(stderr, "Usage: sck <value>\n");
return -1;
}
v = strtod(argv[1], &endp);
if (endp == argv[1]) {
fprintf(stderr, "%s (sck): can't parse period \"%s\"\n",
progname, argv[1]);
return -1;
}
v *= 1e-6; /* Convert from microseconds to seconds. */
if (pgm->set_sck_period == NULL) {
fprintf(stderr,
"%s (sck): the %s programmer cannot set SCK period\n",
progname, pgm->type);
return -2;
}
if ((rc = pgm->set_sck_period(pgm, v)) != 0) {
fprintf(stderr, "%s (sck): failed to set SCK period (rc = %d)\n",
progname, rc);
return -3;
}
return 0;
}
int cmd_varef(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) int cmd_varef(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
{ {
int rc; int rc;