diff --git a/avr.c b/avr.c index cad0443e..40e3b1f3 100644 --- a/avr.c +++ b/avr.c @@ -49,75 +49,6 @@ extern PROGRAMMER * pgm; char * avr_version = "$Id$"; -/* Need to add information for 2323, 2343, and 4414 */ - -#if 0 -struct avrpart parts[] = { - {"AT90S1200", "1200", 20000, - {{0, 64, 0, 0, 9000, 20000, {0x00, 0xff }, NULL}, /* eeprom */ - {0, 1024, 0, 0, 9000, 20000, {0xff, 0 }, NULL}}}, /* flash */ - - {"AT90S2313", "2313", 20000, - {{0, 128, 0, 0, 9000, 20000, {0x80, 0x7f }, NULL}, /* eeprom */ - {0, 2048, 0, 0, 9000, 20000, {0x7f, 0 }, NULL}}}, /* flash */ - - {"AT90S2333", "2333", 20000, - {{0, 128, 0, 0, 9000, 20000, {0x00, 0xff }, NULL}, /* eeprom */ - {0, 2048, 0, 0, 9000, 20000, {0xff, 0 }, NULL}}}, /* flash */ - - {"AT90S4433", "4433", 20000, - {{0, 256, 0, 0, 9000, 20000, {0x00, 0xff }, NULL}, /* eeprom */ - {0, 4096, 0, 0, 9000, 20000, {0xff, 0 }, NULL}}}, /* flash */ - - {"AT90S4434", "4434", 20000, - {{0, 256, 0, 0, 9000, 20000, {0x00, 0xff }, NULL}, /* eeprom */ - {0, 4096, 0, 0, 9000, 20000, {0xff, 0 }, NULL}}}, /* flash */ - - {"AT90S8515", "8515", 20000, - {{0, 512, 0, 0, 9000, 20000, {0x80, 0x7f }, NULL}, /* eeprom */ - {0, 8192, 0, 0, 9000, 20000, {0x7f, 0x00 }, NULL}}}, /* flash */ - - {"AT90S8535", "8535", 20000, - {{0, 512, 0, 0, 9000, 20000, {0x00, 0xff }, NULL}, /* eeprom */ - {0, 8192, 0, 0, 9000, 20000, {0xff, 0x00 }, NULL}}}, /* flash */ - - {"ATMEGA103", "103", 56000*2, - {{0, 4096, 0, 0, 64000, 69000, {0x80, 0x7f }, NULL}, /* eeprom */ - {1, 131072, 256, 512, 22000, 56000, {0xff, 0x00 }, NULL}}}, /* flash */ - -}; - -#define N_AVRPARTS (sizeof(parts)/sizeof(struct avrpart)) - - -int avr_list_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; -} - - -struct avrpart * avr_find_part(char * p) -{ - int i; - - for (i=0; i<N_AVRPARTS; i++) { - if (strcmp(parts[i].optiontag, p)==0) { - return &parts[i]; - } - } - - return NULL; -} -#endif - - AVRPART * avr_new_part(void) { AVRPART * p; @@ -228,6 +159,133 @@ int avr_cmd(int fd, unsigned char cmd[4], unsigned char res[4]) } +/* + * read a calibration byte + */ +unsigned char avr_read_calibration(int fd, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + + LED_ON(fd, pgm->pinno[PIN_LED_PGM]); + LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + + cmd[0] = 0x38; + cmd[1] = 0x00; /* don't care */ + cmd[2] = 0x00; + cmd[3] = 0x00; /* don't care */ + + avr_cmd(fd, cmd, res); + + LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + + return res[3]; /* calibration byte */ +} + + +/* + * read a fuse byte + */ +unsigned char avr_read_fuse(int fd, AVRPART * p, int high) +{ + unsigned char cmd[4]; + unsigned char res[4]; + static unsigned char cmdbyte1[2] = { 0x50, 0x58 }; + static unsigned char cmdbyte2[2] = { 0x00, 0x08 }; + + LED_ON(fd, pgm->pinno[PIN_LED_PGM]); + LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + + cmd[0] = cmdbyte1[high]; + cmd[1] = cmdbyte2[high]; + cmd[2] = 0; /* don't care */ + cmd[3] = 0; /* don't care */ + + avr_cmd(fd, cmd, res); + + LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + + return res[3]; /* fuse bits */ +} + + +/* + * write a fuse byte + */ +int avr_write_fuse(int fd, AVRPART * p, int high, unsigned char b) +{ + unsigned char cmd[4]; + unsigned char res[4]; + static unsigned char cmdbyte[2] = { 0xa0, 0xa8 }; + + LED_ON(fd, pgm->pinno[PIN_LED_PGM]); + LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + + cmd[0] = 0xac; + cmd[1] = cmdbyte[high]; + cmd[2] = 0x00; /* don't care */ + cmd[3] = b; /* fuse bits */ + + avr_cmd(fd, cmd, res); + + usleep(2000); + + LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + + return 0; +} + + +/* + * read a lock byte + */ +unsigned char avr_read_lock(int fd, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + + LED_ON(fd, pgm->pinno[PIN_LED_PGM]); + LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + + cmd[0] = 0x58; + cmd[1] = 0x00; + cmd[2] = 0; + cmd[3] = 0; /* don't care */ + + avr_cmd(fd, cmd, res); + + LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + + return res[3]; /* lock bits */ +} + + +/* + * write a lock byte + */ +int avr_write_lock(int fd, AVRPART * p, unsigned char b) +{ + unsigned char cmd[4]; + unsigned char res[4]; + + LED_ON(fd, pgm->pinno[PIN_LED_PGM]); + LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + + cmd[0] = 0x5c; + cmd[1] = 0xe0; + cmd[2] = 0; /* don't care */ + cmd[3] = b; /* lock bits */ + + avr_cmd(fd, cmd, res); + + usleep(2000); + + LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + + return 0; +} + + /* * read a byte of data from the indicated memory region */ @@ -265,19 +323,20 @@ unsigned char avr_read_byte(int fd, AVRPART * p, /* * Read the entirety of the specified memory type into the - * corresponding buffer of the avrpart pointed to by 'p'. + * corresponding buffer of the avrpart pointed to by 'p'. If size = + * 0, read the entire contents, otherwize, read 'size' bytes. * - * Return the number of bytes read, or -1 if an error occurs. - */ -int avr_read(int fd, AVRPART * p, int memtype) + * Return the number of bytes read, or -1 if an error occurs. */ +int avr_read(int fd, AVRPART * p, int memtype, int size) { unsigned char rbyte; unsigned long i; unsigned char * buf; - int size; buf = p->mem[memtype].buf; - size = p->mem[memtype].size; + if (size == 0) { + size = p->mem[memtype].size; + } for (i=0; i<size; i++) { rbyte = avr_read_byte(fd, p, memtype, i); @@ -292,6 +351,9 @@ int avr_read(int fd, AVRPART * p, int memtype) } + + + /* * write a byte of data to the indicated memory region */ @@ -643,6 +705,8 @@ char * avr_memtstr(int memtype) switch (memtype) { case AVR_M_EEPROM : return "eeprom"; break; case AVR_M_FLASH : return "flash"; break; + case AVR_M_FUSE : return "fuse-bit"; break; + case AVR_M_LOCK : return "fock-bit"; break; default : return "unknown-memtype"; break; } } diff --git a/avr.h b/avr.h index 3444e2ed..0ad6e97c 100644 --- a/avr.h +++ b/avr.h @@ -42,6 +42,8 @@ */ #define AVR_M_EEPROM 0 #define AVR_M_FLASH 1 +#define AVR_M_FUSE 2 +#define AVR_M_LOCK 3 #define AVR_MAXMEMTYPES 2 /* just flash and eeprom */ @@ -86,10 +88,20 @@ unsigned char avr_txrx(int fd, unsigned char byte); int avr_cmd(int fd, unsigned char cmd[4], unsigned char res[4]); +unsigned char avr_read_calibration(int fd, AVRPART * p); + +unsigned char avr_read_fuse(int fd, AVRPART * p, int high); + +int avr_write_fuse(int fd, AVRPART * p, int high, unsigned char b); + +unsigned char avr_read_lock(int fd, AVRPART * p); + +int avr_write_lock(int fd, AVRPART * p, unsigned char b); + unsigned char avr_read_byte(int fd, AVRPART * p, int memtype, unsigned long addr); -int avr_read(int fd, AVRPART * p, int memtype); +int avr_read(int fd, AVRPART * p, int memtype, int size); int avr_write_bank(int fd, AVRPART * p, int memtype, unsigned short bank); diff --git a/avrdude.conf.sample b/avrdude.conf.sample index ae1697ee..d509e21b 100644 --- a/avrdude.conf.sample +++ b/avrdude.conf.sample @@ -360,6 +360,25 @@ part readback_p1 = 0xff; readback_p2 = 0xff; ; +/* + instructions + instr "pe", "programming enable" [ "1010 1100", "0101 0011", "xxxx xxxx", "xxxx xxxx" ]; + instr "ce", "chip erase" [ "1010 1100", "100x xxxx", "xxxx xxxx", "xxxx xxxx" ]; + instr "rpm", "read program memory" [ "0010 H000", "xxxa aaaa", "bbbb bbbb", "oooo oooo" ]; + instr "lpmp" "load program memory page" [ "0100 H000", "xxxx xxxx", "xxbb bbbb", "iiii iiii" ]; + instr "wpmp", "write program memory page" [ "0100 1100", "xxxa aaaa", "bbxx xxxx", "xxxx xxxx" ]; + instr "rep", "read eeprom memory" [ "1010 0000", "xxxx xxxa", "bbbb bbbb", "oooo oooo" ]; + instr "wep", "write eeprom memory" [ "1100 0000", "xxxx xxxa", "bbbb bbbb", "iiii iiii" ]; + instr "rlb", "read lock bits" [ "0101 1000", "0000 0000", "xxxx 0xxx", "xxoo oooo" ]; + instr "wlb", "write lock bits" [ "1010 1100", "111x xxxx", "xxxx xxxx", "11ii iiii" ]; + instr "rsb", "read signature byte" [ "0011 0000", "xxxx xxxx", "xxxx xxbb", "oooo oooo" ]; + instr "wfb", "write fuse bits" [ "1010 1100", "1010 0000", "xxxx xxxx", "ii11 iiii" ]; + instr "wfhb", "write fuse high bits" [ "1010 1100", "1010 1000", "xxxx xxxx", "1111 1iii" ]; + instr "rfb", "read fuse bits" [ "0101 0000", "0000 0000", "xxxx xxxx", "ooxx oooo" ]; + instr "rfhb", "read fuse high bits" [ "0101 1000", "0000 1000", "xxxx xxxx", "xxxx 1ooo" ]; + instr "rcb", "read calibration byte" [ "0011 1000", "xxxx xxxx", "0000 0000", "oooo oooo" ]; + ; +*/ ; part diff --git a/main.c b/main.c index 93fc053a..070e10ae 100644 --- a/main.c +++ b/main.c @@ -893,7 +893,7 @@ int main(int argc, char * argv []) */ fprintf(stderr, "%s: reading %s memory:\n", progname, avr_memtstr(memtype)); - rc = avr_read(fd, p, memtype); + rc = avr_read(fd, p, memtype, 0); if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", progname, avr_memtstr(memtype), rc); @@ -969,7 +969,7 @@ int main(int argc, char * argv []) progname, avr_memtstr(memtype), inputf); fprintf(stderr, "%s: reading on-chip %s data:\n", progname, avr_memtstr(memtype)); - rc = avr_read(fd, v, memtype); + rc = avr_read(fd, v, memtype, vsize); if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", progname, avr_memtstr(memtype), rc); diff --git a/ppi.c b/ppi.c index 01c7a1da..562fcace 100644 --- a/ppi.c +++ b/ppi.c @@ -35,6 +35,8 @@ #include "ppi.h" +#define SLOW_TOGGLE 0 + extern char * progname; struct ppipins_t { @@ -224,8 +226,17 @@ int ppi_setall(int fd, int reg, int val) int ppi_pulse(int fd, int reg, int bit) { ppi_toggle(fd, reg, bit); + +#if SLOW_TOGGLE + usleep(1000); +#endif + ppi_toggle(fd, reg, bit); +#if SLOW_TOGGLE + usleep(1000); +#endif + return 0; } @@ -246,6 +257,10 @@ int ppi_setpin(int fd, int pin, int value) else ppi_clr(fd, pins[pin].reg, pins[pin].bit); +#if SLOW_TOGGLE + usleep(1000); +#endif + return 0; } @@ -280,8 +295,17 @@ int ppi_pulsepin(int fd, int pin) pin--; ppi_toggle(fd, pins[pin].reg, pins[pin].bit); + +#if SLOW_TOGGLE + usleep(1000); +#endif + ppi_toggle(fd, pins[pin].reg, pins[pin].bit); +#if SLOW_TOGGLE + usleep(1000); +#endif + return 0; } diff --git a/term.c b/term.c index fb9ac93f..814034f9 100644 --- a/term.c +++ b/term.c @@ -64,12 +64,16 @@ int cmd_erase (int fd, struct avrpart * p, int argc, char *argv[]); int cmd_sig (int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_cal (int fd, struct avrpart * p, int argc, char *argv[]); + int cmd_part (int fd, struct avrpart * p, int argc, char *argv[]); int cmd_help (int fd, struct avrpart * p, int argc, char *argv[]); int cmd_quit (int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_send (int fd, struct avrpart * p, int argc, char *argv[]); + struct command cmd[] = { { "dump", cmd_dump, "dump memory : %s [eeprom|flash] <addr> <N-Bytes>" }, @@ -77,7 +81,9 @@ struct command cmd[] = { { "write", cmd_write, "write memory : %s [eeprom|flash] <addr> <b1> <b2> ... <bN>" }, { "erase", cmd_erase, "perform a chip erase" }, { "sig", cmd_sig, "display device signature bytes" }, + { "cal", cmd_cal, "display device calibration byte" }, { "part", cmd_part, "display the current part settings" }, + { "send", cmd_send, "send a command : %s <b1> <b2> <b3> <b4>" }, { "help", cmd_help, "help" }, { "?", cmd_help, "help" }, { "quit", cmd_quit, "quit" } @@ -215,7 +221,7 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) } else { if (!((argc == 2) || (argc == 4))) { - fprintf(stderr, "Usage: dump flash|eeprom [<addr> <len>]\n"); + fprintf(stderr, "Usage: dump flash|eeprom|fuse|lock [<addr> <len>]\n"); return -1; } @@ -226,6 +232,14 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) else if (strncasecmp(argv[1],"eeprom",l)==0) { memtype = AVR_M_EEPROM; } + else if ((strncasecmp(argv[1],"fuse",l)==0)|| + (strncasecmp(argv[1],"fuse-bit",l)==0)) { + memtype = AVR_M_FUSE; + } + else if ((strncasecmp(argv[1],"lock",l)==0)|| + (strncasecmp(argv[1],"lock-bit",l)==0)) { + memtype = AVR_M_LOCK; + } else { fprintf(stderr, "%s (dump): invalid memory type \"%s\"\n", progname, argv[1]); @@ -249,7 +263,20 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) } } - maxsize = p->mem[memtype].size; + maxsize = 0; + + switch (memtype) { + case AVR_M_FLASH: + case AVR_M_EEPROM: + maxsize = p->mem[memtype].size; + break; + case AVR_M_FUSE: + maxsize = 2; + break; + case AVR_M_LOCK: + maxsize = 1; + break; + } if (argc == 2) { addr = 0; @@ -273,8 +300,20 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) return -1; } - for (i=0; i<len; i++) - buf[i] = avr_read_byte(fd, p, memtype, addr+i); + for (i=0; i<len; i++) { + switch (memtype) { + case AVR_M_FLASH: + case AVR_M_EEPROM: + buf[i] = avr_read_byte(fd, p, memtype, addr+i); + break; + case AVR_M_FUSE: + buf[i] = avr_read_fuse(fd, p, addr+i); + break; + case AVR_M_LOCK: + buf[i] = avr_read_lock(fd, p); + break; + } + } hexdump_buf(stdout, addr, buf, len); @@ -298,8 +337,8 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) int werror; if (argc < 4) { - fprintf(stderr, - "Usage: write flash|eeprom <addr> <byte1> <byte2> ... byteN>\n"); + fprintf(stderr, "Usage: write flash|eeprom|fuse <addr> <byte1> " + "<byte2> ... byteN>\n"); return -1; } @@ -310,19 +349,39 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) else if (strncasecmp(argv[1],"eeprom",l)==0) { memtype = AVR_M_EEPROM; } + else if ((strncasecmp(argv[1],"fuse",l)==0)|| + (strncasecmp(argv[1],"fuse-bit",l)==0)) { + memtype = AVR_M_FUSE; + } + else if ((strncasecmp(argv[1],"lock",l)==0)|| + (strncasecmp(argv[1],"lock-bit",l)==0)) { + memtype = AVR_M_LOCK; + } else { fprintf(stderr, "%s (write): invalid memory type \"%s\"\n", progname, argv[1]); return -1; } - if (p->mem[memtype].paged) { - fprintf(stderr, "%s (write): sorry, interactive write of page addressed " - "memory is not supported\n", progname); - return -1; - } + maxsize = 0; - maxsize = p->mem[memtype].size; + switch (memtype) { + case AVR_M_FLASH: + case AVR_M_EEPROM: + if (p->mem[memtype].paged) { + fprintf(stderr, "%s (write): sorry, interactive write of page " + "addressed memory is not supported\n", progname); + return -1; + } + maxsize = p->mem[memtype].size; + break; + case AVR_M_FUSE: + maxsize = 2; + break; + case AVR_M_LOCK: + maxsize = 1; + break; + } addr = strtoul(argv[2], &e, 0); if (*e || (e == argv[2])) { @@ -360,13 +419,28 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) if (*e || (e == argv[i])) { fprintf(stderr, "%s (write): can't parse byte \"%s\"\n", progname, argv[i]); + free(buf); return -1; } } LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); for (werror=0, i=0; i<len; i++) { - rc = avr_write_byte(fd, p, memtype, addr+i, buf[i]); + + rc = 0; + switch (memtype) { + case AVR_M_EEPROM: + case AVR_M_FLASH: + rc = avr_write_byte(fd, p, memtype, addr+i, buf[i]); + break; + case AVR_M_FUSE: + rc = avr_write_fuse(fd, p, addr+i, buf[i]); + break; + case AVR_M_LOCK: + rc = avr_write_lock(fd, p, buf[i]); + break; + } + if (rc) { fprintf(stderr, "%s (write): error writing 0x%02x at 0x%04x\n", progname, buf[i], addr+i); @@ -385,6 +459,49 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) } +int cmd_send(int fd, struct avrpart * p, int argc, char * argv[]) +{ + unsigned char cmd[4], res[4]; + char * e; + int i; + int len; + + if (argc != 5) { + fprintf(stderr, "Usage: send <byte1> <byte2> <byte3> <byte4>\n"); + return -1; + } + + /* number of bytes to write at the specified address */ + len = argc - 1; + + /* load command bytes */ + for (i=1; i<argc; i++) { + cmd[i-1] = strtoul(argv[i], &e, 0); + if (*e || (e == argv[i])) { + fprintf(stderr, "%s (send): can't parse byte \"%s\"\n", + progname, argv[i]); + return -1; + } + } + + LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + + avr_cmd(fd, cmd, res); + + /* + * display results + */ + fprintf(stderr, "results:"); + for (i=0; i<len; i++) + fprintf(stderr, " %02x", res[i]); + fprintf(stderr, "\n"); + + fprintf(stdout, "\n"); + + return 0; +} + + int cmd_erase(int fd, struct avrpart * p, int argc, char * argv[]) { fprintf(stderr, "%s: erasing chip\n", progname); @@ -418,6 +535,17 @@ int cmd_sig(int fd, struct avrpart * p, int argc, char * argv[]) } +int cmd_cal(int fd, struct avrpart * p, int argc, char * argv[]) +{ + unsigned char byte; + + byte = avr_read_calibration(fd, p); + fprintf(stdout, "\nDevice calibration = 0x%02x\n\n", byte); + + return 0; +} + + int cmd_quit(int fd, struct avrpart * p, int argc, char * argv[]) { return 1;