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@427 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Jan-Hinnerk Reichert 2004-07-07 08:59:07 +00:00
parent d4e7f8fa07
commit 46db932124
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>
* *.c, *.h: Removed unnecessary includes of
config.h

View File

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

View File

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

View File

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

View File

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

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_sck (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
struct command cmd[] = {
{ "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)" },
{ "varef", cmd_varef, "set <V[aref]> (STK500 only)" },
{ "fosc", cmd_fosc, "set <oscillator frequency> (STK500 only)" },
{ "sck", cmd_sck, "set <SCK period> (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 <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 rc;