From 80f996b49acc6a77e2e7f492d53b8e50ab809447 Mon Sep 17 00:00:00 2001 From: Jan-Hinnerk Reichert Date: Wed, 7 Jul 2004 08:59:07 +0000 Subject: [PATCH] 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 --- ChangeLog | 6 ++++++ avrdude.1 | 5 +++++ doc/avrdude.texi | 3 +++ pgm.h | 1 + stk500.c | 54 ++++++++++++++++++++++++++++++++++++++++-------- term.c | 35 +++++++++++++++++++++++++++++++ 6 files changed, 95 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index a4b6e437..42fd9257 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2004-07-07 Jan-Hinnerk Reichert + * 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 * *.c, *.h: Removed unnecessary includes of config.h diff --git a/avrdude.1 b/avrdude.1 index 744cea2f..d784ec90 100644 --- a/avrdude.1 +++ b/avrdude.1 @@ -434,6 +434,11 @@ by 1E3. .It Ar fosc off Turn the master oscillator off. .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 Display the current voltage and master oscillator parameters. .Em Only supported on the STK500 programmer. diff --git a/doc/avrdude.texi b/doc/avrdude.texi index 231cd231..653c37df 100644 --- a/doc/avrdude.texi +++ b/doc/avrdude.texi @@ -753,6 +753,9 @@ multiplies by 1E6, a trailing letter @var{k} by 1E3. @item fosc off Turn the master oscillator off. +@item sck @var{period} +Set the SCK clock period to @var{period} microseconds. + @item parms Display the current voltage and master oscillator parameters. diff --git a/pgm.h b/pgm.h index bb066c7c..5ab90c3d 100644 --- a/pgm.h +++ b/pgm.h @@ -79,6 +79,7 @@ typedef struct programmer_t { 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); + int (*set_sck_period) (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 ff232fda..781d3c2c 100644 --- a/stk500.c +++ b/stk500.c @@ -41,6 +41,7 @@ #include "stk500_private.h" #include "serial.h" +#define STK500_XTAL 7372800U extern int verbose; 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) { -#define fbase 7372800U unsigned prescale, cmatch, fosc; static unsigned ps[] = { 1, 8, 32, 64, 128, 256, 1024 @@ -898,7 +898,7 @@ static int stk500_set_fosc(PROGRAMMER * pgm, double v) prescale = cmatch = 0; if (v > 0.0) { - if (v > fbase / 2) { + if (v > STK500_XTAL / 2) { const char *unit; if (v > 1e6) { v /= 1e6; @@ -910,22 +910,22 @@ static int stk500_set_fosc(PROGRAMMER * pgm, double v) 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; + progname, v, unit, STK500_XTAL / 2e6); + fosc = STK500_XTAL / 2; } else fosc = (unsigned)v; 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 */ prescale = idx + 1; - cmatch = (unsigned)(fbase / (2 * fosc * ps[idx])) - 1; + cmatch = (unsigned)(STK500_XTAL / (2 * fosc * ps[idx])) - 1; 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)); + progname, fosc, STK500_XTAL / (256 * 1024 * 2)); 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) { 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) { - 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_VADJUST, &vadjust); stk500_getparm(pgm, Parm_STK_OSC_PSCALE, &osc_pscale); 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, "%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"); else { int prescale = 1; - double f = 3.6864e6; + double f = STK500_XTAL / 2; const char *unit; switch (osc_pscale) { @@ -1118,6 +1151,8 @@ static void stk500_print_parms1(PROGRAMMER * pgm, char * p) unit = "Hz"; fprintf(stderr, "%.3f %s\n", f, unit); } + fprintf(stderr, "%sSCK period : %.1f us\n", p, + sck_duration * 8.0e6 / STK500_XTAL + 0.05); return; } @@ -1155,5 +1190,6 @@ void stk500_initpgm(PROGRAMMER * pgm) pgm->set_vtarget = stk500_set_vtarget; pgm->set_varef = stk500_set_varef; pgm->set_fosc = stk500_set_fosc; + pgm->set_sck_period = stk500_set_sck_period; pgm->page_size = 256; } diff --git a/term.c b/term.c index 825632fe..0c1306bf 100644 --- a/term.c +++ b/term.c @@ -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_sck (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); + struct command cmd[] = { { "dump", cmd_dump, "dump memory : %s " }, @@ -91,6 +93,7 @@ struct command cmd[] = { { "vtarg", cmd_vtarg, "set (STK500 only)" }, { "varef", cmd_varef, "set (STK500 only)" }, { "fosc", cmd_fosc, "set (STK500 only)" }, + { "sck", cmd_sck, "set (STK500 only)" }, { "help", cmd_help, "help" }, { "?", cmd_help, "help" }, { "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 \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 rc;