From f1af5d3981aeaf8e4c4d542ad4859300b49f6b6d Mon Sep 17 00:00:00 2001 From: "Brian S. Dean" Date: Mon, 19 Nov 2001 17:44:24 +0000 Subject: [PATCH] Add support for ATMega163. Add support for reading/writing ATMega163 lock and fuse bits. Unfortunately, in looking at the specs for other ATMega parts, they use entirely different instruction formats for these commands. Thus, these routines won't work for the ATMega103, for example. Add support for sending raw command bytes via the interactive terminal interface. This allows one to execute any programming instruction on the target device, whether or not avrprog supports it explicitly or not. Thus, one can use this feature to program fuse / lock bits, or access any other feature of a current or future device that avrprog does not know how to do. Add in comments, an experimental instruction format in the configuration file. If this works out, it would allow supporting new parts and non-orthoganal instructions across existing parts without making avrprog code changes. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@99 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avr.c | 214 ++++++++++++++++++++++++++++---------------- avr.h | 14 ++- avrdude.conf.sample | 19 ++++ main.c | 4 +- ppi.c | 24 +++++ term.c | 154 ++++++++++++++++++++++++++++--- 6 files changed, 338 insertions(+), 91 deletions(-) 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; ipinno[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 " }, @@ -77,7 +81,9 @@ struct command cmd[] = { { "write", cmd_write, "write memory : %s [eeprom|flash] ... " }, { "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 " }, { "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 [ ]\n"); + fprintf(stderr, "Usage: dump flash|eeprom|fuse|lock [ ]\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 ... byteN>\n"); + fprintf(stderr, "Usage: write flash|eeprom|fuse " + " ... 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 \n"); + return -1; + } + + /* number of bytes to write at the specified address */ + len = argc - 1; + + /* load command bytes */ + for (i=1; ipinno[PIN_LED_ERR]); + + avr_cmd(fd, cmd, res); + + /* + * display results + */ + fprintf(stderr, "results:"); + for (i=0; i