diff --git a/avrprog.c b/avrprog.c index d561100a..08e03b8f 100644 --- a/avrprog.c +++ b/avrprog.c @@ -63,8 +63,9 @@ #include <stdarg.h> #include <sys/stat.h> #include </sys/dev/ppbus/ppi.h> +#include <limits.h> -#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; i<N_AVRPARTS; i++) { + fprintf(f, "%s\"%s\" = %s\n", + prefix, parts[i].optiontag, parts[i].partdesc); + } + + return i; +} + + + /* * set 'get' and 'set' appropriately for subsequent passage to ioctl() @@ -323,10 +405,10 @@ unsigned char avr_read_byte ( int fd, AVRMEM memtype, unsigned short addr ) break; case AVR_EEPROM: cmd[0] = 0xa0; - /* addr &= 0x7f; */ break; default: - fprintf(stderr, "%s: avr_read_byte(); internal error: invalid memtype=%d\n", + fprintf(stderr, + "%s: avr_read_byte(); internal error: invalid memtype=%d\n", progname, memtype); exit(1); break; @@ -343,23 +425,31 @@ unsigned char avr_read_byte ( int fd, AVRMEM memtype, unsigned short addr ) /* - * read 'n' words of data from the indicated memory region. If the - * flash memory is being read, n*2 bytes will be read into 'buf'; if - * the eeprom is being read, 'n' bytes will be read into 'buf'. + * read the entirety of the specified memory type into the + * corresponding buffer of the avrpart pointed to by 'p'. */ -int avr_read ( int fd, AVRMEM memtype, unsigned start, unsigned n, - unsigned char * buf, int bufsize ) +int avr_read ( int fd, AVRMEM memtype, struct avrpart * p ) { unsigned char rbyte, memt; - unsigned short end, i, bi; + unsigned short n, start, end, i, bi; + unsigned char * buf; + int bufsize; switch (memtype) { case AVR_FLASH : - memt = AVR_FLASH_LO; + memt = AVR_FLASH_LO; + buf = p->flash; + 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<sizeof(parts)/sizeof(parts[0]); i++) { - fprintf(stderr, " \"%s\" = %s\n", - parts[i].optiontag, parts[i].partdesc); - } + list_valid_parts(stderr, " "); fprintf(stderr, "\n"); } + +int b2ihex ( unsigned char * inbuf, int bufsize, + int recsize, int startaddr, + char * outfile, FILE * outf ) +{ + unsigned char * buf; + unsigned int nextaddr; + int n; + int i; + unsigned char cksum; + + if (recsize > 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<n; i++) { + fprintf ( outf, "%02X", buf[i] ); + cksum += buf[i]; + } + cksum = -cksum; + fprintf ( outf, "%02X\n", cksum ); + + nextaddr += n; + } + + /* advance to next 'recsize' bytes */ + buf += n; + bufsize -= n; + } + + /*----------------------------------------------------------------- + add the trailing zero data line + -----------------------------------------------------------------*/ + cksum = 0; + n = 0; + fprintf ( outf, ":%02X%04X00", n, nextaddr ); + cksum += n + ((nextaddr >> 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; i<n; i++) { + if (sscanf((char *)&buffer[i*2+9], "%02x", &b) != 1) { + fprintf(stderr, "%s: can't scan byte number %d at line %d of %s\n", + progname, i, lineno, infile); + /* display the buffer and the position of the scan error */ + fprintf(stderr, "%s", buffer); + for (j=0; j<9+2*i; j++) { + fprintf(stderr, " "); + } + fprintf(stderr, "^\n"); + return -1; + } + + buf[nextaddr + i] = b; + cksum += b; + } + + /*----------------------------------------------------------------- + read the cksum value from the record and compare it with our + computed value + -----------------------------------------------------------------*/ + if (sscanf((char *)&buffer[n*2+9], "%02x", &b) != 1) { + fprintf(stderr, "%s: can't scan byte number %d at line %d of %s\n", + progname, i, lineno, infile); + /* display the buffer and the position of the scan error */ + fprintf(stderr, "%s", buffer); + for (j=0; j<9+2*i; j++) { + fprintf(stderr, " "); + } + fprintf(stderr, "^\n"); + return -1; + } + + cksum = -cksum & 0xff; + if (cksum != b) { + fprintf(stderr, + "%s: cksum error for line %d of \"%s\": computed=%02x " + "found=%02x\n", + progname, lineno, infile, cksum, b); + return -1; + } + + prevaddr = nextaddr + n; + } + + return 0; +} + + + +int fileio_rbin ( struct fioparms * fio, + char * filename, FILE * f, unsigned char * buf, int size ) +{ + int rc; + + switch (fio->op) { + 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 = "<stdin>"; + f = stdin; + } + else { + fname = "<stdout>"; + 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; i<size; i++) { + buf[i] = 0xff; + } + } + + switch (format) { + case FMT_IHEX: + rc = fileio_ihex(&fio, fname, f, buf, size); + break; + + case FMT_SREC: + rc = fileio_srec(&fio, fname, f, buf, size); + break; + + case FMT_RBIN: + rc = fileio_rbin(&fio, fname, f, buf, size); + break; + + default: + fprintf(stderr, "%s: invalid %s file format: %d\n", + progname, fio.iodesc, format); + return -4; + } + + return rc; +} + + +char * memtypestr ( AVRMEM memtype ) +{ + switch (memtype) { + case AVR_EEPROM : return "eeprom"; break; + case AVR_FLASH : return "flash"; break; + default : return "unknown-memtype"; break; + } +} + + /* * main routine */ int main ( int argc, char * argv [] ) { - int fd; - int rc, exitrc; - int i; - unsigned char * buf; - int ch; - int iofd; - int flash, eeprom, doread, erase, dosig; - int size; - char * outputf; - char * inputf; - char * p1, * p2; - struct avrpart * p; - unsigned char sig[4], nulldev[4]; - int len; - int ovsigck; + int fd; /* file descriptor for parallel port */ + int rc; /* general return code checking */ + int exitrc; /* exit code for main() */ + int i; /* general loop counter */ + int ch; /* options flag */ + int size; /* size of memory region */ + int len; /* length for various strings */ + char buf[PATH_MAX]; /* temporary buffer */ + char * p1; /* used to parse CVS Id */ + char * p2; /* used to parse CVS Ed */ + unsigned char sig[4]; /* AVR signature bytes */ + unsigned char nulldev[4]; /* 0xff signature bytes for comparison */ + struct avrpart * p; /* which avr part we are programming */ + int readorwrite; /* true if a chip read/write op was selected */ - iofd = -1; - outputf = NULL; - inputf = NULL; - doread = 1; - eeprom = 0; - flash = 0; - erase = 0; - dosig = 0; - p = NULL; - ovsigck = 0; + /* options / operating mode variables */ + int memtype; /* AVR_FLASH or AVR_EEPROM */ + int doread; /* 0=reading, 1=writing */ + int erase; /* 1=erase chip, 0=don't */ + char * outputf; /* output file name */ + char * inputf; /* input file name */ + int ovsigck; /* 1=override sig check, 0=don't */ + char * parallel; /* parallel port device */ + int interactive; /* 1=enter interactive command mode, 0=don't */ + int filefmt; /* FMT_AUTO, FMT_IHEX, FMT_SREC, FMT_RBIN */ + + readorwrite = 0; + parallel = DEFAULT_PARALLEL; + outputf = NULL; + inputf = NULL; + doread = 1; + memtype = AVR_FLASH; + erase = 0; + p = NULL; + ovsigck = 0; + interactive = 0; + filefmt = FMT_AUTO; progname = rindex(argv[0],'/'); if (progname) @@ -731,7 +1171,6 @@ int main ( int argc, char * argv [] ) else progname = argv[0]; - /* * Print out an identifying string so folks can tell what version * they are running @@ -767,94 +1206,119 @@ int main ( int argc, char * argv [] ) /* * process command line arguments */ - while ((ch = getopt(argc,argv,"?efFo:p:rsu:")) != -1) { + while ((ch = getopt(argc,argv,"?cef:Fi:m:o:p:P:s")) != -1) { + switch (ch) { - case 'e': /* select eeprom memory */ - if (flash) { - fprintf(stderr,"%s: -e and -f are incompatible\n", progname); - return 1; + case 'm': /* select memory type to operate on */ + if ((strcasecmp(optarg,"e")==0)||(strcasecmp(optarg,"eeprom")==0)) { + memtype = AVR_EEPROM; } - eeprom = 1; - break; - case 'f': /* select flash memory */ - if (eeprom) { - fprintf(stderr,"%s: -e and -f are incompatible\n", progname); - return 1; + else if ((strcasecmp(optarg,"f")==0)|| + (strcasecmp(optarg,"flash")==0)) { + memtype = AVR_FLASH; } - flash = 1; + else { + fprintf(stderr, "%s: invalid memory type \"%s\"\n", + progname, optarg); + usage(); + exit(1); + } + readorwrite = 1; break; + case 'F': /* override invalid signature check */ ovsigck = 1; break; + case 'o': /* specify output file */ if (inputf) { - fprintf(stderr,"%s: -o and -u are incompatible\n", progname); + fprintf(stderr,"%s: -i and -o are incompatible\n", progname); return 1; } doread = 1; outputf = optarg; - if (strcmp(outputf,"-")==0) { - iofd = fileno(stdout); - } - else { - iofd = open ( outputf, O_WRONLY|O_CREAT|O_TRUNC, - S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); - if (iofd < 0) { - fprintf(stderr, "%s: can't open output file \"%s\": %s\n", - progname, outputf, strerror(errno)); - return 1; - } - } + if (filefmt == FMT_AUTO) + filefmt = FMT_IHEX; break; + case 'p' : /* specify AVR part */ p = NULL; - for (i=0; i<sizeof(parts)/sizeof(parts[0]); i++) { + for (i=0; i<N_AVRPARTS; i++) { if (strcmp(parts[i].optiontag, optarg)==0) { p = &parts[i]; break; } } if (p == NULL) { - fprintf(stderr, "%s: AVR Part \"%s\" not found. Valid parts are:\n\n", + fprintf(stderr, + "%s: AVR Part \"%s\" not found. Valid parts are:\n\n", progname, optarg ); - for (i=0; i<sizeof(parts)/sizeof(parts[0]); i++) { - fprintf(stderr, " \"%s\" = %s\n", - parts[i].optiontag, parts[i].partdesc); - } + list_valid_parts(stderr," "); fprintf(stderr, "\n"); return 1; } break; - case 'r': /* perform a chip erase */ + + case 'e': /* perform a chip erase */ erase = 1; break; - case 's': /* read out the signature bytes */ - dosig = 1; - break; - case 'u': /* specify input (upload) file */ + + case 'i': /* specify input file */ if (outputf) { - fprintf(stderr,"%s: -o and -u are incompatible\n", progname); + fprintf(stderr,"%s: -o and -i are incompatible\n", progname); return 1; } doread = 0; inputf = optarg; - iofd = open ( inputf, O_RDONLY, 0); - if (iofd < 0) { - fprintf(stderr, "%s: can't open input file \"%s\": %s\n", - progname, inputf, strerror(errno)); - return 1; + break; + + case 'f': /* specify file format */ + if (strlen(optarg) != 1) { + fprintf(stderr, "%s: invalid file format \"%s\"\n", + progname, optarg); + usage(); + exit(1); + } + switch (optarg[0]) { + case 'a' : filefmt = FMT_AUTO; break; + case 'i' : filefmt = FMT_IHEX; break; + case 'r' : filefmt = FMT_RBIN; break; + case 's' : + fprintf(stderr, "%s: Motorola S-Record format not yet supported\n", + progname); + exit(1); + break; + default : + fprintf(stderr, "%s: invalid file format \"%s\"\n", + progname, optarg); + usage(); + exit(1); } break; + + case 'c': /* enter interactive command mode */ + if (!((inputf == NULL)||(outputf == NULL))) { + fprintf(stderr, + "%s: interactive mode is not compatible with -i or -o\n", + progname); + usage(); + exit(1); + } + interactive = 1; + break; + case '?': /* help */ usage(); - return 1; + exit(0); break; + default: fprintf(stderr, "%s: invalid option -%c\n", progname, ch); usage(); - return 1; + exit(1); break; } + } if (p == NULL) { @@ -862,10 +1326,7 @@ int main ( int argc, char * argv [] ) "%s: No AVR part has been specified, use \"-p Part\"\n\n" " Valid Parts are:\n\n", progname ); - for (i=0; i<sizeof(parts)/sizeof(parts[0]); i++) { - fprintf(stderr, " \"%s\" = %s\n", - parts[i].optiontag, parts[i].partdesc); - } + list_valid_parts(stderr, " "); fprintf(stderr,"\n"); return 1; } @@ -874,27 +1335,27 @@ int main ( int argc, char * argv [] ) progname, p->partdesc, 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>", stdout); + else + b2ihex ( p->eeprom, p->eeprom_size, 32, 0, "<stdout>", 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" );