diff --git a/avrdude/Makefile b/avrdude/Makefile index fabd1ac1..76ba5b20 100644 --- a/avrdude/Makefile +++ b/avrdude/Makefile @@ -4,6 +4,8 @@ TARGET = avrprog +DEST = ${HOME}/bin/0.${ARCH} + all : ${TARGET} CFLAGS = -Wall @@ -14,3 +16,8 @@ ${TARGET} : avrprog.c clean : rm -f *.o ${TARGET} *~ +install : ${DEST}/${TARGET} + +${DEST}/${TARGET} : ${TARGET} + cp -p ${TARGET} $@ + diff --git a/avrdude/avrprog.c b/avrdude/avrprog.c index 9cd3cf2a..da13a96a 100644 --- a/avrdude/avrprog.c +++ b/avrdude/avrprog.c @@ -1,19 +1,46 @@ /* - * Copyright 2000, Brian Dean + * Copyright 2000 Brian S. Dean <bsd@bsdhome.com> * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BRIAN S. DEAN ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRIAN S. DEAN BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * */ /* $Id$ */ /* - * Code to program an Atmel AVR device using the parallel port. + * Code to program an Atmel AVR AT90S device using the parallel port. * * Make the following connections: * - * Pin 2 -> PB7(SCK) CLOCK IN (data bit 0) - * Pin 3 -> PB5(MOSI) Instruction input (data bit 1) - * Pin 4 -> /RESET (data bit 2) - * Pin 10 <- PB6(MISO) Data out (status bit 6) + * Parallel Port Atmel AVR + * ------------- ---------------------------- + * Pin 2 -> Vcc + * Pin 3 -> PB7(SCK) CLOCK IN + * Pin 4 -> PB5(MOSI) Instruction input + * Pin 5 -> /RESET + * Pin 10 <- PB6(MISO) Data out * */ @@ -33,9 +60,10 @@ char * progname; -#define AVR_CLOCK 0x01 /* bit 0 of data register */ -#define AVR_INSTR 0x02 /* bit 1 of data register */ -#define AVR_RESET 0x04 /* bit 2 of data register */ +#define AVR_POWER 0x01 /* bit 0 of data register */ +#define AVR_CLOCK 0x02 /* bit 1 of data register */ +#define AVR_INSTR 0x04 /* bit 2 of data register */ +#define AVR_RESET 0x08 /* bit 3 of data register */ #define AVR_DATA 0x40 /* bit 6 of status register */ @@ -54,23 +82,6 @@ enum { }; -int dprintf ( FILE * f, char * format, ... ) -{ -#if DEBUG - va_list ap; - int rc; - - va_start(ap,format); - rc = vfprintf(f,format,ap); - va_end(ap); - - return rc; -#else - return 0; -#endif -} - - int ppi_getops ( int reg, unsigned long * get, unsigned long * set ) { switch (reg) { @@ -207,19 +218,32 @@ unsigned char avr_txrx ( int fd, unsigned char byte ) } -unsigned char avr_read_byte ( int fd, unsigned short addr, int memtype ) +int avr_cmd ( int fd, unsigned char * cmd, unsigned char * res ) { - unsigned char r; + int i; + + for (i=0; i<4; i++) { + res[i] = avr_txrx(fd, cmd[i]); + } + + return 0; +} + + +unsigned char avr_read_byte ( int fd, int memtype, unsigned short addr ) +{ + unsigned char cmd[4]; + unsigned char res[4]; switch (memtype) { case AVR_FLASH_LO: - avr_txrx(fd, 0x20); + cmd[0] = 0x20; break; case AVR_FLASH_HI: - avr_txrx(fd, 0x28); + cmd[0] = 0x28; break; case AVR_EEPROM: - avr_txrx(fd, 0xa0); + cmd[0] = 0xa0; addr &= 0x7f; break; default: @@ -229,24 +253,28 @@ unsigned char avr_read_byte ( int fd, unsigned short addr, int memtype ) break; } - avr_txrx(fd, addr >> 8); /* high order bits of address */ - avr_txrx(fd, addr & 0x0ff); /* low order bits of address */ - r = avr_txrx(fd, 0); /* don't care */ + cmd[1] = addr >> 8; /* high order bits of address */ + cmd[2] = addr & 0x0ff; /* low order bits of address */ + cmd[3] = 0; /* don't care */ - return r; + avr_cmd(fd, cmd, res); + + return res[3]; } int avr_read ( int fd, int memtype, unsigned start, unsigned n, unsigned char * buf, int bufsize ) { - unsigned char rbyte; - unsigned short data; + unsigned char rbyte, memt; unsigned short end, i, bi; switch (memtype) { - case AVR_FLASH : + case AVR_FLASH : + memt = AVR_FLASH_LO; + break; case AVR_EEPROM : + memt = memtype; break; default: fprintf(stderr, "%s: avr_read(); internal error: invalid memtype=%d\n", @@ -260,29 +288,21 @@ int avr_read ( int fd, int memtype, unsigned start, unsigned n, bi = 0; for (i=start; i<end; i++) { + /* eeprom or low byte of flash */ + rbyte = avr_read_byte(fd, memt, i); + fprintf ( stderr, " \r%4u 0x%02x", i, rbyte ); + if (bi < bufsize) { + buf[bi++] = rbyte; + } + if (memtype == AVR_FLASH) { - rbyte = avr_read_byte(fd, i, AVR_FLASH_LO); /* flash low byte */ - fprintf ( stderr, " \r%4u 0x%02x", i, rbyte ); - data = rbyte; - if (bi < bufsize) { - buf[bi++] = rbyte; - } - - rbyte = avr_read_byte(fd, i, AVR_FLASH_HI); /* flash high byte */ + /* flash high byte */ + rbyte = avr_read_byte(fd, AVR_FLASH_HI, i); fprintf ( stderr, " 0x%02x", rbyte ); - data |= (rbyte << 8); if (bi < bufsize) { buf[bi++] = rbyte; } } - else { - rbyte = avr_read_byte(fd, i, memtype); /* eeprom byte */ - fprintf ( stderr, " \r%4u 0x%02x", i, rbyte ); - if (bi < bufsize) { - buf[bi++] = rbyte; - } - } - } fprintf ( stderr, "\n" ); @@ -293,19 +313,20 @@ int avr_read ( int fd, int memtype, unsigned start, unsigned n, int avr_write_byte ( int fd, int memtype, unsigned short addr, unsigned char data ) { + unsigned char cmd[4], res[4]; unsigned char r; int ready; int tries; switch (memtype) { case AVR_FLASH_LO: - avr_txrx(fd, 0x40); + cmd[0] = 0x40; break; case AVR_FLASH_HI: - avr_txrx(fd, 0x48); + cmd[0] = 0x48; break; case AVR_EEPROM: - avr_txrx(fd, 0xc0); + cmd[0] = 0xc0; addr &= 0x7f; break; default: @@ -315,26 +336,32 @@ int avr_write_byte ( int fd, int memtype, unsigned short addr, unsigned char dat break; } - avr_txrx(fd, addr >> 8); /* high order bits of address */ - avr_txrx(fd, addr & 0x0ff); /* low order bits of address */ - avr_txrx(fd, data); /* data */ + cmd[1] = addr >> 8; /* high order bits of address */ + cmd[2] = addr & 0x0ff; /* low order bits of address */ + cmd[3] = data; /* data */ + + avr_cmd(fd, cmd, res); tries = 0; ready = 0; while (!ready) { usleep(5000); /* flash write delay */ - r = avr_read_byte ( fd, addr, memtype ); + r = avr_read_byte(fd, memtype, addr); if (data == 0x7f) { - usleep(20000); + usleep(20000); /* long delay for 0x7f since polling doesn't work */ ready = 1; } else if (r == data) { ready = 1; } + tries++; if (!ready && tries > 10) { - fprintf(stderr, "**" ); - ready = 1; + /* + * we couldn't write the data, indicate our displeasure by + * returning an error code + */ + return -1; } } @@ -343,17 +370,21 @@ int avr_write_byte ( int fd, int memtype, unsigned short addr, unsigned char dat int avr_write ( int fd, int memtype, unsigned start, - unsigned char * buf, int size ) + unsigned char * buf, int bufsize ) { - unsigned char data; + unsigned char data, memt; unsigned short end, i, bi; + int nl; + int rc; switch (memtype) { case AVR_FLASH : - end = start+size/2; + end = start+bufsize/2; + memt = AVR_FLASH_LO; break; case AVR_EEPROM : - end = start+size; + end = start+bufsize; + memt = memtype; break; default: fprintf(stderr, "%s: avr_write(); internal error: invalid memtype=%d\n", @@ -365,23 +396,28 @@ int avr_write ( int fd, int memtype, unsigned start, bi = 0; for (i=start; i<end; i++) { + /* eeprom or low byte of flash */ + data = buf[bi++]; + nl = 0; + rc = avr_write_byte(fd, memt, i, data ); + fprintf(stderr, " \r%4u 0x%02x", i, data); + if (rc) { + fprintf(stderr, " ***failed; "); + nl = 1; + } + if (memtype == AVR_FLASH) { - /* low byte */ + /* high byte of flash */ data = buf[bi++]; - avr_write_byte(fd, AVR_FLASH_LO, i, data ); - fprintf ( stderr, " \r%4u 0x%02x", i, data ); - - /* high byte */ - data = buf[bi++]; - avr_write_byte(fd, AVR_FLASH_HI, i, data ); - fprintf ( stderr, " 0x%02x", data ); + rc = avr_write_byte(fd, AVR_FLASH_HI, i, data ); + fprintf(stderr, " 0x%02x", data); + if (rc) { + fprintf(stderr, " ***failed; " ); + nl = 1; + } } - else { - data = buf[bi++]; - avr_write_byte(fd, memtype, i, data ); - fprintf ( stderr, " \r%4u 0x%02x", i, data ); - } - + if (nl) + fprintf(stderr, "\n"); } fprintf ( stderr, "\n" ); @@ -392,23 +428,12 @@ int avr_write ( int fd, int memtype, unsigned start, int avr_program_enable ( int fd ) { - unsigned char data[4] = {0xac, 0x53, 0x00, 0x00}; - unsigned char byte, rbyte; - int avrok; - int i; + unsigned char cmd[4] = {0xac, 0x53, 0x00, 0x00}; + unsigned char res[4]; - avrok = 0; + avr_cmd(fd, cmd, res); - for (i=0; i<4; i++) { - byte = data[i]; - rbyte = avr_txrx ( fd, byte ); - if (i == 2) { - if (rbyte == data[1]) - avrok = 1; - } - } - - if (!avrok) + if (res[2] != cmd[1]) return -1; return 0; @@ -418,11 +443,9 @@ int avr_program_enable ( int fd ) int avr_chip_erase ( int fd ) { unsigned char data[4] = {0xac, 0x80, 0x00, 0x00}; - int i; + unsigned char res[4]; - for (i=0; i<4; i++) { - avr_txrx ( fd, data[i] ); - } + avr_cmd(fd, data, res); usleep(20000); @@ -430,11 +453,42 @@ int avr_chip_erase ( int fd ) } +int avr_signature ( int fd, char sig[4] ) +{ + unsigned char cmd[4] = {0x30, 0x00, 0x00, 0x00}; + unsigned char res[4]; + int i; + + for (i=0; i<4; i++) { + cmd[2] = i; + avr_cmd(fd, cmd, res); + sig[i] = res[3]; + } + + return 0; +} + + +void avr_powerup ( int fd ) +{ + ppi_set(fd, PPIDATA, AVR_POWER); /* power up */ + usleep(100000); +} + + +void avr_powerdown ( int fd ) +{ + ppi_clr(fd, PPIDATA, AVR_POWER); /* power down */ +} + + int avr_initialize ( int fd ) { int rc; int tries; + avr_powerup(fd); + ppi_clr(fd, PPIDATA, AVR_CLOCK); ppi_clr(fd, PPIDATA, AVR_RESET); ppi_toggle(fd, PPIDATA, AVR_RESET); @@ -504,9 +558,10 @@ int main ( int argc, char * argv [] ) int fd; int rc; unsigned char buf[2048]; + unsigned char sig[4]; int ch; int iofd; - int flash, eeprom, doread, erase; + int flash, eeprom, doread, erase, dosig; int size; char * outputf; char * inputf; @@ -518,6 +573,7 @@ int main ( int argc, char * argv [] ) eeprom = 0; flash = 0; erase = 0; + dosig = 0; progname = rindex(argv[0],'/'); if (progname) @@ -530,7 +586,7 @@ int main ( int argc, char * argv [] ) return 0; } - while ((ch = getopt(argc,argv,"?efo:ru:")) != -1) { + while ((ch = getopt(argc,argv,"?efo:rsu:")) != -1) { switch (ch) { case 'e': if (flash) { @@ -542,6 +598,9 @@ int main ( int argc, char * argv [] ) case 'r': erase = 1; break; + case 's': + dosig = 1; + break; case 'f': if (eeprom) { fprintf(stderr,"%s: -e and -f are incompatible\n", progname); @@ -606,6 +665,7 @@ int main ( int argc, char * argv [] ) rc = avr_initialize(fd); if (rc < 0) { fprintf ( stderr, "%s: initialization failed, rc=%d\n", progname, rc ); + avr_powerdown(fd); return 1; } @@ -619,9 +679,22 @@ int main ( int argc, char * argv [] ) fprintf(stderr, "%s: done.\n", progname ); } + if (dosig) { + int i; + fprintf(stderr, "%s: reading signature bytes: ", progname ); + avr_signature(fd, sig); + for (i=0; i<4; i++) + fprintf(stderr, "0x%02x ", sig[i]); + fprintf(stderr, "\n"); + } + if (iofd < 0) { - fprintf(stderr, "%s: you must specify an input or an output file\n", - progname); + if (eeprom||flash) { + fprintf(stderr, "%s: you must specify an input or an output file\n", + progname); + } + avr_powerdown(fd); + close(fd); return 1; } @@ -629,6 +702,7 @@ int main ( int argc, char * argv [] ) fprintf(stderr, "%s: please specify either the eeprom (-e) or the flash (-f) memory\n", progname); + avr_powerdown(fd); return 1; } @@ -643,6 +717,7 @@ int main ( int argc, char * argv [] ) if (rc) { fprintf ( stderr, "%s: failed to read all of flash memory, rc=%d\n", progname, rc ); + avr_powerdown(fd); return 1; } } @@ -653,6 +728,7 @@ int main ( int argc, char * argv [] ) if (rc) { fprintf ( stderr, "%s: failed to read all of eeprom memory, rc=%d\n", progname, rc ); + avr_powerdown(fd); return 1; } } @@ -660,11 +736,13 @@ int main ( int argc, char * argv [] ) rc = write ( iofd, buf, size ); if (rc < 0) { fprintf(stderr, "%s: write error: %s\n", progname, strerror(errno)); + avr_powerdown(fd); return 1; } else if (rc != size) { fprintf(stderr, "%s: wrote only %d bytes of the expected %d\n", progname, rc, size); + avr_powerdown(fd); return 1; } } @@ -684,34 +762,38 @@ int main ( int argc, char * argv [] ) if (rc < 0) { fprintf(stderr, "%s: read error from \"%s\": %s\n", progname, inputf, strerror(errno)); - return 1; - } - else if (rc != size) { - fprintf(stderr, "%s: read only %d bytes of the expected %d from \"%s\"\n", - progname, rc, size, inputf); + avr_powerdown(fd); return 1; } + size = rc; + if (flash) { - fprintf ( stderr, "%s: writing flash memory:\n", progname ); + 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 ); + avr_powerdown(fd); return 1; } } else if (eeprom) { - fprintf ( stderr, "%s: writing eeprom memory:\n", progname ); + 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 ); + avr_powerdown(fd); return 1; } } } + avr_powerdown(fd); + close(fd); close(iofd);