From d407508c90212e48329c298e0a5cd4499ab1742f Mon Sep 17 00:00:00 2001 From: "Brian S. Dean" Date: Sat, 13 Jan 2001 20:00:17 +0000 Subject: [PATCH] A lot of general code cleanup. Re-work command line options to be more intuitive. Support Intel Hex input and output file formats. Provide hooks to support Motorola S-Record as well. Add a few more part-specific parameters to the avrpart structure. Only write the flash or eeprom if the data to be written is not 0xff. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@20 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avrprog.c | 861 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 629 insertions(+), 232 deletions(-) diff --git a/avrprog.c b/avrprog.c index d561100a..08e03b8f 100644 --- a/avrprog.c +++ b/avrprog.c @@ -63,8 +63,9 @@ #include #include #include +#include -#define PARALLEL "/dev/ppi0" +#define DEFAULT_PARALLEL "/dev/ppi0" char * version = "$Id$"; @@ -101,21 +102,102 @@ typedef enum { AVR_FLASH_HI } AVRMEM; +enum { + FMT_AUTO, + FMT_SREC, + FMT_IHEX, + FMT_RBIN +}; struct avrpart { - char * partdesc; + char * partdesc; char * optiontag; int flash_size; int eeprom_size; + unsigned char f_readback; + unsigned char e_readback[2]; + unsigned char * flash; + unsigned char * eeprom; }; struct avrpart parts[] = { - { "AT90S8515", "8515", 8192, 512 }, - { "AT90S2313", "2313", 2048, 128 }, - { "AT90S1200", "1200", 1024, 64 } + { "AT90S8515", "8515", 8192, 512, 0x7f, { 0x80, 0x7f }, NULL, NULL }, + { "AT90S2313", "2313", 2048, 128, 0x7f, { 0x80, 0x7f }, NULL, NULL }, + { "AT90S1200", "1200", 1024, 64, 0x7f, { 0x80, 0x7f }, NULL, NULL } }; +#define N_AVRPARTS (sizeof(parts)/sizeof(struct avrpart)) + + +struct fioparms { + int op; + char * mode; + char * iodesc; + char * dir; + char * rw; +}; + +enum { + FIO_READ, + FIO_WRITE +}; + + + +#define MAX_LINE_LEN 256 /* max line length for ASCII format input files */ + + +char * usage_text = +"\n" +"Usage: avrprog [options]\n" +"\n" +" Available Options:\n" +"\n" +" -m MemType : select memory type for reading or writing\n" +" \"e\", \"eeprom\" = EEPROM\n" +" \"f\", \"flash\" = FLASH\n" +"\n" +" -i Filename : select input file\n" +"\n" +" -o Filename : select output file, \"-\" = stdout\n" +"\n" +" -f Format : select input / output file format\n" +" \"i\" = Intel Hex\n" +" \"s\" = Motorola S-Record\n" +" \"r\" = Raw binary\n" +" \"a\" = Auto detect (valid input only)\n" +"\n" +" -p Part : select Atmel part number (see below for valid parts)\n" +"\n" +" -P Parallel : select parallel port device name (default = /dev/ppi0)\n" +"\n" +" -s : read device signature bytes\n" +"\n" +" -F : override invalid device signature check\n" +"\n" +" -c : enter interactive command mode (or read commands\n" +" from stdin)\n" +"\n" +" -e : perform a chip erase (required before programming)\n" +"\n"; + + + +int list_valid_parts ( FILE * f, char * prefix ) +{ + int i; + + for (i=0; iflash; + n = p->flash_size/2; + bufsize = p->flash_size; break; + case AVR_EEPROM : - memt = memtype; + memt = memtype; + buf = p->eeprom; + n = p->eeprom_size; + bufsize = p->eeprom_size; break; + default: fprintf(stderr, "%s: avr_read(); internal error: invalid memtype=%d\n", progname, memtype); @@ -398,7 +488,8 @@ int avr_read ( int fd, AVRMEM memtype, unsigned start, unsigned n, /* * write a byte of data to the indicated memory region */ -int avr_write_byte ( int fd, AVRMEM memtype, unsigned short addr, unsigned char data ) +int avr_write_byte ( int fd, AVRMEM memtype, + unsigned short addr, unsigned char data ) { unsigned char cmd[4], res[4]; unsigned char r; @@ -414,10 +505,10 @@ int avr_write_byte ( int fd, AVRMEM memtype, unsigned short addr, unsigned char break; case AVR_EEPROM: cmd[0] = 0xc0; - /* addr &= 0x7f; */ break; default: - fprintf(stderr, "%s: avr_write_byte(); internal error: invalid memtype=%d\n", + fprintf(stderr, + "%s: avr_write_byte(); internal error: invalid memtype=%d\n", progname, memtype); exit(1); break; @@ -457,24 +548,35 @@ int avr_write_byte ( int fd, AVRMEM memtype, unsigned short addr, unsigned char /* - * write 'bufsize' bytes of data to the indicated memory region. + * Write the whole memory region (flash or eeprom, specified by + * 'memtype') from the corresponding buffer of the avrpart pointed to + * by 'p'. All of the memory is updated, however, input data of 0xff + * is not actually written out, because empty flash and eeprom + * contains 0xff, and you can't actually write 1's, only 0's. */ -int avr_write ( int fd, AVRMEM memtype, unsigned start, - unsigned char * buf, int bufsize ) +int avr_write ( int fd, AVRMEM memtype, struct avrpart * p ) { unsigned char data, memt; - unsigned short end, i, bi; + unsigned short start, end, i, bi; int nl; int rc; + unsigned char * buf; + int bufsize; + + start = 0; switch (memtype) { case AVR_FLASH : - end = start+bufsize/2; - memt = AVR_FLASH_LO; + buf = p->flash; + bufsize = p->flash_size; + end = start+bufsize/2; + memt = AVR_FLASH_LO; break; case AVR_EEPROM : - end = start+bufsize; - memt = memtype; + buf = p->eeprom; + bufsize = p->eeprom_size; + end = start+bufsize; + memt = memtype; break; default: fprintf(stderr, "%s: avr_write(); internal error: invalid memtype=%d\n", @@ -489,7 +591,10 @@ int avr_write ( int fd, AVRMEM memtype, unsigned start, /* eeprom or low byte of flash */ data = buf[bi++]; nl = 0; - rc = avr_write_byte(fd, memt, i, data ); + if (data != 0xff) + rc = avr_write_byte(fd, memt, i, data ); + else + rc = 0; fprintf(stderr, " \r%4u 0x%02x", i, data); if (rc) { fprintf(stderr, " ***failed; "); @@ -499,7 +604,10 @@ int avr_write ( int fd, AVRMEM memtype, unsigned start, if (memtype == AVR_FLASH) { /* high byte of flash */ data = buf[bi++]; - rc = avr_write_byte(fd, AVR_FLASH_HI, i, data ); + if (data != 0xff) + rc = avr_write_byte(fd, AVR_FLASH_HI, i, data ); + else + rc = 0; fprintf(stderr, " 0x%02x", data); if (rc) { fprintf(stderr, " ***failed; " ); @@ -666,64 +774,396 @@ int ppi_sense_test ( int fd ) */ void usage ( void ) { - int i; - fprintf ( stderr, - "\nUsage: %s [options]\n" - "\n" - " Available Options:\n" - " -r : erase the flash and eeprom (required before programming)\n" - " -e : select eeprom for reading or writing\n" - " -f : select flash for reading or writing\n" - " -p Part : see below for valid parts\n" - " -u InputFile : write data from this file\n" - " -o OutputFile : write data to this file\n" - " -F : override invalid device signature check\n" - " -s : read device signature bytes\n" - "\n", - progname ); + fprintf ( stderr, "%s", usage_text ); fprintf(stderr, " Valid Parts for the -p option are:\n"); - for (i=0; i 255) { + fprintf ( stderr, "%s: recsize=%d, must be < 256\n", + progname, recsize ); + return -1; + } + + nextaddr = startaddr; + + buf = inbuf; + while (bufsize) { + n = recsize; + if (n > bufsize) + n = bufsize; + + if (n) { + cksum = 0; + fprintf ( outf, ":%02X%04X00", n, nextaddr ); + cksum += n + ((nextaddr >> 8) & 0x0ff) + (nextaddr & 0x0ff); + for (i=0; i> 8) & 0x0ff) + (nextaddr & 0x0ff); + cksum = -cksum; + fprintf ( outf, "%02X\n", cksum ); + + return 0; +} + + +int ihex2b ( char * infile, FILE * inf, + unsigned char * outbuf, int bufsize ) +{ + unsigned char buffer [ MAX_LINE_LEN ]; + unsigned char * buf; + unsigned int prevaddr, nextaddr; + unsigned int b; + int n; + int i, j; + unsigned int cksum, rectype; + int lineno; + + lineno = 0; + prevaddr = 0; + buf = outbuf; + + while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) { + lineno++; + if (buffer[0] != ':') + continue; + if (sscanf((char *)&buffer[1], + "%02x%04x%02x", &n, &nextaddr, &rectype) != 3) { + fprintf(stderr, "%s: invalid record at line %d of \"%s\"\n", + progname, lineno, infile); + exit(1); + } + + if (rectype != 0) { + fprintf(stderr, + "%s: don't know how to deal with rectype=%d " + "at line %d of \"%s\"\n", + progname, rectype, lineno, infile); + exit(1); + } + + if (n && ((nextaddr + n) > bufsize)) { + fprintf(stderr, "%s: address 0x%04x out of range at line %d of %s\n", + progname, nextaddr+n, lineno, infile); + return -1; + } + + /* start computing a checksum */ + cksum = n + ((nextaddr >> 8 ) & 0x0ff) + (nextaddr & 0x0ff); + + for (i=0; iop) { + case FIO_READ: + rc = fread(buf, 1, size, f); + break; + case FIO_WRITE: + rc = fwrite(buf, 1, size, f); + break; + } + + if (rc < size) { + fprintf(stderr, + "%s: %s error %s %s: %s; %s %d of the expected %d bytes\n", + progname, fio->iodesc, fio->dir, filename, strerror(errno), + fio->rw, rc, size); + return -5; + } + + return rc; +} + + +int fileio_ihex ( struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size ) +{ + int rc; + + switch (fio->op) { + case FIO_WRITE: + rc = b2ihex(buf, size, 32, 0, filename, f); + if (rc) { + return -5; + } + break; + + case FIO_READ: + rc = ihex2b(filename, f, buf, size); + if (rc) + return -5; + break; + + default: + fprintf(stderr, "%s: invalid Intex Hex file I/O operation=%d\n", + progname, fio->op); + return -5; + break; + } + + return 0; +} + + +int fileio_srec ( struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size ) +{ + fprintf(stderr, "%s: Motorola S-Record %s format not yet supported\n", + progname, fio->iodesc); + return -5; +} + + +int fileio_setparms ( int op, struct fioparms * fp ) +{ + fp->op = op; + + switch (op) { + case FIO_READ: + fp->mode = "r"; + fp->iodesc = "input"; + fp->dir = "from"; + fp->rw = "read"; + break; + + case FIO_WRITE: + fp->mode = "w"; + fp->iodesc = "output"; + fp->dir = "to"; + fp->rw = "wrote"; + break; + + default: + fprintf(stderr, "%s: invalid I/O operation %d\n", + progname, op); + return -1; + break; + } + + return 0; +} + + +int fileio ( int op, char * filename, int format, + struct avrpart * p, AVRMEM memtype ) +{ + int rc; + FILE * f; + char * fname; + unsigned char * buf; + int size; + struct fioparms fio; + int i; + + rc = fileio_setparms(op, &fio); + if (rc < 0) + return -1; + + if (strcmp(filename, "-")==0) { + if (fio.op == FIO_READ) { + fname = ""; + f = stdin; + } + else { + fname = ""; + f = stdout; + } + } + else { + f = fopen(filename, fio.mode); + if (f == NULL) { + fprintf(stderr, "%s: can't open %s file %s: %s\n", + progname, fio.iodesc, filename, strerror(errno)); + return -2; + } + } + + switch (memtype) { + case AVR_EEPROM: + buf = p->eeprom; + size = p->eeprom_size; + break; + + case AVR_FLASH: + buf = p->flash; + size = p->flash_size; + break; + + default: + fprintf(stderr, "%s: invalid memory type for %s: %d\n", + progname, fio.iodesc, memtype); + return -3; + } + + if (fio.op == FIO_READ) { + /* 0xff fill unspecified memory */ + for (i=0; ipartdesc, p->flash_size, p->eeprom_size); fprintf(stderr, "\n"); - if (p->flash_size >= p->eeprom_size) - size = p->flash_size; - else - size = p->eeprom_size; - - buf = (unsigned char *) malloc(size); - if (buf == NULL) { - fprintf(stderr, - "%s: out of memory allocating %d bytes for on-chip memory buffer\n", - progname, size); - return 1; + p->flash = (unsigned char *) malloc(p->flash_size); + if (p->flash == NULL) { + fprintf(stderr, "%s: can't alloc buffer for flash size of %d bytes\n", + progname, p->flash_size); + exit(1); } + p->eeprom = (unsigned char *) malloc(p->eeprom_size); + if (p->eeprom == NULL) { + fprintf(stderr, "%s: can't alloc buffer for eeprom size of %d bytes\n", + progname, p->eeprom_size); + exit(1); + } /* * open the parallel port */ - fd = open ( PARALLEL, O_RDWR ); + fd = open ( DEFAULT_PARALLEL, O_RDWR ); if (fd < 0) { fprintf ( stderr, "%s: can't open device \"%s\": %s\n", - progname, PARALLEL, strerror(errno) ); + progname, DEFAULT_PARALLEL, strerror(errno) ); return 1; } @@ -911,7 +1372,8 @@ int main ( int argc, char * argv [] ) goto main_exit; } - fprintf ( stderr, "%s: AVR device initialized and ready to accept instructions\n", + fprintf ( stderr, + "%s: AVR device initialized and ready to accept instructions\n", progname ); /* @@ -957,44 +1419,18 @@ int main ( int argc, char * argv [] ) } - if (dosig) { - /* - * read out the on-chip signature bytes - */ - fprintf(stderr, "%s: reading signature bytes: ", progname ); - avr_signature(fd, sig); - for (i=0; i<4; i++) - fprintf(stderr, "%02x", sig[i]); - fprintf(stderr, "\n"); - } - - - if (iofd < 0) { + if ((inputf==NULL) && (outputf==NULL)) { /* * Check here to see if any other operations were selected and * generate an error message because if they were, we need either * an input or and output file, but one was not selected. * Otherwise, we just shut down. */ - if (eeprom||flash) { + if (readorwrite) { fprintf(stderr, "%s: you must specify an input or an output file\n", progname); exitrc = 1; } - usage(); - goto main_exit; - } - - - if (!(eeprom||flash)) { - /* - * an input file or an output file was specified, but the memory - * type (eeprom or flash) was not specified. - */ - fprintf(stderr, - "%s: please specify either the eeprom (-e) or the flash (-f) memory\n", - progname); - exitrc = 1; goto main_exit; } @@ -1003,93 +1439,55 @@ int main ( int argc, char * argv [] ) /* * read out the specified device memory and write it to a file */ - if (flash) { - size = p->flash_size; - fprintf ( stderr, "%s: reading flash memory:\n", progname ); - rc = avr_read ( fd, AVR_FLASH, 0, size/2, buf, size ); - if (rc) { - fprintf ( stderr, "%s: failed to read all of flash memory, rc=%d\n", - progname, rc ); - exitrc = 1; - goto main_exit; - } - } - else if (eeprom) { - size = p->eeprom_size; - fprintf ( stderr, "%s: reading eeprom memory:\n", progname ); - rc = avr_read ( fd, AVR_EEPROM, 0, size, buf, size ); - if (rc) { - fprintf ( stderr, "%s: failed to read all of eeprom memory, rc=%d\n", - progname, rc ); - exitrc = 1; - goto main_exit; - } + fprintf ( stderr, "%s: reading %s memory:\n", + progname, memtypestr(memtype) ); + rc = avr_read ( fd, memtype, p ); + if (rc) { + fprintf ( stderr, "%s: failed to read all of %s memory, rc=%d\n", + progname, memtypestr(memtype), rc ); + exitrc = 1; + goto main_exit; } - /* - * write it out to the specified file - */ - rc = write ( iofd, buf, size ); + rc = fileio(FIO_WRITE, outputf, filefmt, p, memtype); if (rc < 0) { - fprintf(stderr, "%s: write error: %s\n", progname, strerror(errno)); - exitrc = 1; - goto main_exit; - } - else if (rc != size) { - fprintf(stderr, "%s: wrote only %d bytes of the expected %d\n", - progname, rc, size); + fprintf(stderr, "%s: terminating\n", progname); exitrc = 1; goto main_exit; } + } else { /* - * write the selected device memory using data from a file + * write the selected device memory using data from a file; first + * read the data from the specified file */ - if (flash) { - size = p->flash_size; - } - else if (eeprom) { - size = p->eeprom_size; - } - - /* - * read in the data file that will be used to write into the chip - */ - rc = read(iofd, buf, size); + rc = fileio(FIO_READ, inputf, filefmt, p, memtype ); if (rc < 0) { - fprintf(stderr, "%s: read error from \"%s\": %s\n", - progname, inputf, strerror(errno)); + fprintf(stderr, "%s: terminating\n", progname); exitrc = 1; goto main_exit; } - size = rc; /* * write the buffer contents to the selected memory type */ - if (flash) { - fprintf(stderr, "%s: writing %d bytes into flash memory:\n", - progname, size); - rc = avr_write ( fd, AVR_FLASH, 0, buf, size ); - if (rc) { - fprintf ( stderr, "%s: failed to write flash memory, rc=%d\n", - progname, rc ); - exitrc = 1; - goto main_exit; - } - } - else if (eeprom) { - fprintf(stderr, "%s: writing %d bytes into eeprom memory:\n", - progname, size); - rc = avr_write ( fd, AVR_EEPROM, 0, buf, size ); - if (rc) { - fprintf ( stderr, "%s: failed to write eeprom memory, rc=%d\n", - progname, rc ); - exitrc = 1; - goto main_exit; - } + fprintf(stderr, "%s: writing %s:\n", + progname, memtypestr(memtype)); +#if 1 + rc = avr_write ( fd, memtype, p ); +#else + if (memtype == AVR_FLASH) + b2ihex ( p->flash, p->flash_size, 32, 0, "", stdout); + else + b2ihex ( p->eeprom, p->eeprom_size, 32, 0, "", stdout); +#endif + if (rc) { + fprintf ( stderr, "%s: failed to write flash memory, rc=%d\n", + progname, rc ); + exitrc = 1; + goto main_exit; } } @@ -1104,7 +1502,6 @@ int main ( int argc, char * argv [] ) ppi_clr(fd, PPIDATA, AVR_RESET); close(fd); - close(iofd); fprintf(stderr, "\n" );