From 4d2df357362de382b3b1f199c4023a0daf1e33d3 Mon Sep 17 00:00:00 2001 From: "Brian S. Dean" Date: Thu, 1 Aug 2002 01:00:03 +0000 Subject: [PATCH] Implement a way of tracking how many erase-rewrite cycles a part has undergone. This utilizes the last two bytes of EEPROM to maintain a counter that is incremented each time the part is erased. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@138 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avr.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- avr.h | 4 +++ avrdude.1 | 24 +++++++++++++++++ fileio.c | 2 +- main.c | 52 ++++++++++++++++++++++++++++++----- 5 files changed, 152 insertions(+), 11 deletions(-) diff --git a/avr.c b/avr.c index 5ce5c3a1..3a342521 100644 --- a/avr.c +++ b/avr.c @@ -417,6 +417,7 @@ int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose) unsigned char * buf; AVRMEM * mem; int rc; + int printed; mem = avr_locate_mem(p, memtype); if (mem == NULL) { @@ -430,6 +431,8 @@ int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose) size = mem->size; } + printed = 0; + for (i=0; ipinno[PIN_LED_ERR]); - werror = 0; + printed = 0; + werror = 0; wsize = m->size; if (size < wsize) { @@ -733,6 +741,7 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose) if (verbose) { if ((i % 16 == 0)||(i == (wsize-1))) { fprintf(stderr, "\r \r%6lu", i); + printed = 1; } } rc = avr_write_byte(fd, p, m, i, data); @@ -773,8 +782,8 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose) } } - - fprintf(stderr, "\n"); + if (printed) + fprintf(stderr, "\n"); return i; } @@ -1008,6 +1017,70 @@ int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size) } +int avr_get_cycle_count(int fd, AVRPART * p) +{ + int size; + AVRMEM * a; + int cycle_count; + unsigned char v1, v2; + int rc; + + a = avr_locate_mem(p, "eeprom"); + if (a == NULL) { + return -1; + } + + rc = avr_read_byte(fd, p, a, a->size-2, &v1); + if (rc < 0) { + fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n", + progname, rc); + return -1; + } + rc = avr_read_byte(fd, p, a, a->size-1, &v2); + if (rc < 0) { + fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n", + progname, rc); + return -1; + } + + cycle_count = ((unsigned int)v1) << 8 | v2; + + return cycle_count; +} + + +int avr_put_cycle_count(int fd, AVRPART * p, int cycles) +{ + int size; + AVRMEM * a; + unsigned char v1, v2; + int rc; + + a = avr_locate_mem(p, "eeprom"); + if (a == NULL) { + return -1; + } + + v2 = cycles & 0x0ff; + v1 = (cycles & 0x0ff00) >> 8; + + rc = avr_write_byte(fd, p, a, a->size-2, v1); + if (rc < 0) { + fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n", + progname, rc); + return -1; + } + rc = avr_write_byte(fd, p, a, a->size-1, v2); + if (rc < 0) { + fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n", + progname, rc); + return -1; + } + + return 0; +} + + char * avr_op_str(int op) { diff --git a/avr.h b/avr.h index fd2e8890..9f46da86 100644 --- a/avr.h +++ b/avr.h @@ -167,4 +167,8 @@ void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type, void avr_display(FILE * f, AVRPART * p, char * prefix, int verbose); +int avr_get_cycle_count(int fd, AVRPART * p); + +int avr_put_cycle_count(int fd, AVRPART * p, int cycles); + #endif diff --git a/avrdude.1 b/avrdude.1 index 2629aa9c..d9eda1d8 100644 --- a/avrdude.1 +++ b/avrdude.1 @@ -293,6 +293,30 @@ Tells .Nm to enter the interactive ``terminal'' mode instead of up- or downloading files. See below for a detailed description of the terminal mode. +.It Fl y +Tells +.Nm +to use the last two bytes of the connected parts' EEPROM memory to +track the number of times the device has been erased. When this +option is used and the +.Fl e +flag is specified to generate a chip erase, the previous counter will +be saved before the chip erase, it is then incremented, and written +back after the erase cycle completes. Presumably, the device would +only be erased just before being programmed, and thus, this can be +utilized to give an indication of how may erase-rewrite cycles the +part has undergone. Since the FLASH memory can only endure a finite +number of erase-rewrite cycles, one can use this option to track when +a part is nearing the limit. The typical limit for Atmel AVR FLASH is +1000 cycles. Of course, if the application needs the last two bytes +of EEPROM memory, this option should not be used. +.It Fl Y Ar cycles +Instructs +.Nm +to initialize the erase-rewrite cycle counter residing at the last two +bytes of EEPROM memory to the specified value. If the application +needs the last two bytes of EEPROM memory, this option should not be +used. .El .Ss Terminal mode In this mode, diff --git a/fileio.c b/fileio.c index ae792164..3b9dff6a 100644 --- a/fileio.c +++ b/fileio.c @@ -583,7 +583,7 @@ int fileio(int op, char * filename, FILEFMT format, return -1; } - fprintf(stderr, "%s: %s file %s auto detected as %s\n\n", + fprintf(stderr, "%s: %s file %s auto detected as %s\n", progname, fio.iodesc, fname, fmtstr(format)); } diff --git a/main.c b/main.c index fe42265d..3cadd512 100644 --- a/main.c +++ b/main.c @@ -115,7 +115,7 @@ char ** modules[N_MODULES] = { &term_version }; -char * version = "2.0.3"; +char * version = "2.1.0"; char * main_version = "$Id$"; @@ -486,6 +486,10 @@ int main(int argc, char * argv []) char * pinconfig; /* programmer id */ char * partdesc; /* part id */ char configfile[PATH_MAX]; /* pin configuration file */ + int cycles; /* erase-rewrite cycles */ + int set_cycles; /* value to set the erase-rewrite cycles to */ + int do_cycles; /* track erase-rewrite cycles */ + char * e; progname = rindex(argv[0],'/'); if (progname) @@ -515,6 +519,8 @@ int main(int argc, char * argv []) pgm = NULL; pinconfig = "avrprog"; /* compiled-in default */ verbose = 0; + do_cycles = 0; + set_cycles = -1; strcpy(configfile, CONFIG_DIR); i = strlen(configfile); @@ -561,7 +567,7 @@ int main(int argc, char * argv []) /* * process command line arguments */ - while ((ch = getopt(argc,argv,"?c:C:eE:f:Fi:m:no:p:P:tv")) != -1) { + while ((ch = getopt(argc,argv,"?c:C:eE:f:Fi:m:no:p:P:tvyY:")) != -1) { switch (ch) { case 'c': /* pin configuration */ @@ -671,6 +677,19 @@ int main(int argc, char * argv []) verbose++; break; + case 'y': + do_cycles = 1; + break; + + case 'Y': + set_cycles = strtol(optarg, &e, 0); + if ((e == optarg) || (*e != 0)) { + fprintf(stderr, "%s: invalid cycle count '%s'\n", + progname, optarg); + exit(1); + } + break; + case '?': /* help */ usage(); exit(0); @@ -834,6 +853,17 @@ int main(int argc, char * argv []) "%s: AVR device initialized and ready to accept instructions\n", progname); + /* + * see if the cycle count in the last two bytes of eeprom seems + * reasonable + */ + cycles = avr_get_cycle_count(fd, p); + if ((cycles != -1) && (cycles != 0x00ffff)) { + fprintf(stderr, + "%s: current erase-rewrite cycle count is %d (if being tracked)\n", + progname, cycles); + } + /* * Let's read the signature bytes to make sure there is at least a * chip on the other end that is responding correctly. A check @@ -852,7 +882,7 @@ int main(int argc, char * argv []) fprintf(stderr, "%s: WARNING: signature data not defined for device \"%s\"\n", progname, p->desc); - } + } if (sig != NULL) { int ff; @@ -880,19 +910,29 @@ int main(int argc, char * argv []) } } - fprintf(stderr, "\n"); - if (erase) { /* * erase the chip's flash and eeprom memories, this is required * before the chip can accept new programming */ + fprintf(stderr, "%s: erasing chip\n", progname); avr_chip_erase(fd,p); + if (do_cycles && (cycles != -1)) { + if (cycles == 0x00ffff) { + cycles = 0; + } + cycles++; + if (set_cycles != -1) { + cycles = set_cycles; + } + fprintf(stderr, "%s: erase-rewrite cycle count is now %d\n", + progname, cycles); + avr_put_cycle_count(fd, p, cycles); + } fprintf(stderr, "%s: done.\n", progname); } - if (!terminal && ((inputf==NULL) && (outputf==NULL))) { /* * Check here to see if any other operations were selected and