From 4337d15fc4aca36cc43b57dc9f2d966863cc4a5b Mon Sep 17 00:00:00 2001 From: bsd Date: Thu, 14 Feb 2002 02:48:07 +0000 Subject: [PATCH] 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/avrdude@123 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avr.c | 146 ++++++++++++++++++++++++++++++++++++++------ avr.h | 8 ++- avrdude.conf.sample | 114 ++++++++++++++++++++++++++++++++++ config_gram.y | 7 +++ lexer.l | 1 + main.c | 2 +- term.c | 18 ++++-- 7 files changed, 273 insertions(+), 23 deletions(-) diff --git a/avr.c b/avr.c index 2c3937e6..2c8d3b58 100644 --- a/avr.c +++ b/avr.c @@ -442,8 +442,9 @@ int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose) } buf[i] = rbyte; if (verbose) { - if ((i % 16 == 0)||(i == (size-1))) - fprintf(stderr, " \r%4lu 0x%02x", i, rbyte); + if ((i % 16 == 0)||(i == (size-1))) { + 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); if (rc != 0) { if (rc != -1) { - return -1; + return -2; } /* * 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; ready = 0; while (!ready) { - usleep(mem->min_write_delay); /* typical write delay */ + usleep(mem->min_write_delay); rc = avr_read_byte(fd, p, mem, addr, &r); 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]) || (data == mem->readback[1])) { /* @@ -619,24 +623,62 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, usleep(mem->max_write_delay); rc = avr_read_byte(fd, p, mem, addr, &r); 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) { 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++; if (!ready && tries > 5) { /* - * we couldn't write the data, indicate our displeasure by - * returning an error code + * we wrote the data, but after waiting for what should have + * 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_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; ibuf[i]; if (verbose) { - if ((i % 16 == 0)||(i == (wsize-1))) - fprintf(stderr, " \r%4lu 0x%02x ", i, data); + if ((i % 16 == 0)||(i == (wsize-1))) { + fprintf(stderr, "\r \r%6lu", i); + } } rc = avr_write_byte(fd, p, m, i, data); if (rc) { @@ -953,7 +996,7 @@ int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size) for (i=0; i"; 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 ""; break; + } +} + + + +void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type, + int verbose) +{ + int i, j; + char * optr; + if (m == NULL) { fprintf(f, "%s Page Polled\n" @@ -976,6 +1056,13 @@ void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type) prefix, prefix, prefix); } 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, "%s%-11s %-6s %6d %4d %5d %5d %5d 0x%02x 0x%02x\n", prefix, m->desc, @@ -987,12 +1074,35 @@ void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type) m->max_write_delay, m->readback[0], 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; iop[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; char * buf; @@ -1020,10 +1130,12 @@ void avr_display(FILE * f, AVRPART * p, char * prefix) 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)) { m = ldata(ln); - avr_mem_display(px, f, m, i); + avr_mem_display(px, f, m, i, verbose); } if (buf) diff --git a/avr.h b/avr.h index 831ea3c7..fd2e8890 100644 --- a/avr.h +++ b/avr.h @@ -87,6 +87,10 @@ typedef struct avrmem { int num_pages; /* number of pages (if page addressed) */ int min_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 * buf; /* pointer to memory buffer */ 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); -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 diff --git a/avrdude.conf.sample b/avrdude.conf.sample index 8ae562f4..a7391eb5 100644 --- a/avrdude.conf.sample +++ b/avrdude.conf.sample @@ -209,6 +209,82 @@ part 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"; ; + 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", "x x x x x x x x x x x x x x x x"; + + pwroff_after_write = 1; ; memory "lock" size = 1; @@ -411,6 +489,8 @@ part 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"; + + pwroff_after_write = 1; ; memory "lock" size = 1; @@ -478,6 +558,26 @@ part 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"; ; + 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", "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"; + ; ; diff --git a/config_gram.y b/config_gram.y index 73e95a2c..e5afc493 100644 --- a/config_gram.y +++ b/config_gram.y @@ -60,6 +60,7 @@ %token K_NUM_PAGES %token K_PART %token K_PGMLED +%token K_PWROFF_AFTER_WRITE %token K_PROGRAMMER %token K_RDYLED %token K_READBACK_P1 @@ -398,6 +399,12 @@ mem_spec : 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 { current_mem->readback[0] = $3->value.number; diff --git a/lexer.l b/lexer.l index c70920ee..6d81fbb5 100644 --- a/lexer.l +++ b/lexer.l @@ -142,6 +142,7 @@ page_size { yylval=NULL; return K_PAGE_SIZE; } paged { yylval=NULL; return K_PAGED; } part { yylval=NULL; return K_PART; } pgmled { yylval=NULL; return K_PGMLED; } +pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; } programmer { yylval=NULL; return K_PROGRAMMER; } rdyled { yylval=NULL; return K_RDYLED; } readback_p1 { yylval=NULL; return K_READBACK_P1; } diff --git a/main.c b/main.c index 55e843ff..32d81b2a 100644 --- a/main.c +++ b/main.c @@ -764,7 +764,7 @@ int main(int argc, char * argv []) v = avr_dup_part(p); if (verbose) { - avr_display(stderr, p, progbuf); + avr_display(stderr, p, progbuf, verbose); fprintf(stderr, "\n"); pinconfig_display(progbuf); } diff --git a/term.c b/term.c index 0f8939f1..a43a58a8 100644 --- a/term.c +++ b/term.c @@ -303,7 +303,8 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) int len, maxsize; char * memtype; unsigned long addr, i; - char * buf; + unsigned char * buf; + unsigned char b; int rc; int werror; 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]); if (rc) { - fprintf(stderr, "%s (write): error writing 0x%02x at 0x%05lx\n", - progname, buf[i], addr+i); + fprintf(stderr, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n", + progname, buf[i], addr+i, rc); if (rc == -1) fprintf(stderr, "write operation not supported on memory type \"%s\"\n", mem->desc); 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) { 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[]) { fprintf(stdout, "\n"); - avr_display(stdout, p, ""); + avr_display(stdout, p, "", 0); fprintf(stdout, "\n"); return 0;