diff --git a/ChangeLog b/ChangeLog index 159dc169..0ab6cb8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2006-10-09 Joerg Wunsch + + 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 Submitted by freckle@sf.net: diff --git a/avrdude.1 b/avrdude.1 index fcc61864..0b424356 100644 --- a/avrdude.1 +++ b/avrdude.1 @@ -19,7 +19,7 @@ .\" .\" $Id$ .\" -.Dd DATE September 10, 2006 +.Dd DATE October 9, 2006 .Os .Dt AVRDUDE 1 .Sh NAME @@ -40,6 +40,7 @@ .Op Fl F .Op Fl i Ar delay .Op Fl n +.Op Fl O .Op Fl P Ar port .Op Fl q .Op Fl s @@ -360,6 +361,12 @@ slow machines. No-write - disables actually writing data to the MCU (useful for debugging .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 Use .Ar port diff --git a/doc/avrdude.texi b/doc/avrdude.texi index 27265c1e..9e3dafb8 100644 --- a/doc/avrdude.texi +++ b/doc/avrdude.texi @@ -505,6 +505,13 @@ slow machines. No-write - disables actually writing data to the MCU (useful for 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} Use port to identify the device to which the programmer is attached. Normally, the default parallel port is used, but if the programmer type diff --git a/main.c b/main.c index 6025122a..9b841a6c 100644 --- a/main.c +++ b/main.c @@ -110,6 +110,7 @@ void usage(void) " -P Specify connection port.\n" " -F Override invalid signature check.\n" " -e Perform a chip erase.\n" + " -O Perform RC oscillator calibration (see AVR053). \n" " -U :r|w|v:[:format]\n" " Memory operation specification.\n" " Multiple -U options are allowed, each request\n" @@ -682,6 +683,7 @@ int main(int argc, char * argv []) /* options / operating mode variables */ 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 so, 1=erase if we are going to program flash */ char * port; /* device port (/dev/xxx) */ @@ -739,6 +741,7 @@ int main(int argc, char * argv []) partdesc = NULL; port = default_parallel; erase = 0; + calibrate = 0; auto_erase = 1; p = NULL; ovsigck = 0; @@ -805,7 +808,7 @@ int main(int argc, char * argv []) /* * 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) { case 'b': /* override default programmer baud rate */ @@ -864,6 +867,10 @@ int main(int argc, char * argv []) nowrite = 1; break; + case 'O': /* perform RC oscillator calibration */ + calibrate = 1; + break; + case 'p' : /* specify AVR part */ partdesc = optarg; break; @@ -1151,6 +1158,21 @@ int main(int argc, char * argv []) 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) { avr_display(stderr, p, progbuf, verbose); fprintf(stderr, "\n"); diff --git a/pgm.c b/pgm.c index 606e7b31..b983dc81 100644 --- a/pgm.c +++ b/pgm.c @@ -123,6 +123,7 @@ PROGRAMMER * pgm_new(void) pgm->set_vtarget = NULL; pgm->set_varef = NULL; pgm->set_fosc = NULL; + pgm->perform_osccal = NULL; return pgm; } diff --git a/pgm.h b/pgm.h index 1a8813aa..bebdf6e3 100644 --- a/pgm.h +++ b/pgm.h @@ -100,6 +100,7 @@ typedef struct programmer_t { int (*getpin) (struct programmer_t * pgm, int pin); int (*highpulsepin) (struct programmer_t * pgm, int pin); int (*parseexitspecs) (struct programmer_t * pgm, char *s); + int (*perform_osccal) (struct programmer_t * pgm); char config_file[PATH_MAX]; /* config file where defined */ int lineno; /* config file line number */ char flag; /* for private use of the programmer */ diff --git a/stk500v2.c b/stk500v2.c index d58cc183..2087ae26 100644 --- a/stk500v2.c +++ b/stk500v2.c @@ -329,7 +329,7 @@ static int stk500v2_jtagmkII_recv(PROGRAMMER * pgm, unsigned char msg[], return -1; } memcpy(msg, jtagmsg + 1, rv - 1); - return 0; + return rv; } static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) { @@ -524,8 +524,8 @@ retry: return 0; } -static int stk500v2_command -(PROGRAMMER * pgm, unsigned char * buf, size_t len, size_t maxlen) { +static int stk500v2_command(PROGRAMMER * pgm, unsigned char * buf, + size_t len, size_t maxlen) { int i; int tries = 0; int status; @@ -539,14 +539,24 @@ retry: // send the command to the programmer stk500v2_send(pgm,buf,len); - // attempt to read the status back status = stk500v2_recv(pgm,buf,maxlen); // if we got a successful readback, return if (status > 0) { 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 @@ -582,10 +592,14 @@ static int stk500v2_cmd(PROGRAMMER * pgm, unsigned char cmd[4], buf[7] = cmd[3]; 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", progname); return -1; + } else if (result < 6) { + fprintf(stderr, "%s: stk500v2_cmd(): short reply, len = %d\n", + progname, result); + return -1; } 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)); - if (result < 0 || buf[1] != STATUS_CMD_OK) { + if (result < 0) { fprintf(stderr, "%s: stk500pp_initalize(): " - "failed to set control stack, got 0x%02x\n", - progname, buf[1]); + "failed to set control stack\n", + progname); return -1; } @@ -852,9 +866,10 @@ static void stk500v2_disable(PROGRAMMER * pgm) result = stk500v2_command(pgm, buf, 3, sizeof(buf)); - if (buf[1] != STATUS_CMD_OK) { - fprintf(stderr, "%s: stk500v2_disable(): failed to leave programming mode, got 0x%02x\n", - progname,buf[1]); + if (result < 0) { + fprintf(stderr, + "%s: stk500v2_disable(): failed to leave programming mode\n", + progname); } return; @@ -879,11 +894,11 @@ static void stk500hv_disable(PROGRAMMER * pgm, enum hvmode mode) result = stk500v2_command(pgm, buf, 3, sizeof(buf)); - if (result < 0 || buf[1] != STATUS_CMD_OK) { + if (result < 0) { fprintf(stderr, "%s: stk500hv_disable(): " - "failed to leave programming mode, got 0x%02x\n", - progname,buf[1]); + "failed to leave programming mode\n", + progname); exit(1); } @@ -986,9 +1001,10 @@ static int stk500v2_loadaddr(PROGRAMMER * pgm, unsigned int addr) result = stk500v2_command(pgm, buf, 5, sizeof(buf)); - if (buf[1] != STATUS_CMD_OK) { - fprintf(stderr, "%s: stk500v2_loadaddr(): failed to set load address, got 0x%02x\n", - progname,buf[1]); + if (result < 0) { + fprintf(stderr, + "%s: stk500v2_loadaddr(): failed to set load address\n", + progname); 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)); - if (result < 0 || buf[1] != STATUS_CMD_OK) { + if (result < 0) { fprintf(stderr, "%s: stk500hv_read_byte(): " - "timeout/error communicating with programmer (status %d)\n", - progname, result); + "timeout/error communicating with programmer\n", + progname); 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)); - if (result < 0 || buf[1] != STATUS_CMD_OK) { + if (result < 0) { fprintf(stderr, "%s: stk500hv_write_byte(): " - "timeout/error communicating with programmer (status %d)\n", - progname, result); + "timeout/error communicating with programmer\n", + progname); 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); result = stk500v2_command(pgm,buf,block_size+10, sizeof(buf)); - if (buf[1] != STATUS_CMD_OK) { - fprintf(stderr,"%s: stk500v2_paged_write: write command failed with %d\n", - progname,buf[1]); + if (result < 0) { + fprintf(stderr, + "%s: stk500v2_paged_write: write command failed\n", + progname); 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); result = stk500v2_command(pgm, buf, page_size + 5, sizeof(buf)); - if (buf[1] != STATUS_CMD_OK) { - fprintf(stderr, "%s: stk500hv_paged_write: write command failed with %d\n", - progname, buf[1]); + if (result < 0) { + fprintf(stderr, + "%s: stk500hv_paged_write: write command failed\n", + progname); 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)); - if (buf[1] != STATUS_CMD_OK) { - fprintf(stderr,"%s: stk500v2_paged_load: read command failed with %d\n", - progname,buf[1]); + if (result < 0) { + fprintf(stderr, + "%s: stk500v2_paged_load: read command failed\n", + progname); return -1; } #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)); - if (buf[1] != STATUS_CMD_OK) { - fprintf(stderr, "%s: stk500hv_paged_load: read command failed with %d\n", - progname, buf[1]); + if (result < 0) { + fprintf(stderr, + "%s: stk500hv_paged_load: read command failed\n", + progname); return -1; } #if 0 @@ -2088,6 +2108,23 @@ static void stk500v2_print_parms(PROGRAMMER * 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 @@ -2183,6 +2220,7 @@ void stk500v2_initpgm(PROGRAMMER * pgm) pgm->set_varef = stk500v2_set_varef; pgm->set_fosc = stk500v2_set_fosc; pgm->set_sck_period = stk500v2_set_sck_period; + pgm->perform_osccal = stk500v2_perform_osccal; pgm->page_size = 256; } @@ -2274,5 +2312,6 @@ void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm) pgm->paged_load = stk500v2_paged_load; pgm->print_parms = stk500v2_print_parms; pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->perform_osccal = stk500v2_perform_osccal; pgm->page_size = 256; }