Submitted by John Voltz: add AVR053 oscillator calibration.

* main.c: Add the -O option.
* pgm.c: Add the hook for the perform_osccal() method.
* pgm.h: (Ditto.)
* stk500v2.c: Implement perform_osccal().
* avrdude.1: Document the -O option.
* doc/avrdude.texi: (Ditto.)
Partially closes bug #17487: AVR RC oscillator calibration
routine not supported (feature request)


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@671 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Joerg Wunsch 2006-10-09 14:34:24 +00:00
parent 57028107ff
commit 2cfccda03d
7 changed files with 127 additions and 38 deletions

View File

@ -1,3 +1,15 @@
2006-10-09 Joerg Wunsch <j@uriah.heep.sax.de>
Submitted by John Voltz: add AVR053 oscillator calibration.
* main.c: Add the -O option.
* pgm.c: Add the hook for the perform_osccal() method.
* pgm.h: (Ditto.)
* stk500v2.c: Implement perform_osccal().
* avrdude.1: Document the -O option.
* doc/avrdude.texi: (Ditto.)
Partially closes bug #17487: AVR RC oscillator calibration
routine not supported (feature request)
2006-10-09 Joerg Wunsch <j@uriah.heep.sax.de> 2006-10-09 Joerg Wunsch <j@uriah.heep.sax.de>
Submitted by freckle@sf.net: Submitted by freckle@sf.net:

View File

@ -19,7 +19,7 @@
.\" .\"
.\" $Id$ .\" $Id$
.\" .\"
.Dd DATE September 10, 2006 .Dd DATE October 9, 2006
.Os .Os
.Dt AVRDUDE 1 .Dt AVRDUDE 1
.Sh NAME .Sh NAME
@ -40,6 +40,7 @@
.Op Fl F .Op Fl F
.Op Fl i Ar delay .Op Fl i Ar delay
.Op Fl n .Op Fl n
.Op Fl O
.Op Fl P Ar port .Op Fl P Ar port
.Op Fl q .Op Fl q
.Op Fl s .Op Fl s
@ -360,6 +361,12 @@ slow machines.
No-write - disables actually writing data to the MCU (useful for debugging No-write - disables actually writing data to the MCU (useful for debugging
.Nm avrdude .Nm avrdude
). ).
.It Fl O
Perform a RC oscillator run-time calibration according to Atmel
application note AVR053.
This is only supported on the STK500v2, AVRISP mkII, and JTAG ICE mkII
hardware.
Note that the result will be stored in the EEPROM cell at address 0.
.It Fl P Ar port .It Fl P Ar port
Use Use
.Ar port .Ar port

View File

@ -505,6 +505,13 @@ slow machines.
No-write - disables actually writing data to the MCU (useful for No-write - disables actually writing data to the MCU (useful for
debugging AVRDUDE). debugging AVRDUDE).
@item -O
Perform a RC oscillator run-time calibration according to Atmel
application note AVR053.
This is only supported on the STK500v2, AVRISP mkII, and JTAG ICE mkII
hardware.
Note that the result will be stored in the EEPROM cell at address 0.
@item -P @var{port} @item -P @var{port}
Use port to identify the device to which the programmer is attached. Use port to identify the device to which the programmer is attached.
Normally, the default parallel port is used, but if the programmer type Normally, the default parallel port is used, but if the programmer type

24
main.c
View File

@ -110,6 +110,7 @@ void usage(void)
" -P <port> Specify connection port.\n" " -P <port> Specify connection port.\n"
" -F Override invalid signature check.\n" " -F Override invalid signature check.\n"
" -e Perform a chip erase.\n" " -e Perform a chip erase.\n"
" -O Perform RC oscillator calibration (see AVR053). \n"
" -U <memtype>:r|w|v:<filename>[:format]\n" " -U <memtype>:r|w|v:<filename>[:format]\n"
" Memory operation specification.\n" " Memory operation specification.\n"
" Multiple -U options are allowed, each request\n" " Multiple -U options are allowed, each request\n"
@ -682,6 +683,7 @@ int main(int argc, char * argv [])
/* options / operating mode variables */ /* options / operating mode variables */
int erase; /* 1=erase chip, 0=don't */ int erase; /* 1=erase chip, 0=don't */
int calibrate; /* 1=calibrate RC oscillator, 0=don't */
int auto_erase; /* 0=never erase unless explicity told to do int auto_erase; /* 0=never erase unless explicity told to do
so, 1=erase if we are going to program flash */ so, 1=erase if we are going to program flash */
char * port; /* device port (/dev/xxx) */ char * port; /* device port (/dev/xxx) */
@ -739,6 +741,7 @@ int main(int argc, char * argv [])
partdesc = NULL; partdesc = NULL;
port = default_parallel; port = default_parallel;
erase = 0; erase = 0;
calibrate = 0;
auto_erase = 1; auto_erase = 1;
p = NULL; p = NULL;
ovsigck = 0; ovsigck = 0;
@ -805,7 +808,7 @@ int main(int argc, char * argv [])
/* /*
* process command line arguments * process command line arguments
*/ */
while ((ch = getopt(argc,argv,"?b:B:c:C:DeE:Fi:np:P:qstU:uvVyY:")) != -1) { while ((ch = getopt(argc,argv,"?b:B:c:C:DeE:Fi:np:OP:qstU:uvVyY:")) != -1) {
switch (ch) { switch (ch) {
case 'b': /* override default programmer baud rate */ case 'b': /* override default programmer baud rate */
@ -864,6 +867,10 @@ int main(int argc, char * argv [])
nowrite = 1; nowrite = 1;
break; break;
case 'O': /* perform RC oscillator calibration */
calibrate = 1;
break;
case 'p' : /* specify AVR part */ case 'p' : /* specify AVR part */
partdesc = optarg; partdesc = optarg;
break; break;
@ -1151,6 +1158,21 @@ int main(int argc, char * argv [])
goto main_exit; goto main_exit;
} }
if (calibrate) {
/*
* perform an RC oscillator calibration
* as outlined in appnote AVR053
*/
fprintf(stderr, "%s: performing RC oscillator calibration\n", progname);
exitrc = pgm->perform_osccal(pgm);
if (exitrc == 0 && quell_progress < 2) {
fprintf(stderr,
"%s: calibration value is now stored in EEPROM at address 0\n",
progname);
}
goto main_exit;
}
if (verbose) { if (verbose) {
avr_display(stderr, p, progbuf, verbose); avr_display(stderr, p, progbuf, verbose);
fprintf(stderr, "\n"); fprintf(stderr, "\n");

1
pgm.c
View File

@ -123,6 +123,7 @@ PROGRAMMER * pgm_new(void)
pgm->set_vtarget = NULL; pgm->set_vtarget = NULL;
pgm->set_varef = NULL; pgm->set_varef = NULL;
pgm->set_fosc = NULL; pgm->set_fosc = NULL;
pgm->perform_osccal = NULL;
return pgm; return pgm;
} }

1
pgm.h
View File

@ -100,6 +100,7 @@ typedef struct programmer_t {
int (*getpin) (struct programmer_t * pgm, int pin); int (*getpin) (struct programmer_t * pgm, int pin);
int (*highpulsepin) (struct programmer_t * pgm, int pin); int (*highpulsepin) (struct programmer_t * pgm, int pin);
int (*parseexitspecs) (struct programmer_t * pgm, char *s); int (*parseexitspecs) (struct programmer_t * pgm, char *s);
int (*perform_osccal) (struct programmer_t * pgm);
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 */
char flag; /* for private use of the programmer */ char flag; /* for private use of the programmer */

View File

@ -329,7 +329,7 @@ static int stk500v2_jtagmkII_recv(PROGRAMMER * pgm, unsigned char msg[],
return -1; return -1;
} }
memcpy(msg, jtagmsg + 1, rv - 1); memcpy(msg, jtagmsg + 1, rv - 1);
return 0; return rv;
} }
static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) { static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) {
@ -524,8 +524,8 @@ retry:
return 0; return 0;
} }
static int stk500v2_command static int stk500v2_command(PROGRAMMER * pgm, unsigned char * buf,
(PROGRAMMER * pgm, unsigned char * buf, size_t len, size_t maxlen) { size_t len, size_t maxlen) {
int i; int i;
int tries = 0; int tries = 0;
int status; int status;
@ -539,14 +539,24 @@ retry:
// send the command to the programmer // send the command to the programmer
stk500v2_send(pgm,buf,len); stk500v2_send(pgm,buf,len);
// attempt to read the status back // attempt to read the status back
status = stk500v2_recv(pgm,buf,maxlen); status = stk500v2_recv(pgm,buf,maxlen);
// if we got a successful readback, return // if we got a successful readback, return
if (status > 0) { if (status > 0) {
DEBUG(" = %d\n",status); DEBUG(" = %d\n",status);
return status; if (status < 2) {
fprintf(stderr, "%s: stk500v2_command(): short reply\n", progname);
return -1;
}
if (buf[1] == STATUS_CMD_OK)
return status;
if (buf[1] == STATUS_CMD_FAILED)
fprintf(stderr, "%s: stk500v2_command(): command failed\n", progname);
else
fprintf(stderr, "%s: stk500v2_command(): unknown status 0x%02x\n",
progname, buf[1]);
return -1;
} }
// otherwise try to sync up again // otherwise try to sync up again
@ -582,10 +592,14 @@ static int stk500v2_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
buf[7] = cmd[3]; buf[7] = cmd[3];
result = stk500v2_command(pgm, buf, 8, sizeof(buf)); result = stk500v2_command(pgm, buf, 8, sizeof(buf));
if (buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr, "%s: stk500v2_cmd(): failed to send command\n", fprintf(stderr, "%s: stk500v2_cmd(): failed to send command\n",
progname); progname);
return -1; return -1;
} else if (result < 6) {
fprintf(stderr, "%s: stk500v2_cmd(): short reply, len = %d\n",
progname, result);
return -1;
} }
res[0] = buf[2]; res[0] = buf[2];
@ -782,11 +796,11 @@ static int stk500hv_initialize(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode)
result = stk500v2_command(pgm, buf, CTL_STACK_SIZE + 1, sizeof(buf)); result = stk500v2_command(pgm, buf, CTL_STACK_SIZE + 1, sizeof(buf));
if (result < 0 || buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr, fprintf(stderr,
"%s: stk500pp_initalize(): " "%s: stk500pp_initalize(): "
"failed to set control stack, got 0x%02x\n", "failed to set control stack\n",
progname, buf[1]); progname);
return -1; return -1;
} }
@ -852,9 +866,10 @@ static void stk500v2_disable(PROGRAMMER * pgm)
result = stk500v2_command(pgm, buf, 3, sizeof(buf)); result = stk500v2_command(pgm, buf, 3, sizeof(buf));
if (buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr, "%s: stk500v2_disable(): failed to leave programming mode, got 0x%02x\n", fprintf(stderr,
progname,buf[1]); "%s: stk500v2_disable(): failed to leave programming mode\n",
progname);
} }
return; return;
@ -879,11 +894,11 @@ static void stk500hv_disable(PROGRAMMER * pgm, enum hvmode mode)
result = stk500v2_command(pgm, buf, 3, sizeof(buf)); result = stk500v2_command(pgm, buf, 3, sizeof(buf));
if (result < 0 || buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr, fprintf(stderr,
"%s: stk500hv_disable(): " "%s: stk500hv_disable(): "
"failed to leave programming mode, got 0x%02x\n", "failed to leave programming mode\n",
progname,buf[1]); progname);
exit(1); exit(1);
} }
@ -986,9 +1001,10 @@ static int stk500v2_loadaddr(PROGRAMMER * pgm, unsigned int addr)
result = stk500v2_command(pgm, buf, 5, sizeof(buf)); result = stk500v2_command(pgm, buf, 5, sizeof(buf));
if (buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr, "%s: stk500v2_loadaddr(): failed to set load address, got 0x%02x\n", fprintf(stderr,
progname,buf[1]); "%s: stk500v2_loadaddr(): failed to set load address\n",
progname);
return -1; return -1;
} }
@ -1090,11 +1106,11 @@ static int stk500hv_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
result = stk500v2_command(pgm, buf, cmdlen, sizeof(buf)); result = stk500v2_command(pgm, buf, cmdlen, sizeof(buf));
if (result < 0 || buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr, fprintf(stderr,
"%s: stk500hv_read_byte(): " "%s: stk500hv_read_byte(): "
"timeout/error communicating with programmer (status %d)\n", "timeout/error communicating with programmer\n",
progname, result); progname);
return -1; return -1;
} }
@ -1254,11 +1270,11 @@ static int stk500hv_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
result = stk500v2_command(pgm, buf, cmdlen, sizeof(buf)); result = stk500v2_command(pgm, buf, cmdlen, sizeof(buf));
if (result < 0 || buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr, fprintf(stderr,
"%s: stk500hv_write_byte(): " "%s: stk500hv_write_byte(): "
"timeout/error communicating with programmer (status %d)\n", "timeout/error communicating with programmer\n",
progname, result); progname);
return -1; return -1;
} }
@ -1411,9 +1427,10 @@ static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
memcpy(buf+10,m->buf+addr, block_size); memcpy(buf+10,m->buf+addr, block_size);
result = stk500v2_command(pgm,buf,block_size+10, sizeof(buf)); result = stk500v2_command(pgm,buf,block_size+10, sizeof(buf));
if (buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr,"%s: stk500v2_paged_write: write command failed with %d\n", fprintf(stderr,
progname,buf[1]); "%s: stk500v2_paged_write: write command failed\n",
progname);
return -1; return -1;
} }
} }
@ -1508,9 +1525,10 @@ static int stk500hv_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
memset(buf + 5 + block_size, 0xff, page_size - block_size); memset(buf + 5 + block_size, 0xff, page_size - block_size);
result = stk500v2_command(pgm, buf, page_size + 5, sizeof(buf)); result = stk500v2_command(pgm, buf, page_size + 5, sizeof(buf));
if (buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr, "%s: stk500hv_paged_write: write command failed with %d\n", fprintf(stderr,
progname, buf[1]); "%s: stk500hv_paged_write: write command failed\n",
progname);
return -1; return -1;
} }
} }
@ -1621,9 +1639,10 @@ static int stk500v2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
} }
result = stk500v2_command(pgm,buf,4,sizeof(buf)); result = stk500v2_command(pgm,buf,4,sizeof(buf));
if (buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr,"%s: stk500v2_paged_load: read command failed with %d\n", fprintf(stderr,
progname,buf[1]); "%s: stk500v2_paged_load: read command failed\n",
progname);
return -1; return -1;
} }
#if 0 #if 0
@ -1699,9 +1718,10 @@ static int stk500hv_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
} }
result = stk500v2_command(pgm, buf, 3, sizeof(buf)); result = stk500v2_command(pgm, buf, 3, sizeof(buf));
if (buf[1] != STATUS_CMD_OK) { if (result < 0) {
fprintf(stderr, "%s: stk500hv_paged_load: read command failed with %d\n", fprintf(stderr,
progname, buf[1]); "%s: stk500hv_paged_load: read command failed\n",
progname);
return -1; return -1;
} }
#if 0 #if 0
@ -2088,6 +2108,23 @@ static void stk500v2_print_parms(PROGRAMMER * pgm)
stk500v2_print_parms1(pgm, ""); stk500v2_print_parms1(pgm, "");
} }
static int stk500v2_perform_osccal(PROGRAMMER * pgm)
{
unsigned char buf[32];
int rv;
buf[0] = CMD_OSCCAL;
rv = stk500v2_command(pgm, buf, 1, sizeof(buf));
if (rv < 0) {
fprintf(stderr, "%s: stk500v2_perform_osccal(): failed\n",
progname);
return -1;
}
return 0;
}
/* /*
* Wrapper functions for the JTAG ICE mkII in ISP mode. This mode * Wrapper functions for the JTAG ICE mkII in ISP mode. This mode
@ -2183,6 +2220,7 @@ void stk500v2_initpgm(PROGRAMMER * pgm)
pgm->set_varef = stk500v2_set_varef; pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc; pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period; pgm->set_sck_period = stk500v2_set_sck_period;
pgm->perform_osccal = stk500v2_perform_osccal;
pgm->page_size = 256; pgm->page_size = 256;
} }
@ -2274,5 +2312,6 @@ void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm)
pgm->paged_load = stk500v2_paged_load; pgm->paged_load = stk500v2_paged_load;
pgm->print_parms = stk500v2_print_parms; pgm->print_parms = stk500v2_print_parms;
pgm->set_sck_period = stk500v2_set_sck_period_mk2; pgm->set_sck_period = stk500v2_set_sck_period_mk2;
pgm->perform_osccal = stk500v2_perform_osccal;
pgm->page_size = 256; pgm->page_size = 256;
} }