diff --git a/Makefile b/Makefile index c19bf8d9..0dd87e7e 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,9 @@ install : dirs \ ${CONFIGDIR}/avrprog.conf.sample \ ${CONFIGDIR}/avrprog.conf +config_gram.o : avr.h config.h lists.h pindefs.h + + dirs : @for dir in ${DIRS}; do \ if [ ! -d $$dir ]; then \ diff --git a/avr.c b/avr.c index 40e3b1f3..54bf9e5f 100644 --- a/avr.c +++ b/avr.c @@ -37,6 +37,7 @@ #include "avr.h" #include "config.h" +#include "lists.h" #include "pindefs.h" #include "ppi.h" @@ -64,33 +65,82 @@ AVRPART * avr_new_part(void) p->id[0] = 0; p->desc[0] = 0; + p->mem = lcreat(NULL, 0); + return p; } -AVRPART * avr_dup_part(AVRPART * d) +OPCODE * avr_new_opcode(void) { - AVRPART * p; - int i; + OPCODE * m; - p = (AVRPART *)malloc(sizeof(AVRPART)); - if (p == NULL) { - fprintf(stderr, "avr_dup_part(): out of memory\n"); + m = (OPCODE *)malloc(sizeof(*m)); + if (m == NULL) { + fprintf(stderr, "avr_new_opcode(): out of memory\n"); exit(1); } + memset(m, 0, sizeof(*m)); + + return m; +} + + + +AVRMEM * avr_new_memtype(void) +{ + AVRMEM * m; + + m = (AVRMEM *)malloc(sizeof(*m)); + if (m == NULL) { + fprintf(stderr, "avr_new_memtype(): out of memory\n"); + exit(1); + } + + memset(m, 0, sizeof(*m)); + + return m; +} + + +AVRMEM * avr_dup_mem(AVRMEM * m) +{ + AVRMEM * n; + + n = avr_new_memtype(); + + *n = *m; + + n->buf = (unsigned char *)malloc(n->size); + if (n->buf == NULL) { + fprintf(stderr, + "avr_dup_mem(): out of memory (memsize=%d)\n", + n->size); + exit(1); + } + memset(n->buf, 0, n->size); + + return n; +} + + +AVRPART * avr_dup_part(AVRPART * d) +{ + AVRPART * p; + LISTID save; + LNODEID ln; + + p = avr_new_part(); + save = p->mem; + *p = *d; - for (i=0; imem[i].buf = (unsigned char *)malloc(p->mem[i].size); - if (p->mem[i].buf == NULL) { - fprintf(stderr, - "avr_dup_part(): out of memory (memsize=%d)\n", - p->mem[i].size); - exit(1); - } - memset(p->mem[i].buf, 0, p->mem[i].size); + p->mem = save; + + for (ln=lfirst(d->mem); ln; ln=lnext(ln)) { + ladd(p->mem, avr_dup_mem(ldata(ln))); } return p; @@ -98,6 +148,32 @@ AVRPART * avr_dup_part(AVRPART * d) +AVRMEM * avr_locate_mem(AVRPART * p, char * desc) +{ + AVRMEM * m, * match; + LNODEID ln; + int matches; + int l; + + l = strlen(desc); + matches = 0; + match = NULL; + for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { + m = ldata(ln); + if (strncmp(desc, m->desc, l) == 0) { + match = m; + matches++; + } + } + + if (matches == 1) + return match; + + return NULL; +} + + + /* * transmit and receive a bit of data to/from the AVR device */ @@ -155,132 +231,106 @@ int avr_cmd(int fd, unsigned char cmd[4], unsigned char res[4]) res[i] = avr_txrx(fd, cmd[i]); } - return 0; -} - - -/* - * 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]); +#if 0 + fprintf(stderr, "avr_cmd(): [ "); + for (i=0; i<4; i++) + fprintf(stderr, "%02x ", cmd[i]); + fprintf(stderr, "] [ "); + for (i=0; i<4; i++) + fprintf(stderr, "%02x ", res[i]); + fprintf(stderr, "]\n"); +#endif return 0; } -/* - * read a lock byte - */ -unsigned char avr_read_lock(int fd, AVRPART * p) +int avr_set_bits(OPCODE * op, unsigned char * cmd) { - unsigned char cmd[4]; - unsigned char res[4]; + int i, j, bit; + unsigned char mask; - LED_ON(fd, pgm->pinno[PIN_LED_PGM]); - LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + for (i=0; i<32; i++) { + if (op->bit[i].type == AVR_CMDBIT_VALUE) { + j = 3 - i / 8; + bit = i % 8; + mask = 1 << bit; + if (op->bit[i].value) + cmd[j] = cmd[j] | mask; + else + cmd[j] = cmd[j] & ~mask; + } + } - 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 */ + return 0; } -/* - * write a lock byte - */ -int avr_write_lock(int fd, AVRPART * p, unsigned char b) +int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr) { - unsigned char cmd[4]; - unsigned char res[4]; + int i, j, bit; + unsigned long value; + unsigned char mask; - LED_ON(fd, pgm->pinno[PIN_LED_PGM]); - LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + for (i=0; i<32; i++) { + if (op->bit[i].type == AVR_CMDBIT_ADDRESS) { + j = 3 - i / 8; + bit = i % 8; + mask = 1 << bit; + value = addr >> op->bit[i].bitno & 0x01; + if (value) + cmd[j] = cmd[j] | mask; + else + cmd[j] = cmd[j] & ~mask; + } + } - cmd[0] = 0x5c; - cmd[1] = 0xe0; - cmd[2] = 0; /* don't care */ - cmd[3] = b; /* lock bits */ + return 0; +} - avr_cmd(fd, cmd, res); - usleep(2000); +int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data) +{ + int i, j, bit; + unsigned char value; + unsigned char mask; - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + for (i=0; i<32; i++) { + if (op->bit[i].type == AVR_CMDBIT_INPUT) { + j = 3 - i / 8; + bit = i % 8; + mask = 1 << bit; + value = data >> op->bit[i].bitno & 0x01; + if (value) + cmd[j] = cmd[j] | mask; + else + cmd[j] = cmd[j] & ~mask; + } + } + + return 0; +} + + +int avr_get_output(OPCODE * op, unsigned char * cmd, unsigned char * data) +{ + int i, j, bit; + unsigned char value; + unsigned char mask; + + for (i=0; i<32; i++) { + if (op->bit[i].type == AVR_CMDBIT_OUTPUT) { + j = 3 - i / 8; + bit = i % 8; + mask = 1 << bit; + value = ((cmd[j] & mask) >> bit) & 0x01; + value = value << op->bit[i].bitno; + if (value) + *data = *data | value; + else + *data = *data & ~value; + } + } return 0; } @@ -289,60 +339,89 @@ int avr_write_lock(int fd, AVRPART * p, unsigned char b) /* * read a byte of data from the indicated memory region */ -unsigned char avr_read_byte(int fd, AVRPART * p, - int memtype, unsigned long addr) +int avr_read_byte(int fd, AVRPART * p, AVRMEM * mem, unsigned long addr, + unsigned char * value) { - unsigned short offset; unsigned char cmd[4]; unsigned char res[4]; - /* order here is very important, AVR_EEPROM, AVR_FLASH, AVR_FLASH+1 */ - static unsigned char cmdbyte[3] = { 0xa0, 0x20, 0x28 }; + unsigned char data; + OPCODE * readop; LED_ON(fd, pgm->pinno[PIN_LED_PGM]); LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); - offset = 0; - - if (memtype == AVR_M_FLASH) { - offset = addr & 0x01; - addr = addr / 2; + if (mem->op[AVR_OP_READ_LO]) { + if (addr & 0x00000001) + readop = mem->op[AVR_OP_READ_HI]; + else + readop = mem->op[AVR_OP_READ_LO]; + addr = addr / 2; + } + else { + readop = mem->op[AVR_OP_READ]; } - cmd[0] = cmdbyte[memtype + offset]; - cmd[1] = addr >> 8; /* high order bits of address */ - cmd[2] = addr & 0x0ff; /* low order bits of address */ - cmd[3] = 0; /* don't care */ + if (readop == NULL) { + fprintf(stderr, + "avr_read_byte(): operation not supported on memory type \"%s\"\n", + p->desc); + return -1; + } + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(readop, cmd); + avr_set_addr(readop, cmd, addr); avr_cmd(fd, cmd, res); + data = 0; + avr_get_output(readop, res, &data); LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); - return res[3]; + *value = data; + + return 0; } /* * Read the entirety of the specified memory type into the * corresponding buffer of the avrpart pointed to by 'p'. If size = - * 0, read the entire contents, otherwize, read 'size' bytes. + * 0, read the entire contents, otherwise, read 'size' bytes. * - * Return the number of bytes read, or -1 if an error occurs. */ -int avr_read(int fd, AVRPART * p, int memtype, int size) + * Return the number of bytes read, or -1 if an error occurs. + */ +int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose) { unsigned char rbyte; unsigned long i; unsigned char * buf; + AVRMEM * mem; + int rc; - buf = p->mem[memtype].buf; + mem = avr_locate_mem(p, memtype); + if (mem == NULL) { + fprintf(stderr, "No \"%s\" memory for part %s\n", + memtype, p->desc); + return -1; + } + + buf = mem->buf; if (size == 0) { - size = p->mem[memtype].size; + size = mem->size; } for (i=0; iop[AVR_OP_WRITEPAGE]; + if (wp == NULL) { + fprintf(stderr, + "avr_write_page(): memory \"%s\" not configured for page writes\n", + mem->desc); + return -1; + } + + if (mem->op[AVR_OP_LOADPAGE_LO]) + addr = addr / 2; LED_ON(fd, pgm->pinno[PIN_LED_PGM]); LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); - /* - * 'page' indicates which page is being programmed: 0 for the first - * page_size block, 1 for the second, up to num_pages-1 for the - * last. The MCU actually wants the high-order bits of what would - * be the actual address instead, shifted left to the upper most - * bits of a 16 bit word. For a 128K flash, the actual address is a - * 17 bits. To get the right value to send to the MCU, we want to - * shift 'page' left by 16 - the number of bits in the page - * address. - */ - page = page << p->mem[memtype].pageaddr_shift; - - cmd[0] = 0x4c; - cmd[1] = page >> 8; /* high order bits of address */ - cmd[2] = page & 0x0ff; /* low order bits of address */ - cmd[3] = 0; /* these bits are ignored */ + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(wp, cmd); + avr_set_addr(wp, cmd, addr); avr_cmd(fd, cmd, res); /* * since we don't know what voltage the target AVR is powered by, be * conservative and delay the max amount the spec says to wait */ - usleep(p->mem[memtype].max_write_delay); + usleep(mem->max_write_delay); LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); return 0; @@ -399,7 +477,7 @@ int avr_write_page(int fd, AVRPART * p, int memtype, /* * write a byte of data to the indicated memory region */ -int avr_write_byte(int fd, AVRPART * p, int memtype, +int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, unsigned long addr, unsigned char data) { unsigned char cmd[4]; @@ -408,45 +486,67 @@ int avr_write_byte(int fd, AVRPART * p, int memtype, int ready; int tries; unsigned char b; - unsigned short offset; unsigned short caddr; - /* order here is very important, AVR_M_EEPROM, AVR_M_FLASH, AVR_M_FLASH+1 */ - static unsigned char cmdbyte[3] = { 0xc0, 0x40, 0x48 }; + OPCODE * writeop; + int rc; - if (!p->mem[memtype].paged) { + if (!mem->paged) { /* * check to see if the write is necessary by reading the existing * value and only write if we are changing the value; we can't * use this optimization for paged addressing. */ - b = avr_read_byte(fd, p, memtype, addr); + rc = avr_read_byte(fd, p, mem, addr, &b); + if (rc != 0) + return -1; + if (b == data) { return 0; } } - else { - addr = addr % p->mem[memtype].page_size; + + /* + * determine which memory opcode to use + */ + if (mem->op[AVR_OP_WRITE_LO]) { + if (addr & 0x01) + writeop = mem->op[AVR_OP_WRITE_HI]; + else + writeop = mem->op[AVR_OP_WRITE_LO]; + caddr = addr / 2; } + else if (mem->op[AVR_OP_LOADPAGE_LO]) { + if (addr & 0x01) + writeop = mem->op[AVR_OP_LOADPAGE_HI]; + else + writeop = mem->op[AVR_OP_LOADPAGE_LO]; + caddr = addr / 2; + } + else { + writeop = mem->op[AVR_OP_WRITE]; + caddr = addr; + } + + if (writeop == NULL) { + fprintf(stderr, + "avr_write_byte(): write not support for memory type \"%s\"\n", + mem->desc); + exit(1); + return -1; + } + LED_ON(fd, pgm->pinno[PIN_LED_PGM]); LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); - offset = 0; - - caddr = addr; - if (memtype == AVR_M_FLASH) { - offset = addr & 0x01; - caddr = addr / 2; - } - - cmd[0] = cmdbyte[memtype + offset]; - cmd[1] = caddr >> 8; /* high order bits of address */ - cmd[2] = caddr & 0x0ff; /* low order bits of address */ - cmd[3] = data; /* data */ + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(writeop, cmd); + avr_set_addr(writeop, cmd, caddr); + avr_set_input(writeop, cmd, data); avr_cmd(fd, cmd, res); - if (p->mem[memtype].paged) { + if (mem->paged) { /* * in paged addressing, single bytes to written to the memory * page complete immediately, we only need to delay when we commit @@ -459,18 +559,24 @@ int avr_write_byte(int fd, AVRPART * p, int memtype, tries = 0; ready = 0; while (!ready) { - usleep(p->mem[memtype].min_write_delay); /* typical write delay */ - r = avr_read_byte(fd, p, memtype, addr); - if ((data == p->mem[memtype].readback[0]) || - (data == p->mem[memtype].readback[1])) { + usleep(mem->min_write_delay); /* typical write delay */ + rc = avr_read_byte(fd, p, mem, addr, &r); + if (rc != 0) { + return -1; + } + if ((data == mem->readback[0]) || + (data == mem->readback[1])) { /* * use an extra long delay when we happen to be writing values * used for polled data read-back. In this case, polling * doesn't work, and we need to delay the worst case write time * specified for the chip. */ - usleep(p->mem[memtype].max_write_delay); - r = avr_read_byte(fd, p, memtype, addr); + usleep(mem->max_write_delay); + rc = avr_read_byte(fd, p, mem, addr, &r); + if (rc != 0) { + return -1; + } } if (r == data) { @@ -504,19 +610,28 @@ int avr_write_byte(int fd, AVRPART * p, int memtype, * * Return the number of bytes written, or -1 if an error occurs. */ -int avr_write(int fd, AVRPART * p, int memtype, int size) +int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose) { int rc; int wsize; unsigned long i; unsigned char data; int werror; + AVRMEM * m; + + m = avr_locate_mem(p, memtype); + if (m == NULL) { + fprintf(stderr, "No \"%s\" memory for part %s\n", + memtype, p->desc); + return -1; + } + LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); werror = 0; - wsize = p->mem[memtype].size; + wsize = m->size; if (size < wsize) { wsize = size; } @@ -530,10 +645,12 @@ int avr_write(int fd, AVRPART * p, int memtype, int size) for (i=0; imem[memtype].buf[i]; - rc = avr_write_byte(fd, p, memtype, i, data); - if (i % 16 == 0) - fprintf(stderr, " \r%4lu 0x%02x", i, data); + data = m->buf[i]; + if (verbose) { + if (i % 16 == 0) + fprintf(stderr, " \r%4lu 0x%02x ", i, data); + } + rc = avr_write_byte(fd, p, m, i, data); if (rc) { fprintf(stderr, " ***failed; "); fprintf(stderr, "\n"); @@ -541,15 +658,16 @@ int avr_write(int fd, AVRPART * p, int memtype, int size) werror = 1; } - if (p->mem[memtype].paged) { - if (((i % p->mem[memtype].page_size) == p->mem[memtype].page_size-1) || + if (m->paged) { + if (((i % m->page_size) == m->page_size-1) || (i == wsize-1)) { - rc = avr_write_page(fd, p, memtype, i/p->mem[memtype].page_size); + rc = avr_write_page(fd, p, m, i); if (rc) { fprintf(stderr, - " *** page %ld (addresses 0x%04lx - 0x%04lx) failed to write\n", - i % p->mem[memtype].page_size, - i-p->mem[memtype].page_size+1, i); + " *** page %ld (addresses 0x%04lx - 0x%04lx) failed " + "to write\n", + i % m->page_size, + i - m->page_size + 1, i); fprintf(stderr, "\n"); LED_ON(fd, pgm->pinno[PIN_LED_ERR]); werror = 1; @@ -576,15 +694,23 @@ int avr_write(int fd, AVRPART * p, int memtype, int size) /* * issue the 'program enable' command to the AVR device */ -int avr_program_enable(int fd) +int avr_program_enable(int fd, AVRPART * p) { - unsigned char cmd[4] = {0xac, 0x53, 0x00, 0x00}; + unsigned char cmd[4]; unsigned char res[4]; + if (p->op[AVR_OP_PGM_ENABLE] == NULL) { + fprintf(stderr, "program enable instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd); avr_cmd(fd, cmd, res); if (res[2] != cmd[1]) - return -1; + return -2; return 0; } @@ -595,12 +721,21 @@ int avr_program_enable(int fd) */ int avr_chip_erase(int fd, AVRPART * p) { - unsigned char data[4] = {0xac, 0x80, 0x00, 0x00}; + unsigned char cmd[4]; unsigned char res[4]; + if (p->op[AVR_OP_CHIP_ERASE] == NULL) { + fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + LED_ON(fd, pgm->pinno[PIN_LED_PGM]); - avr_cmd(fd, data, res); + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); + avr_cmd(fd, cmd, res); usleep(p->chip_erase_delay); avr_initialize(fd, p); @@ -613,16 +748,16 @@ int avr_chip_erase(int fd, AVRPART * p) /* * read the AVR device's signature bytes */ -int avr_signature(int fd, unsigned char sig[4]) +int avr_signature(int fd, AVRPART * p) { - unsigned char cmd[4] = {0x30, 0x00, 0x00, 0x00}; - unsigned char res[4]; - int i; + int rc; - for (i=0; i<4; i++) { - cmd[2] = i; - avr_cmd(fd, cmd, res); - sig[i] = res[3]; + rc = avr_read(fd, p, "signature", 0, 0); + if (rc < 0) { + fprintf(stderr, + "%s: error reading signature data for part \"%s\", rc=%d\n", + progname, p->desc, rc); + return -1; } return 0; @@ -674,12 +809,12 @@ int avr_initialize(int fd, AVRPART * p) * of sync. */ if (strcmp(p->desc, "AT90S1200")==0) { - avr_program_enable(fd); + avr_program_enable(fd, p); } else { tries = 0; do { - rc = avr_program_enable(fd); + rc = avr_program_enable(fd, p); if (rc == 0) break; ppi_pulsepin(fd, pgm->pinno[PIN_AVR_SCK]); @@ -700,27 +835,17 @@ int avr_initialize(int fd, AVRPART * p) -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; - } -} - - int avr_initmem(AVRPART * p) { - int i; + LNODEID ln; + AVRMEM * m; - for (i=0; imem[i].buf = (unsigned char *) malloc(p->mem[i].size); - if (p->mem[i].buf == NULL) { + for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { + m = ldata(ln); + m->buf = (unsigned char *) malloc(m->size); + if (m->buf == NULL) { fprintf(stderr, "%s: can't alloc buffer for %s size of %d bytes\n", - progname, avr_memtstr(i), p->mem[i].size); + progname, m->desc, m->size); return -1; } } @@ -736,15 +861,32 @@ int avr_initmem(AVRPART * p) * * Return the number of bytes verified, or -1 if they don't match. */ -int avr_verify(AVRPART * p, AVRPART * v, int memtype, int size) +int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size) { int i; unsigned char * buf1, * buf2; int vsize; + AVRMEM * a, * b; - buf1 = p->mem[memtype].buf; - buf2 = v->mem[memtype].buf; - vsize = p->mem[memtype].size; + a = avr_locate_mem(p, memtype); + if (a == NULL) { + fprintf(stderr, + "avr_verify(): memory type \"%s\" not defined for part %s\n", + memtype, p->desc); + return -1; + } + + b = avr_locate_mem(v, memtype); + if (b == NULL) { + fprintf(stderr, + "avr_verify(): memory type \"%s\" not defined for part %s\n", + memtype, v->desc); + return -1; + } + + buf1 = a->buf; + buf2 = b->buf; + vsize = a->size; if (vsize < size) { fprintf(stderr, @@ -752,7 +894,7 @@ int avr_verify(AVRPART * p, AVRPART * v, int memtype, int size) "%s%s memory region only contains %d bytes\n" "%sOnly %d bytes will be verified.\n", progname, size, - progbuf, avr_memtstr(memtype), vsize, + progbuf, memtype, vsize, progbuf, vsize); size = vsize; } @@ -777,20 +919,19 @@ void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type) { if (m == NULL) { fprintf(f, - "%sMem Page Page Polled\n" - "%sType Paged Size Size #Pages Shift MinW MaxW ReadBack\n" - "%s------ ------ ------ ---- ------ ----- ----- ----- ---------\n", + "%sMem Page Polled\n" + "%sType Paged Size Size #Pages MinW MaxW ReadBack\n" + "%s----------- ------ ------ ---- ------ ----- ----- ---------\n", prefix, prefix, prefix); } else { fprintf(f, - "%s%-6s %-6s %6d %4d %6d %5d %5d %5d 0x%02x 0x%02x\n", - prefix, avr_memtstr(type), + "%s%-11s %-6s %6d %4d %5d %5d %5d 0x%02x 0x%02x\n", + prefix, m->desc, m->paged ? "yes" : "no", m->size, m->page_size, m->num_pages, - m->pageaddr_shift, m->min_write_delay, m->max_write_delay, m->readback[0], @@ -805,6 +946,8 @@ void avr_display(FILE * f, AVRPART * p, char * prefix) int i; char * buf; char * px; + LNODEID ln; + AVRMEM * m; fprintf(f, "%sAVR Part : %s\n" @@ -827,8 +970,9 @@ void avr_display(FILE * f, AVRPART * p, char * prefix) } avr_mem_display(px, f, NULL, 0); - for (i=0; imem[i], i); + for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { + m = ldata(ln); + avr_mem_display(px, f, m, i); } if (buf) diff --git a/avr.h b/avr.h index 0ad6e97c..c6a0f42d 100644 --- a/avr.h +++ b/avr.h @@ -34,29 +34,62 @@ #include +#include "lists.h" + + /* - * AVR memory designations; the order of these is important, these are - * used as indexes into statically initialized data, don't change them - * around. Specifically, avr_read_byte() and avr_write_byte() rely on - * the order. + * AVR serial programming instructions */ -#define AVR_M_EEPROM 0 -#define AVR_M_FLASH 1 -#define AVR_M_FUSE 2 -#define AVR_M_LOCK 3 +enum { + AVR_OP_READ, + AVR_OP_WRITE, + AVR_OP_READ_LO, + AVR_OP_READ_HI, + AVR_OP_WRITE_LO, + AVR_OP_WRITE_HI, + AVR_OP_LOADPAGE_LO, + AVR_OP_LOADPAGE_HI, + AVR_OP_WRITEPAGE, + AVR_OP_CHIP_ERASE, + AVR_OP_PGM_ENABLE, + AVR_OP_MAX +}; -#define AVR_MAXMEMTYPES 2 /* just flash and eeprom */ +enum { + AVR_CMDBIT_IGNORE, /* bit is ignored on input and output */ + AVR_CMDBIT_VALUE, /* bit is set to 0 or 1 for input or output */ + AVR_CMDBIT_ADDRESS, /* this bit represents an input address bit */ + AVR_CMDBIT_INPUT, /* this bit is an input bit */ + AVR_CMDBIT_OUTPUT /* this bit is an output bit */ +}; + +/* + * serial programming instruction bit specifications + */ +typedef struct cmdbit { + int type; /* AVR_CMDBIT_* */ + int bitno; /* which input bit to use for this command bit */ + int value; /* bit value if type == AVR_CMDBIT_VALUD */ +} CMDBIT; + +typedef struct opcode { + CMDBIT bit[32]; /* opcode bit specs */ +} OPCODE; + + +#define AVR_MEMDESCLEN 64 typedef struct avrmem { - int paged; /* page addressed (e.g. ATmega flash) */ - int size; /* total memory size in bytes */ - int page_size; /* size of memory page (if page addressed) */ - int num_pages; /* number of pages (if page addressed) */ - int pageaddr_shift; /* number of bits in the page address */ - int min_write_delay; /* microseconds */ - int max_write_delay; /* microseconds */ - unsigned char readback[2]; /* polled read-back values */ - unsigned char * buf; /* pointer to memory buffer */ + char desc[AVR_MEMDESCLEN]; /* memory description ("flash", "eeprom", etc) */ + int paged; /* page addressed (e.g. ATmega flash) */ + int size; /* total memory size in bytes */ + int page_size; /* size of memory page (if page addressed) */ + int num_pages; /* number of pages (if page addressed) */ + int min_write_delay; /* microseconds */ + int max_write_delay; /* microseconds */ + unsigned char readback[2]; /* polled read-back values */ + unsigned char * buf; /* pointer to memory buffer */ + OPCODE * op[AVR_OP_MAX]; /* opcodes */ } AVRMEM; @@ -65,10 +98,10 @@ typedef struct avrmem { typedef struct avrpart { char desc[AVR_DESCLEN]; /* long part name */ char id[AVR_IDLEN]; /* short part name */ + int chip_erase_delay; /* microseconds */ + OPCODE * op[AVR_OP_MAX]; /* opcodes */ - int chip_erase_delay; /* microseconds */ - - AVRMEM mem[AVR_MAXMEMTYPES]; + LISTID mem; /* avr memory definitions */ } AVRPART; @@ -80,42 +113,38 @@ AVRPART * avr_find_part(char * p); AVRPART * avr_new_part(void); +OPCODE * avr_new_opcode(void); + +AVRMEM * avr_new_memtype(void); + AVRPART * avr_dup_part(AVRPART * d); +AVRMEM * avr_locate_mem(AVRPART * p, char * desc); + int avr_txrx_bit(int fd, int bit); 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); +int avr_read_byte(int fd, AVRPART * p, AVRMEM * mem, unsigned long addr, + unsigned char * value); -unsigned char avr_read_fuse(int fd, AVRPART * p, int high); +int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose); -int avr_write_fuse(int fd, AVRPART * p, int high, unsigned char b); +int avr_write_page(int fd, AVRPART * p, AVRMEM * mem, + unsigned long addr); -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 size); - -int avr_write_bank(int fd, AVRPART * p, int memtype, - unsigned short bank); - -int avr_write_byte(int fd, AVRPART * p, int memtype, +int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, unsigned long addr, unsigned char data); -int avr_write(int fd, AVRPART * p, int memtype, int size); +int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose); -int avr_program_enable(int fd); +int avr_program_enable(int fd, AVRPART * p); int avr_chip_erase(int fd, AVRPART * p); -int avr_signature(int fd, unsigned char sig[4]); +int avr_signature(int fd, AVRPART * p); void avr_powerup(int fd); @@ -127,8 +156,7 @@ char * avr_memtstr(int memtype); int avr_initmem(AVRPART * p); -int avr_verify(AVRPART * p, AVRPART * v, int memtype, - int size); +int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size); void avr_display(FILE * f, AVRPART * p, char * prefix); diff --git a/avrdude.conf.sample b/avrdude.conf.sample index d509e21b..00e02897 100644 --- a/avrdude.conf.sample +++ b/avrdude.conf.sample @@ -93,7 +93,7 @@ programmer vfyled = 17; ; - +/* part id = "1200"; desc = "AT90S1200"; @@ -335,22 +335,40 @@ part readback_p2 = 0xff; ; ; +*/ part id = "m163"; desc = "ATMEGA163"; + pgm_enable = "1", "0", "1", "0", "1", "1", "0", "0", + "0", "1", "0", "1", "0", "0", "1", "1", + "x", "x", "x", "x", "x", "x", "x", "x", + "x", "x", "x", "x", "x", "x", "x", "x"; + + chip_erase = "1", "0", "1", "0", "1", "1", "0", "0", + "1", "0", "0", "0", "0", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "x", + "x", "x", "x", "x", "x", "x", "x", "x"; + chip_erase_delay = 32000; - eeprom - paged = no; + memory "eeprom" size = 512; - page_size = 0; - num_pages = 0; min_write_delay = 4000; max_write_delay = 4000; readback_p1 = 0xff; readback_p2 = 0xff; + + read = "1", "0", "1", "0", "0", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "a8", + "a7", "a6", "a5", "a4", "a3", "a2", "a1", "a0", + "o", "o", "o", "o", "o", "o", "o", "o"; + + write = "1", "1", "0", "0", "0", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "a8", + "a7", "a6", "a5", "a4", "a3", "a2", "a1", "a0", + "i", "i", "i", "i", "i", "i", "i", "i"; ; - flash + memory "flash" paged = yes; size = 16384; page_size = 128; @@ -359,7 +377,93 @@ part max_write_delay = 16000; readback_p1 = 0xff; readback_p2 = 0xff; + + read_lo = "0", "0", "1", "0", "0", "0", "0", "0", + "x", "x", "x", "a12", "a11", "a10", "a9", "a8", + "a7", "a6", "a5", "a4", "a3", "a2", "a1", "a0", + "o", "o", "o", "o", "o", "o", "o", "o"; + + read_hi = "0", "0", "1", "0", "1", "0", "0", "0", + "x", "x", "x", "a12", "a11", "a10", "a9", "a8", + "a7", "a6", "a5", "a4", "a3", "a2", "a1", "a0", + "o", "o", "o", "o", "o", "o", "o", "o"; + + loadpage_lo = "0", "1", "0", "0", "0", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "x", + "x", "x", "a5", "a4", "a3", "a2", "a1", "a0", + "i", "i", "i", "i", "i", "i", "i", "i"; + + loadpage_hi = "0", "1", "0", "0", "1", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "x", + "x", "x", "a5", "a4", "a3", "a2", "a1", "a0", + "i", "i", "i", "i", "i", "i", "i", "i"; + + writepage = "0", "1", "0", "0", "1", "1", "0", "0", + "x", "x", "x", "a12", "a11", "a10", "a9", "a8", + "a7", "a6", "x", "x", "x", "x", "x", "x", + "x", "x", "x", "x", "x", "x", "x", "x"; ; + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + + read = "0", "1", "0", "1", "0", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "x", + "o", "o", "x", "x", "o", "o", "o", "o"; + + write = "1", "0", "1", "0", "1", "1", "0", "0", + "1", "0", "1", "0", "0", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "x", + "i", "i", "1", "1", "i", "i", "i", "i"; + ; + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + + read = "0", "1", "0", "1", "1", "0", "0", "0", + "0", "0", "0", "0", "1", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "x", + "x", "x", "x", "x", "1", "o", "o", "o"; + + write = "1", "0", "1", "0", "1", "1", "0", "0", + "1", "0", "1", "0", "1", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "x", + "1", "1", "1", "1", "1", "i", "i", "i"; + ; + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + + read = "0", "1", "0", "1", "1", "0", "0", "0", + "0", "0", "0", "0", "0", "0", "0", "0", + "x", "x", "x", "x", "0", "x", "x", "x", + "x", "x", "o", "o", "o", "o", "o", "o"; + + write = "1", "0", "1", "0", "1", "1", "0", "0", + "1", "1", "1", "x", "x", "x", "x", "x", + "x", "x", "x", "x", "x", "x", "x", "x", + "1", "1", "i", "i", "i", "i", "i", "i"; + ; + memory "signature" + size = 3; + + read = "0", "0", "1", "1", "0", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "x", + "x", "x", "x", "x", "x", "x", "a1", "a0", + "o", "o", "o", "o", "o", "o", "o", "o"; + ; + memory "calibration" + size = 1; + read = "0", "0", "1", "1", "1", "0", "0", "0", + "x", "x", "x", "x", "x", "x", "x", "x", + "0", "0", "0", "0", "0", "0", "0", "0", + "o", "o", "o", "o", "o", "o", "o", "o"; + ; + /* instructions instr "pe", "programming enable" [ "1010 1100", "0101 0011", "xxxx xxxx", "xxxx xxxx" ]; @@ -381,6 +485,7 @@ part */ ; +/* part id = "m8"; desc = "ATMEGA8"; @@ -407,3 +512,4 @@ part ; ; +*/ \ No newline at end of file diff --git a/config.c b/config.c index 983f5fc7..a6e9e709 100644 --- a/config.c +++ b/config.c @@ -45,7 +45,7 @@ LISTID string_list; LISTID number_list; PROGRAMMER * current_prog; AVRPART * current_part; -int current_mem; +AVRMEM * current_mem; LISTID part_list; LISTID programmers; diff --git a/config.h b/config.h index 016910dd..ca4f1a9d 100644 --- a/config.h +++ b/config.h @@ -63,7 +63,7 @@ typedef struct programmer_t { extern FILE * yyin; extern PROGRAMMER * current_prog; extern AVRPART * current_part; -extern int current_mem; +extern AVRMEM * current_mem; extern LISTID programmers; extern LISTID part_list; extern int lineno; diff --git a/config_gram.y b/config_gram.y index 13bd333f..4645af52 100644 --- a/config_gram.y +++ b/config_gram.y @@ -29,8 +29,23 @@ /* $Id$ */ +%token K_OP +%token K_READ +%token K_WRITE +%token K_READ_LO +%token K_READ_HI +%token K_WRITE_LO +%token K_WRITE_HI +%token K_LOADPAGE_LO +%token K_LOADPAGE_HI +%token K_WRITEPAGE +%token K_CHIP_ERASE +%token K_PGM_ENABLE + +%token K_MEMORY + %token K_PAGE_SIZE -%token K_PAGEED +%token K_PAGED %token K_BUFF %token K_CHIP_ERASE_DELAY %token K_DESC @@ -107,7 +122,8 @@ part_def : { current_part = avr_new_part(); } part_parms { - unsigned int i, j, shift, psize; + LNODEID ln; + AVRMEM * m; if (current_part->id[0] == 0) { fprintf(stderr, @@ -121,49 +137,35 @@ part_def : * to shift a page for constructing the page address for * page-addressed memories. */ - for (i=0; imem[i].paged) { - if (!current_part->mem[i].page_size) { + for (ln=lfirst(current_part->mem); ln; ln=lnext(ln)) { + m = ldata(ln); + if (m->paged) { + if (m->page_size == 0) { fprintf(stderr, "%s: error at %s:%d: must specify page_size for paged " "memory\n", progname, infile, lineno); exit(1); } - if (!current_part->mem[i].num_pages) { + if (m->num_pages == 0) { fprintf(stderr, "%s: error at %s:%d: must specify num_pages for paged " "memory\n", progname, infile, lineno); exit(1); } - if (current_part->mem[i].size != current_part->mem[i].page_size * - current_part->mem[i].num_pages) { + if (m->size != m->page_size * m->num_pages) { fprintf(stderr, "%s: error at %s:%d: page size (%u) * num_pages (%u) = " "%u does not match memory size (%u)\n", progname, infile, lineno, - current_part->mem[i].page_size, - current_part->mem[i].num_pages, - current_part->mem[i].page_size * current_part->mem[i].num_pages, - current_part->mem[i].size); + m->page_size, + m->num_pages, + m->page_size * m->num_pages, + m->size); exit(1); } - shift = 0; - psize = current_part->mem[i].page_size / 2 - 1; - for (j=0; j<32 && !shift; j++) { - if ((psize >> j) == 0) { - shift = j; - } - } - if (!shift) { - fprintf(stderr, - "%s: error at %s:%d: can't determine amount to shift for the page address\n" - " Are you sure page_size (=%u) is correct?\n", - progname, infile, lineno, current_part->mem[i].page_size); - exit(1); - } - current_part->mem[i].pageaddr_shift = shift; + } } @@ -246,6 +248,21 @@ prog_parm : ; +opcode : + K_READ | + K_WRITE | + K_READ_LO | + K_READ_HI | + K_WRITE_LO | + K_WRITE_HI | + K_LOADPAGE_LO | + K_LOADPAGE_HI | + K_WRITEPAGE | + K_CHIP_ERASE | + K_PGM_ENABLE +; + + part_parms : part_parm TKN_SEMI | part_parms part_parm TKN_SEMI @@ -273,11 +290,46 @@ part_parm : free_token($3); } | +/* K_EEPROM { current_mem = AVR_M_EEPROM; } mem_specs | K_FLASH { current_mem = AVR_M_FLASH; } - mem_specs + mem_specs | +*/ + + K_MEMORY TKN_STRING + { + current_mem = avr_new_memtype(); + strcpy(current_mem->desc, strdup($2->value.string)); + free_token($2); + } + mem_specs + { + ladd(current_part->mem, current_mem); + current_mem = NULL; + } | + + opcode TKN_EQUAL string_list { + { + int opnum; + OPCODE * op; + + if (lsize(string_list) != 32) { + fprintf(stderr, + "%s: error at %s:%d: only %d bits specified, need 32\n", + progname, infile, lineno, lsize(string_list)); + exit(1); + } + + opnum = which_opcode($1); + op = avr_new_opcode(); + parse_cmdbits(op); + current_part->op[opnum] = op; + + free_token($1); + } + } ; @@ -295,52 +347,73 @@ mem_specs : mem_spec : K_PAGED TKN_EQUAL yesno { - current_part->mem[current_mem].paged = $3->primary == K_YES ? 1 : 0; + current_mem->paged = $3->primary == K_YES ? 1 : 0; free_token($3); } | K_SIZE TKN_EQUAL TKN_NUMBER { - current_part->mem[current_mem].size = $3->value.number; + current_mem->size = $3->value.number; free_token($3); } | K_PAGE_SIZE TKN_EQUAL TKN_NUMBER { - current_part->mem[current_mem].page_size = $3->value.number; + current_mem->page_size = $3->value.number; free_token($3); } | K_NUM_PAGES TKN_EQUAL TKN_NUMBER { - current_part->mem[current_mem].num_pages = $3->value.number; + current_mem->num_pages = $3->value.number; free_token($3); } | K_MIN_WRITE_DELAY TKN_EQUAL TKN_NUMBER { - current_part->mem[current_mem].min_write_delay = $3->value.number; + current_mem->min_write_delay = $3->value.number; free_token($3); } | K_MAX_WRITE_DELAY TKN_EQUAL TKN_NUMBER { - current_part->mem[current_mem].max_write_delay = $3->value.number; + current_mem->max_write_delay = $3->value.number; free_token($3); } | K_READBACK_P1 TKN_EQUAL TKN_NUMBER { - current_part->mem[current_mem].readback[0] = $3->value.number; + current_mem->readback[0] = $3->value.number; free_token($3); } | K_READBACK_P2 TKN_EQUAL TKN_NUMBER { - current_part->mem[current_mem].readback[1] = $3->value.number; + current_mem->readback[1] = $3->value.number; free_token($3); + } | + + opcode TKN_EQUAL string_list { + { + int opnum; + OPCODE * op; + + if (lsize(string_list) != 32) { + fprintf(stderr, + "%s: error at %s:%d: only %d bits specified, need 32\n", + progname, infile, lineno, lsize(string_list)); + exit(1); + } + + opnum = which_opcode($1); + op = avr_new_opcode(); + parse_cmdbits(op); + current_mem->op[opnum] = op; + + free_token($1); } + } ; @@ -392,3 +465,123 @@ static int assign_pin(int pinno, TOKEN * v) return 0; } + +static int which_opcode(TOKEN * opcode) +{ + switch (opcode->primary) { + case K_READ : return AVR_OP_READ; break; + case K_WRITE : return AVR_OP_WRITE; break; + case K_READ_LO : return AVR_OP_READ_LO; break; + case K_READ_HI : return AVR_OP_READ_HI; break; + case K_WRITE_LO : return AVR_OP_WRITE_LO; break; + case K_WRITE_HI : return AVR_OP_WRITE_HI; break; + case K_LOADPAGE_LO : return AVR_OP_LOADPAGE_LO; break; + case K_LOADPAGE_HI : return AVR_OP_LOADPAGE_HI; break; + case K_WRITEPAGE : return AVR_OP_WRITEPAGE; break; + case K_CHIP_ERASE : return AVR_OP_CHIP_ERASE; break; + case K_PGM_ENABLE : return AVR_OP_PGM_ENABLE; break; + default : + fprintf(stderr, + "%s: error at %s:%d: invalid opcode\n", + progname, infile, lineno); + exit(1); + break; + } +} + + +static int parse_cmdbits(OPCODE * op) +{ + TOKEN * t; + int bitno; + char ch; + char * e; + char * q; + int len; + + bitno = 31; + while (lsize(string_list)) { + + t = lrmv_n(string_list, 1); + + len = strlen(t->value.string); + + if (len == 0) { + fprintf(stderr, + "%s: error at %s:%d: invalid bit specifier \"\"\n", + progname, infile, lineno); + exit(1); + } + + ch = t->value.string[0]; + + if (len == 1) { + switch (ch) { + case '1': + op->bit[bitno].type = AVR_CMDBIT_VALUE; + op->bit[bitno].value = 1; + op->bit[bitno].bitno = bitno % 8; + break; + case '0': + op->bit[bitno].type = AVR_CMDBIT_VALUE; + op->bit[bitno].value = 0; + op->bit[bitno].bitno = bitno % 8; + break; + case 'x': + op->bit[bitno].type = AVR_CMDBIT_IGNORE; + op->bit[bitno].value = 0; + op->bit[bitno].bitno = bitno % 8; + break; + case 'a': + op->bit[bitno].type = AVR_CMDBIT_ADDRESS; + op->bit[bitno].value = 0; + op->bit[bitno].bitno = 8*(bitno/8) + bitno % 8; + break; + case 'i': + op->bit[bitno].type = AVR_CMDBIT_INPUT; + op->bit[bitno].value = 0; + op->bit[bitno].bitno = bitno % 8; + break; + case 'o': + op->bit[bitno].type = AVR_CMDBIT_OUTPUT; + op->bit[bitno].value = 0; + op->bit[bitno].bitno = bitno % 8; + break; + default : + fprintf(stderr, + "%s: error at %s:%d: invalid bit specifier '%c'\n", + progname, infile, lineno, ch); + exit(1); + break; + } + } + else { + if (ch == 'a') { + q = &t->value.string[1]; + op->bit[bitno].bitno = strtol(q, &e, 0); + if ((e == q)||(*e != 0)) { + fprintf(stderr, + "%s: error at %s:%d: can't parse bit number from \"%s\"\n", + progname, infile, lineno, q); + exit(1); + } + op->bit[bitno].type = AVR_CMDBIT_ADDRESS; + op->bit[bitno].value = 0; + } + else { + fprintf(stderr, + "%s: error at %s:%d: invalid bit specifier \"%s\"\n", + progname, infile, lineno, t->value.string); + exit(1); + } + } + + free_token(t); + bitno--; + + } /* while */ + + return 0; +} + + diff --git a/fileio.c b/fileio.c index cf28033e..a0304e20 100644 --- a/fileio.c +++ b/fileio.c @@ -520,7 +520,7 @@ int fmt_autodetect(char * fname) int fileio(int op, char * filename, FILEFMT format, - struct avrpart * p, int memtype, int size) + struct avrpart * p, char * memtype, int size) { int rc; FILE * f; @@ -528,6 +528,15 @@ int fileio(int op, char * filename, FILEFMT format, unsigned char * buf; struct fioparms fio; int i; + AVRMEM * mem; + + mem = avr_locate_mem(p, memtype); + if (mem == NULL) { + fprintf(stderr, + "fileio(): memory type \"%s\" not configured for device \"%s\"\n", + memtype, p->desc); + return -1; + } rc = fileio_setparms(op, &fio); if (rc < 0) @@ -554,9 +563,9 @@ int fileio(int op, char * filename, FILEFMT format, } /* point at the requested memory buffer */ - buf = p->mem[memtype].buf; + buf = mem->buf; if (fio.op == FIO_READ) - size = p->mem[memtype].size; + size = mem->size; if (fio.op == FIO_READ) { /* 0xff fill unspecified memory */ diff --git a/fileio.h b/fileio.h index d775b2a9..7c1126f5 100644 --- a/fileio.h +++ b/fileio.h @@ -57,6 +57,6 @@ char * fmtstr(FILEFMT format); int fileio_setparms(int op, struct fioparms * fp); int fileio(int op, char * filename, FILEFMT format, - struct avrpart * p, int memtype, int size); + struct avrpart * p, char * memtype, int size); #endif diff --git a/lexer.l b/lexer.l index 27487102..ffcd4bd5 100644 --- a/lexer.l +++ b/lexer.l @@ -152,6 +152,21 @@ size { yylval=NULL; return K_SIZE; } vcc { yylval=NULL; return K_VCC; } vfyled { yylval=NULL; return K_VFYLED; } +op { yylval=NULL; return K_OP; } +read { yylval=new_token(K_READ); return K_READ; } +write { yylval=new_token(K_WRITE); return K_WRITE; } +read_lo { yylval=new_token(K_READ_LO); return K_READ_LO; } +read_hi { yylval=new_token(K_READ_HI); return K_READ_HI; } +write_lo { yylval=new_token(K_WRITE_LO); return K_WRITE_LO; } +write_hi { yylval=new_token(K_WRITE_HI); return K_WRITE_HI; } +loadpage_lo { yylval=new_token(K_LOADPAGE_LO); return K_LOADPAGE_LO; } +loadpage_hi { yylval=new_token(K_LOADPAGE_HI); return K_LOADPAGE_HI; } +writepage { yylval=new_token(K_WRITEPAGE); return K_WRITEPAGE; } +chip_erase { yylval=new_token(K_CHIP_ERASE); return K_CHIP_ERASE; } +pgm_enable { yylval=new_token(K_PGM_ENABLE); return K_PGM_ENABLE; } + +memory { yylval=NULL; return K_MEMORY; } + no { yylval=new_token(K_NO); return K_NO; } yes { yylval=new_token(K_YES); return K_YES; } diff --git a/main.c b/main.c index 070e10ae..7833c452 100644 --- a/main.c +++ b/main.c @@ -450,17 +450,16 @@ int main(int argc, char * argv []) int ch; /* options flag */ int size; /* size of memory region */ int len; /* length for various strings */ - 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 */ struct avrpart * v; /* used for verify */ int readorwrite; /* true if a chip read/write op was selected */ int ppidata; /* cached value of the ppi data register */ int vsize=-1; /* number of bytes to verify */ char timestamp[64]; + AVRMEM * sig; /* signature data */ /* options / operating mode variables */ - int memtype; /* AVR_FLASH or AVR_EEPROM */ + char * memtype; /* "flash", "eeprom", etc */ int doread; /* 1=reading AVR, 0=writing AVR */ int erase; /* 1=erase chip, 0=don't */ char * outputf; /* output file name */ @@ -493,7 +492,7 @@ int main(int argc, char * argv []) outputf = NULL; inputf = NULL; doread = 1; - memtype = AVR_M_FLASH; + memtype = "flash"; erase = 0; p = NULL; ovsigck = 0; @@ -567,17 +566,14 @@ int main(int argc, char * argv []) case 'm': /* select memory type to operate on */ if ((strcasecmp(optarg,"e")==0)||(strcasecmp(optarg,"eeprom")==0)) { - memtype = AVR_M_EEPROM; + memtype = "eeprom"; } else if ((strcasecmp(optarg,"f")==0)|| (strcasecmp(optarg,"flash")==0)) { - memtype = AVR_M_FLASH; + memtype = "flash"; } else { - fprintf(stderr, "%s: invalid memory type \"%s\"\n\n", - progname, optarg); - usage(); - exit(1); + memtype = optarg; } readorwrite = 1; break; @@ -833,23 +829,43 @@ int main(int argc, char * argv []) * against 0xffffffff should ensure that the signature bytes are * valid. */ - avr_signature(fd, sig); - fprintf(stderr, "%s: Device signature = 0x", progname); - for (i=0; i<4; i++) - fprintf(stderr, "%02x", sig[i]); - fprintf(stderr, "\n"); + rc = avr_signature(fd, p); + if (rc != 0) { + fprintf(stderr, "%s: error reading signature data, rc=%d\n", + progname, rc); + exit(1); + } - memset(nulldev,0xff,4); - if (memcmp(sig,nulldev,4)==0) { - fprintf(stderr, - "%s: Yikes! Invalid device signature.\n", progname); - if (!ovsigck) { - fprintf(stderr, "%sDouble check connections and try again, " - "or use -F to override\n" - "%sthis check.\n\n", - progbuf, progbuf); - exitrc = 1; - goto main_exit; + sig = avr_locate_mem(p, "signature"); + if (sig == NULL) { + fprintf(stderr, + "%s: WARNING: signature data not defined for device \"%s\"\n", + progname, p->desc); + } + + if (sig != NULL) { + int ff; + + fprintf(stderr, "%s: Device signature = 0x", progname); + ff = 1; + for (i=0; isize; i++) { + fprintf(stderr, "%02x", sig->buf[i]); + if (sig->buf[i] != 0xff) + ff = 0; + } + fprintf(stderr, "\n"); + + if (ff) { + fprintf(stderr, + "%s: Yikes! Invalid device signature.\n", progname); + if (!ovsigck) { + fprintf(stderr, "%sDouble check connections and try again, " + "or use -F to override\n" + "%sthis check.\n\n", + progbuf, progbuf); + exitrc = 1; + goto main_exit; + } } } @@ -892,11 +908,11 @@ int main(int argc, char * argv []) * read out the specified device memory and write it to a file */ fprintf(stderr, "%s: reading %s memory:\n", - progname, avr_memtstr(memtype)); - rc = avr_read(fd, p, memtype, 0); + progname, memtype); + rc = avr_read(fd, p, memtype, 0, 1); if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", - progname, avr_memtstr(memtype), rc); + progname, memtype, rc); exitrc = 1; goto main_exit; } @@ -931,10 +947,10 @@ int main(int argc, char * argv []) * write the buffer contents to the selected memory type */ fprintf(stderr, "%s: writing %s:\n", - progname, avr_memtstr(memtype)); + progname, memtype); if (!nowrite) { - rc = avr_write(fd, p, memtype, size); + rc = avr_write(fd, p, memtype, size, 1); } else { /* @@ -954,7 +970,7 @@ int main(int argc, char * argv []) vsize = rc; fprintf(stderr, "%s: %d bytes of %s written\n", progname, - vsize, avr_memtstr(memtype)); + vsize, memtype); } @@ -966,13 +982,13 @@ int main(int argc, char * argv []) LED_ON(fd, pgm->pinno[PIN_LED_VFY]); fprintf(stderr, "%s: verifying %s memory against %s:\n", - progname, avr_memtstr(memtype), inputf); + progname, memtype, inputf); fprintf(stderr, "%s: reading on-chip %s data:\n", - progname, avr_memtstr(memtype)); - rc = avr_read(fd, v, memtype, vsize); + progname, memtype); + rc = avr_read(fd, v, memtype, vsize, 1); if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", - progname, avr_memtstr(memtype), rc); + progname, memtype, rc); LED_ON(fd, pgm->pinno[PIN_LED_ERR]); exitrc = 1; goto main_exit; @@ -989,7 +1005,7 @@ int main(int argc, char * argv []) } fprintf(stderr, "%s: %d bytes of %s verified\n", - progname, rc, avr_memtstr(memtype)); + progname, rc, memtype); LED_OFF(fd, pgm->pinno[PIN_LED_VFY]); } diff --git a/term.c b/term.c index 814034f9..c99de90d 100644 --- a/term.c +++ b/term.c @@ -38,6 +38,7 @@ #include "avr.h" #include "config.h" +#include "lists.h" #include "pindefs.h" #include "ppi.h" @@ -64,8 +65,6 @@ 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[]); @@ -76,14 +75,13 @@ int cmd_send (int fd, struct avrpart * p, int argc, char *argv[]); struct command cmd[] = { - { "dump", cmd_dump, "dump memory : %s [eeprom|flash] " }, + { "dump", cmd_dump, "dump memory : %s " }, { "read", cmd_dump, "alias for dump" }, - { "write", cmd_write, "write memory : %s [eeprom|flash] ... " }, + { "write", cmd_write, "write memory : %s ... " }, { "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 " }, + { "part", cmd_part, "display the current part information" }, + { "send", cmd_send, "send a raw command : %s " }, { "help", cmd_help, "help" }, { "?", cmd_help, "help" }, { "quit", cmd_quit, "quit" } @@ -179,7 +177,7 @@ int chardump_line(char * buffer, unsigned char * p, int n, int pad) } -int hexdump_buf(FILE * f, int startaddr, char * buf, int len) +int hexdump_buf(FILE * f, int startaddr, unsigned char * buf, int len) { int addr; int i, n; @@ -209,84 +207,51 @@ int hexdump_buf(FILE * f, int startaddr, char * buf, int len) int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) { char * e; - int i, l; - char * buf; + unsigned char * buf; int maxsize; - static int memtype=AVR_M_FLASH; - static unsigned short addr=0; + unsigned long i; + static unsigned long addr=0; static int len=64; + AVRMEM * mem; + char * memtype = NULL; + int rc; - if (argc == 1) { - addr += len; + if (!((argc == 2) || (argc == 4))) { + fprintf(stderr, "Usage: dump [ ]\n"); + return -1; } - else { - if (!((argc == 2) || (argc == 4))) { - fprintf(stderr, "Usage: dump flash|eeprom|fuse|lock [ ]\n"); + + memtype = argv[1]; + + mem = avr_locate_mem(p, memtype); + if (mem == NULL) { + fprintf(stderr, "\"%s\" memory type not defined for part \"%s\"\n", + memtype, p->desc); + return -1; + } + + if (argc == 4) { + addr = strtoul(argv[2], &e, 0); + if (*e || (e == argv[2])) { + fprintf(stderr, "%s (dump): can't parse address \"%s\"\n", + progname, argv[2]); return -1; } - l = strlen(argv[1]); - if (strncasecmp(argv[1],"flash",l)==0) { - memtype = AVR_M_FLASH; - } - 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]); + len = strtol(argv[3], &e, 0); + if (*e || (e == argv[3])) { + fprintf(stderr, "%s (dump): can't parse length \"%s\"\n", + progname, argv[3]); return -1; } - - if (argc == 4) { - addr = strtoul(argv[2], &e, 0); - if (*e || (e == argv[2])) { - fprintf(stderr, "%s (dump): can't parse address \"%s\"\n", - progname, argv[2]); - return -1; - } - - len = strtol(argv[3], &e, 0); - if (*e || (e == argv[3])) { - fprintf(stderr, "%s (dump): can't parse length \"%s\"\n", - progname, argv[3]); - return -1; - } - } } - 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; - len = maxsize; - } + maxsize = mem->size; if (addr > maxsize) { fprintf(stderr, - "%s (dump): address 0x%04x is out of range for %s memory\n", - progname, addr, avr_memtstr(memtype)); + "%s (dump): address 0x%05lx is out of range for %s memory\n", + progname, addr, mem->desc); return -1; } @@ -301,17 +266,11 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) } for (i=0; idesc, addr+i, p->desc); + return -1; } } @@ -321,6 +280,8 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) free(buf); + addr = addr + len; + return 0; } @@ -328,13 +289,13 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) { char * e; - int i, l; int len, maxsize; - int memtype; - unsigned short addr; + char * memtype; + unsigned long addr, i; char * buf; int rc; int werror; + AVRMEM * mem; if (argc < 4) { fprintf(stderr, "Usage: write flash|eeprom|fuse " @@ -342,46 +303,16 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) return -1; } - l = strlen(argv[1]); - if (strncasecmp(argv[1],"flash",l)==0) { - memtype = AVR_M_FLASH; - } - 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]); + memtype = argv[1]; + + mem = avr_locate_mem(p, memtype); + if (mem == NULL) { + fprintf(stderr, "\"%s\" memory type not defined for part \"%s\"\n", + memtype, p->desc); return -1; } - maxsize = 0; - - 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; - } + maxsize = mem->size; addr = strtoul(argv[2], &e, 0); if (*e || (e == argv[2])) { @@ -392,8 +323,8 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) if (addr > maxsize) { fprintf(stderr, - "%s (write): address 0x%04x is out of range for %s memory\n", - progname, addr, avr_memtstr(memtype)); + "%s (write): address 0x%05lx is out of range for %s memory\n", + progname, addr, memtype); return -1; } @@ -404,7 +335,7 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) fprintf(stderr, "%s (write): selected address and # bytes exceed " "range for %s memory\n", - progname, avr_memtstr(memtype)); + progname, memtype); return -1; } @@ -427,22 +358,9 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); for (werror=0, i=0; idesc); + } + else { + fprintf(stdout, "Device signature = 0x", progname); + for (i=0; isize; i++) + fprintf(stdout, "%02x", m->buf[i]); + fprintf(stdout, "\n\n"); + } return 0; } @@ -562,7 +483,9 @@ int cmd_help(int fd, struct avrpart * p, int argc, char * argv[]) fprintf(stdout, cmd[i].desc, cmd[i].name); fprintf(stdout, "\n"); } - fprintf(stdout, "\n"); + fprintf(stdout, + "\nUse the 'part' command to display valid memory types for use with the\n" + "'dump' and 'write' commands.\n\n"); return 0; }