Fix error reporting by avr_write_byte().

Fix setting of status LEDs under various write-fail conditions.

Add a flag to indicate that a memory type requires the device to
possibly be powered off and back on after a write to it.  This is due
to a hardware problem on some Atmel devices, see:

	http://www.atmel.com/atmel/acrobat/doc1280.pdf

Add greater verbosity to the part-display code when verbose>1 to
display avrprog's encoding of the defined programming instructions.
This is primarily for debugging purposes.


Part updates:

  * add the AT90S4414 part

  * add fuse and lock bit access instructions for the AT90S1200,
    AT90S4434, and AT90S8515.

  * add the pwroff_after_write flag to the fuse bits for the AT90S2333
    and AT90S4433 parts


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@123 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Brian S. Dean 2002-02-14 02:48:07 +00:00
parent e4790aa020
commit 333d246562
7 changed files with 273 additions and 23 deletions

View File

@ -442,8 +442,9 @@ 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))) {
fprintf(stderr, " \r%4lu 0x%02x", i, rbyte); fprintf(stderr, "\r \r%6lu", i);
}
} }
} }
@ -524,7 +525,7 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem,
rc = avr_read_byte(fd, p, mem, addr, &b); rc = avr_read_byte(fd, p, mem, addr, &b);
if (rc != 0) { if (rc != 0) {
if (rc != -1) { if (rc != -1) {
return -1; return -2;
} }
/* /*
* the read operation is not support on this memory type * the read operation is not support on this memory type
@ -603,11 +604,14 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem,
tries = 0; tries = 0;
ready = 0; ready = 0;
while (!ready) { while (!ready) {
usleep(mem->min_write_delay); /* typical write delay */ usleep(mem->min_write_delay);
rc = avr_read_byte(fd, p, mem, addr, &r); rc = avr_read_byte(fd, p, mem, addr, &r);
if (rc != 0) { if (rc != 0) {
return -1; LED_OFF(fd, pgm->pinno[PIN_LED_PGM]);
LED_ON(fd, pgm->pinno[PIN_LED_ERR]);
return -4;
} }
if ((data == mem->readback[0]) || if ((data == mem->readback[0]) ||
(data == mem->readback[1])) { (data == mem->readback[1])) {
/* /*
@ -619,24 +623,62 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem,
usleep(mem->max_write_delay); usleep(mem->max_write_delay);
rc = avr_read_byte(fd, p, mem, addr, &r); rc = avr_read_byte(fd, p, mem, addr, &r);
if (rc != 0) { if (rc != 0) {
return -1; LED_OFF(fd, pgm->pinno[PIN_LED_PGM]);
LED_ON(fd, pgm->pinno[PIN_LED_ERR]);
return -5;
} }
} }
if (r == data) { if (r == data) {
ready = 1; ready = 1;
} }
else if (mem->pwroff_after_write) {
/*
* The device has been flagged as power-off after write to this
* memory type. The reason we don't just blindly follow the
* flag is that the power-off advice may only apply to some
* memory bits but not all. We only actually power-off the
* device if the data read back does not match what we wrote.
*/
usleep(mem->max_write_delay); /* maximum write delay */
LED_OFF(fd, pgm->pinno[PIN_LED_PGM]);
fprintf(stderr,
"%s: this device must be powered off and back on to continue\n",
progname);
if (pgm->pinno[PPI_AVR_VCC]) {
fprintf(stderr, "%s: attempting to do this now ...\n", progname);
avr_powerdown(fd);
usleep(250000);
rc = avr_initialize(fd, p);
if (rc < 0) {
fprintf(stderr, "%s: initialization failed, rc=%d\n", progname, rc);
fprintf(stderr,
"%s: can't re-initialize device after programming the "
"%s bits\n", progname, mem->desc);
fprintf(stderr,
"%s: you must manually power-down the device and restart\n"
"%s: avrprog to continue.\n",
progname, progname);
return -3;
}
fprintf(stderr, "%s: device was successfully re-initialized\n",
progname);
return 0;
}
}
tries++; tries++;
if (!ready && tries > 5) { if (!ready && tries > 5) {
/* /*
* we couldn't write the data, indicate our displeasure by * we wrote the data, but after waiting for what should have
* returning an error code * been plenty of time, the memory cell still doesn't match what
* we wrote. Indicate a write error.
*/ */
LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); LED_OFF(fd, pgm->pinno[PIN_LED_PGM]);
LED_ON(fd, pgm->pinno[PIN_LED_ERR]); LED_ON(fd, pgm->pinno[PIN_LED_ERR]);
return -1; return -6;
} }
} }
@ -689,8 +731,9 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose)
for (i=0; i<wsize; i++) { for (i=0; i<wsize; i++) {
data = m->buf[i]; data = m->buf[i];
if (verbose) { if (verbose) {
if ((i % 16 == 0)||(i == (wsize-1))) if ((i % 16 == 0)||(i == (wsize-1))) {
fprintf(stderr, " \r%4lu 0x%02x ", i, data); fprintf(stderr, "\r \r%6lu", i);
}
} }
rc = avr_write_byte(fd, p, m, i, data); rc = avr_write_byte(fd, p, m, i, data);
if (rc) { if (rc) {
@ -953,7 +996,7 @@ int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size)
for (i=0; i<size; i++) { for (i=0; i<size; i++) {
if (buf1[i] != buf2[i]) { if (buf1[i] != buf2[i]) {
fprintf(stderr, fprintf(stderr,
"%s: verification error, first mismatch at byte %d\n" "%s: verification error, first mismatch at byte 0x%04x\n"
"%s0x%02x != 0x%02x\n", "%s0x%02x != 0x%02x\n",
progname, i, progname, i,
progbuf, buf1[i], buf2[i]); progbuf, buf1[i], buf2[i]);
@ -966,8 +1009,45 @@ int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size)
void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type) char * avr_op_str(int op)
{ {
switch (op) {
case AVR_OP_READ : return "READ"; break;
case AVR_OP_WRITE : return "WRITE"; break;
case AVR_OP_READ_LO : return "READ_LO"; break;
case AVR_OP_READ_HI : return "READ_HI"; break;
case AVR_OP_WRITE_LO : return "WRITE_LO"; break;
case AVR_OP_WRITE_HI : return "WRITE_HI"; break;
case AVR_OP_LOADPAGE_LO : return "LOADPAGE_LO"; break;
case AVR_OP_LOADPAGE_HI : return "LOADPAGE_HI"; break;
case AVR_OP_WRITEPAGE : return "WRITEPAGE"; break;
case AVR_OP_CHIP_ERASE : return "CHIP_ERASE"; break;
case AVR_OP_PGM_ENABLE : return "PGM_ENABLE"; break;
default : return "<unknown opcode>"; break;
}
}
char * bittype(int type)
{
switch (type) {
case AVR_CMDBIT_IGNORE : return "IGNORE"; break;
case AVR_CMDBIT_VALUE : return "VALUE"; break;
case AVR_CMDBIT_ADDRESS : return "ADDRESS"; break;
case AVR_CMDBIT_INPUT : return "INPUT"; break;
case AVR_CMDBIT_OUTPUT : return "OUTPUT"; break;
default : return "<unknown bit type>"; break;
}
}
void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type,
int verbose)
{
int i, j;
char * optr;
if (m == NULL) { if (m == NULL) {
fprintf(f, fprintf(f,
"%s Page Polled\n" "%s Page Polled\n"
@ -976,6 +1056,13 @@ void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type)
prefix, prefix, prefix); prefix, prefix, prefix);
} }
else { else {
if (verbose > 1) {
fprintf(f,
"%s Page Polled\n"
"%sMemory Type Paged Size Size #Pages MinW MaxW ReadBack\n"
"%s----------- ------ ------ ---- ------ ----- ----- ---------\n",
prefix, prefix, prefix);
}
fprintf(f, fprintf(f,
"%s%-11s %-6s %6d %4d %5d %5d %5d 0x%02x 0x%02x\n", "%s%-11s %-6s %6d %4d %5d %5d %5d 0x%02x 0x%02x\n",
prefix, m->desc, prefix, m->desc,
@ -987,12 +1074,35 @@ void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type)
m->max_write_delay, m->max_write_delay,
m->readback[0], m->readback[0],
m->readback[1]); m->readback[1]);
if (verbose > 1) {
fprintf(stderr,
"%s Memory Ops:\n"
"%s Oeration Inst Bit Bit Type Bitno Value\n"
"%s ----------- -------- -------- ----- -----\n",
prefix, prefix, prefix);
for (i=0; i<AVR_OP_MAX; i++) {
if (m->op[i]) {
for (j=31; j>=0; j--) {
if (j==31)
optr = avr_op_str(i);
else
optr = " ";
fprintf(f,
"%s %-11s %8d %8s %5d %5d\n",
prefix, optr, j,
bittype(m->op[i]->bit[j].type),
m->op[i]->bit[j].bitno,
m->op[i]->bit[j].value);
}
}
}
}
} }
} }
void avr_display(FILE * f, AVRPART * p, char * prefix) void avr_display(FILE * f, AVRPART * p, char * prefix, int verbose)
{ {
int i; int i;
char * buf; char * buf;
@ -1020,10 +1130,12 @@ void avr_display(FILE * f, AVRPART * p, char * prefix)
px = buf; px = buf;
} }
avr_mem_display(px, f, NULL, 0); if (verbose <= 1) {
avr_mem_display(px, f, NULL, 0, verbose);
}
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
m = ldata(ln); m = ldata(ln);
avr_mem_display(px, f, m, i); avr_mem_display(px, f, m, i, verbose);
} }
if (buf) if (buf)

View File

@ -87,6 +87,10 @@ typedef struct avrmem {
int num_pages; /* number of pages (if page addressed) */ int num_pages; /* number of pages (if page addressed) */
int min_write_delay; /* microseconds */ int min_write_delay; /* microseconds */
int max_write_delay; /* microseconds */ int max_write_delay; /* microseconds */
int pwroff_after_write; /* after this memory type is written to,
the device must be powered off and
back on, see errata
http://www.atmel.com/atmel/acrobat/doc1280.pdf */
unsigned char readback[2]; /* polled read-back values */ unsigned char readback[2]; /* polled read-back values */
unsigned char * buf; /* pointer to memory buffer */ unsigned char * buf; /* pointer to memory buffer */
OPCODE * op[AVR_OP_MAX]; /* opcodes */ OPCODE * op[AVR_OP_MAX]; /* opcodes */
@ -158,7 +162,9 @@ int avr_initmem(AVRPART * p);
int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size); int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size);
void avr_display(FILE * f, AVRPART * p, char * prefix); void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type,
int verbose);
void avr_display(FILE * f, AVRPART * p, char * prefix, int verbose);
#endif #endif

View File

@ -209,6 +209,82 @@ part
read = "0 0 1 1 0 0 0 0 x x x x x x x x", read = "0 0 1 1 0 0 0 0 x x x x x x x x",
"x x x x x x a1 a0 o o o o o o o o"; "x x x x x x a1 a0 o o o o o o o o";
; ;
memory "fuse"
size = 1;
min_write_delay = 9000;
max_write_delay = 20000;
read = "0 1 0 1 0 0 0 0 x x x x x x x x",
"x x x x x x x x x x o o o o o o";
write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i",
"x x x x x x x x x x x x x x x x";
;
memory "lock"
size = 1;
min_write_delay = 9000;
max_write_delay = 20000;
read = "0 1 0 1 1 0 0 0 x x x x x x x x",
"x x x x x x x x x x x x x o o x";
write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1",
"x x x x x x x x x x x x x x x x";
;
;
part
id = "4414";
desc = "AT90S4414";
chip_erase_delay = 20000;
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
"x x x x x x x x x x x x x x x x";
chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0",
"x x x x x x x x x x x x x x x x";
memory "eeprom"
size = 256;
min_write_delay = 9000;
max_write_delay = 20000;
readback_p1 = 0x80;
readback_p2 = 0x7f;
read = " 1 0 1 0 0 0 0 0 x x x x x x x a8",
"a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
write = " 1 1 0 0 0 0 0 0 x x x x x x x a8",
"a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i";
;
memory "flash"
size = 4096;
min_write_delay = 9000;
max_write_delay = 20000;
readback_p1 = 0x7f;
readback_p2 = 0x00;
read_lo = " 0 0 1 0 0 0 0 0",
" x x x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
read_hi = " 0 0 1 0 1 0 0 0",
" x x x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
write_lo = " 0 1 0 0 0 0 0 0",
" x x x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
write_hi = " 0 1 0 0 1 0 0 0",
" x x x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
;
memory "signature"
size = 3;
read = "0 0 1 1 0 0 0 0 x x x x x x x x",
"x x x x x x a1 a0 o o o o o o o o";
;
; ;
@ -335,6 +411,8 @@ part
write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i",
"x x x x x x x x x x x x x x x x"; "x x x x x x x x x x x x x x x x";
pwroff_after_write = 1;
; ;
memory "lock" memory "lock"
size = 1; size = 1;
@ -411,6 +489,8 @@ part
write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i",
"x x x x x x x x x x x x x x x x"; "x x x x x x x x x x x x x x x x";
pwroff_after_write = 1;
; ;
memory "lock" memory "lock"
size = 1; size = 1;
@ -478,6 +558,26 @@ part
read = "0 0 1 1 0 0 0 0 x x x x x x x x", read = "0 0 1 1 0 0 0 0 x x x x x x x x",
"x x x x x x a1 a0 o o o o o o o o"; "x x x x x x a1 a0 o o o o o o o o";
; ;
memory "fuse"
size = 1;
min_write_delay = 9000;
max_write_delay = 20000;
read = "0 1 0 1 0 0 0 0 x x x x x x x x",
"x x x x x x x x x x o o o o o o";
write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i",
"x x x x x x x x x x x x x x x x";
;
memory "lock"
size = 1;
min_write_delay = 9000;
max_write_delay = 20000;
read = "0 1 0 1 1 0 0 0 x x x x x x x x",
"x x x x x x x x x x x x x o o x";
write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1",
"x x x x x x x x x x x x x x x x";
;
; ;
@ -534,6 +634,20 @@ part
read = "0 0 1 1 0 0 0 0 x x x x x x x x", read = "0 0 1 1 0 0 0 0 x x x x x x x x",
"x x x x x x a1 a0 o o o o o o o o"; "x x x x x x a1 a0 o o o o o o o o";
; ;
memory "fuse"
size = 1;
read = "0 1 0 1 1 0 0 0 x x x x x x x x",
"x x x x x x x x x x x x x x x o";
write = "1 0 1 0 1 1 0 0 1 0 1 1 1 1 1 i",
"x x x x x x x x x x x x x x x x";
;
memory "lock"
size = 1;
read = "0 1 0 1 1 0 0 0 x x x x x x x x",
"x x x x x x x x o o x x x x x x";
write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1",
"x x x x x x x x x x x x x x x x";
;
; ;

View File

@ -60,6 +60,7 @@
%token K_NUM_PAGES %token K_NUM_PAGES
%token K_PART %token K_PART
%token K_PGMLED %token K_PGMLED
%token K_PWROFF_AFTER_WRITE
%token K_PROGRAMMER %token K_PROGRAMMER
%token K_RDYLED %token K_RDYLED
%token K_READBACK_P1 %token K_READBACK_P1
@ -398,6 +399,12 @@ mem_spec :
free_token($3); free_token($3);
} | } |
K_PWROFF_AFTER_WRITE TKN_EQUAL TKN_NUMBER
{
current_mem->pwroff_after_write = $3->value.number;
free_token($3);
} |
K_READBACK_P1 TKN_EQUAL TKN_NUMBER K_READBACK_P1 TKN_EQUAL TKN_NUMBER
{ {
current_mem->readback[0] = $3->value.number; current_mem->readback[0] = $3->value.number;

View File

@ -142,6 +142,7 @@ page_size { yylval=NULL; return K_PAGE_SIZE; }
paged { yylval=NULL; return K_PAGED; } paged { yylval=NULL; return K_PAGED; }
part { yylval=NULL; return K_PART; } part { yylval=NULL; return K_PART; }
pgmled { yylval=NULL; return K_PGMLED; } pgmled { yylval=NULL; return K_PGMLED; }
pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; }
programmer { yylval=NULL; return K_PROGRAMMER; } programmer { yylval=NULL; return K_PROGRAMMER; }
rdyled { yylval=NULL; return K_RDYLED; } rdyled { yylval=NULL; return K_RDYLED; }
readback_p1 { yylval=NULL; return K_READBACK_P1; } readback_p1 { yylval=NULL; return K_READBACK_P1; }

View File

@ -764,7 +764,7 @@ int main(int argc, char * argv [])
v = avr_dup_part(p); v = avr_dup_part(p);
if (verbose) { if (verbose) {
avr_display(stderr, p, progbuf); avr_display(stderr, p, progbuf, verbose);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
pinconfig_display(progbuf); pinconfig_display(progbuf);
} }

View File

@ -303,7 +303,8 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[])
int len, maxsize; int len, maxsize;
char * memtype; char * memtype;
unsigned long addr, i; unsigned long addr, i;
char * buf; unsigned char * buf;
unsigned char b;
int rc; int rc;
int werror; int werror;
AVRMEM * mem; AVRMEM * mem;
@ -371,14 +372,23 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[])
rc = avr_write_byte(fd, p, mem, addr+i, buf[i]); rc = avr_write_byte(fd, p, mem, addr+i, buf[i]);
if (rc) { if (rc) {
fprintf(stderr, "%s (write): error writing 0x%02x at 0x%05lx\n", fprintf(stderr, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n",
progname, buf[i], addr+i); progname, buf[i], addr+i, rc);
if (rc == -1) if (rc == -1)
fprintf(stderr, fprintf(stderr,
"write operation not supported on memory type \"%s\"\n", "write operation not supported on memory type \"%s\"\n",
mem->desc); mem->desc);
werror = 1; werror = 1;
} }
rc = avr_read_byte(fd, p, mem, addr+i, &b);
if (b != buf[i]) {
fprintf(stderr,
"%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n",
progname, buf[i], addr+i, b);
werror = 1;
}
if (werror) { if (werror) {
LED_ON(fd, pgm->pinno[PIN_LED_ERR]); LED_ON(fd, pgm->pinno[PIN_LED_ERR]);
} }
@ -446,7 +456,7 @@ int cmd_erase(int fd, struct avrpart * p, int argc, char * argv[])
int cmd_part(int fd, struct avrpart * p, int argc, char * argv[]) int cmd_part(int fd, struct avrpart * p, int argc, char * argv[])
{ {
fprintf(stdout, "\n"); fprintf(stdout, "\n");
avr_display(stdout, p, ""); avr_display(stdout, p, "", 0);
fprintf(stdout, "\n"); fprintf(stdout, "\n");
return 0; return 0;