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
This commit is contained in:
parent
5b12f02975
commit
4d2df35736
81
avr.c
81
avr.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
4
avr.h
4
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);
|
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
|
||||||
|
|
24
avrdude.1
24
avrdude.1
|
@ -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,
|
||||||
|
|
2
fileio.c
2
fileio.c
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
50
main.c
50
main.c
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue