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@138 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Brian S. Dean 2002-08-01 01:00:03 +00:00
parent 777d96086a
commit c7a17e849a
5 changed files with 152 additions and 11 deletions

View File

@ -417,6 +417,7 @@ int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose)
unsigned char * buf; unsigned char * buf;
AVRMEM * mem; AVRMEM * mem;
int rc; int rc;
int printed;
mem = avr_locate_mem(p, memtype); mem = avr_locate_mem(p, memtype);
if (mem == NULL) { if (mem == NULL) {
@ -430,6 +431,8 @@ int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose)
size = mem->size; size = mem->size;
} }
printed = 0;
for (i=0; i<size; i++) { for (i=0; i<size; i++) {
rc = avr_read_byte(fd, p, mem, i, &rbyte); rc = avr_read_byte(fd, p, mem, i, &rbyte);
if (rc != 0) { if (rc != 0) {
@ -443,12 +446,15 @@ int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose)
buf[i] = rbyte; buf[i] = rbyte;
if (verbose) { if (verbose) {
if ((i % 16 == 0)||(i == (size-1))) { if ((i % 16 == 0)||(i == (size-1))) {
printed = 1;
fprintf(stderr, "\r \r%6lu", i); fprintf(stderr, "\r \r%6lu", i);
} }
} }
} }
fprintf(stderr, "\n"); if (printed) {
fprintf(stderr, "\n");
}
return i; return i;
} }
@ -704,6 +710,7 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose)
unsigned char data; unsigned char data;
int werror; int werror;
AVRMEM * m; AVRMEM * m;
int printed;
m = avr_locate_mem(p, memtype); m = avr_locate_mem(p, memtype);
if (m == NULL) { if (m == NULL) {
@ -714,7 +721,8 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose)
LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); LED_OFF(fd, pgm->pinno[PIN_LED_ERR]);
werror = 0; printed = 0;
werror = 0;
wsize = m->size; wsize = m->size;
if (size < wsize) { if (size < wsize) {
@ -733,6 +741,7 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose)
if (verbose) { if (verbose) {
if ((i % 16 == 0)||(i == (wsize-1))) { if ((i % 16 == 0)||(i == (wsize-1))) {
fprintf(stderr, "\r \r%6lu", i); fprintf(stderr, "\r \r%6lu", i);
printed = 1;
} }
} }
rc = avr_write_byte(fd, p, m, i, data); 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)
} }
} }
if (printed)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
return i; 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) char * avr_op_str(int op)
{ {

View File

@ -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); 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 #endif

View File

@ -293,6 +293,30 @@ Tells
.Nm .Nm
to enter the interactive ``terminal'' mode instead of up- or downloading to enter the interactive ``terminal'' mode instead of up- or downloading
files. See below for a detailed description of the terminal mode. 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 .El
.Ss Terminal mode .Ss Terminal mode
In this mode, In this mode,

View File

@ -583,7 +583,7 @@ int fileio(int op, char * filename, FILEFMT format,
return -1; 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)); progname, fio.iodesc, fname, fmtstr(format));
} }

View File

@ -115,7 +115,7 @@ char ** modules[N_MODULES] = {
&term_version &term_version
}; };
char * version = "2.0.3"; char * version = "2.1.0";
char * main_version = "$Id$"; char * main_version = "$Id$";
@ -486,6 +486,10 @@ int main(int argc, char * argv [])
char * pinconfig; /* programmer id */ char * pinconfig; /* programmer id */
char * partdesc; /* part id */ char * partdesc; /* part id */
char configfile[PATH_MAX]; /* pin configuration file */ 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],'/'); progname = rindex(argv[0],'/');
if (progname) if (progname)
@ -515,6 +519,8 @@ int main(int argc, char * argv [])
pgm = NULL; pgm = NULL;
pinconfig = "avrprog"; /* compiled-in default */ pinconfig = "avrprog"; /* compiled-in default */
verbose = 0; verbose = 0;
do_cycles = 0;
set_cycles = -1;
strcpy(configfile, CONFIG_DIR); strcpy(configfile, CONFIG_DIR);
i = strlen(configfile); i = strlen(configfile);
@ -561,7 +567,7 @@ int main(int argc, char * argv [])
/* /*
* process command line arguments * 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) { switch (ch) {
case 'c': /* pin configuration */ case 'c': /* pin configuration */
@ -671,6 +677,19 @@ int main(int argc, char * argv [])
verbose++; verbose++;
break; 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 */ case '?': /* help */
usage(); usage();
exit(0); exit(0);
@ -834,6 +853,17 @@ int main(int argc, char * argv [])
"%s: AVR device initialized and ready to accept instructions\n", "%s: AVR device initialized and ready to accept instructions\n",
progname); 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 * 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 * chip on the other end that is responding correctly. A check
@ -852,7 +882,7 @@ int main(int argc, char * argv [])
fprintf(stderr, fprintf(stderr,
"%s: WARNING: signature data not defined for device \"%s\"\n", "%s: WARNING: signature data not defined for device \"%s\"\n",
progname, p->desc); progname, p->desc);
} }
if (sig != NULL) { if (sig != NULL) {
int ff; int ff;
@ -880,19 +910,29 @@ int main(int argc, char * argv [])
} }
} }
fprintf(stderr, "\n");
if (erase) { if (erase) {
/* /*
* erase the chip's flash and eeprom memories, this is required * erase the chip's flash and eeprom memories, this is required
* before the chip can accept new programming * before the chip can accept new programming
*/ */
fprintf(stderr, "%s: erasing chip\n", progname); fprintf(stderr, "%s: erasing chip\n", progname);
avr_chip_erase(fd,p); 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); fprintf(stderr, "%s: done.\n", progname);
} }
if (!terminal && ((inputf==NULL) && (outputf==NULL))) { if (!terminal && ((inputf==NULL) && (outputf==NULL))) {
/* /*
* Check here to see if any other operations were selected and * Check here to see if any other operations were selected and