From a193330803bd85c1baaf5aea07d7c1ef0df60098 Mon Sep 17 00:00:00 2001 From: "Brian S. Dean" Date: Sat, 30 Nov 2002 14:09:12 +0000 Subject: [PATCH] Seperate programmer operations out into a driver-like interface so that programmers other than the direct parallel port connection can be supported. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@159 81a1dc3b-b13d-400b-aceb-764788c761c2 --- Makefile | 1 + avr.c | 313 ++++++--------------------------- avr.h | 87 ++-------- avrdude.conf.sample | 4 + config.c | 23 --- config.h | 7 - config_gram.y | 25 ++- lexer.l | 5 +- main.c | 216 ++++++++--------------- pgm.c | 135 +++++++++++++++ pgm.h | 75 ++++++++ ppi.c | 413 ++++++++++++++++++++++++++++++++++++++++++++ ppi.h | 44 +++++ term.c | 63 +++---- term.h | 3 +- 15 files changed, 868 insertions(+), 546 deletions(-) create mode 100644 pgm.c create mode 100644 pgm.h diff --git a/Makefile b/Makefile index 7ba16868..82a2c300 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ DIRS = ${BINDIR} ${MANDIR} ${DOCDIR} ${CONFIGDIR} INSTALL = /usr/bin/install -c -o root -g wheel CFLAGS += -Wall -DCONFIG_DIR=\"${CONFIGDIR}\" ${YYDEF} +#CFLAGS = -g -Wall -DCONFIG_DIR=\"${CONFIGDIR}\" ${YYDEF} LDFLAGS = YFLAGS = -t -d -v diff --git a/avr.c b/avr.c index 8d28cbb8..8555ec8d 100644 --- a/avr.c +++ b/avr.c @@ -177,65 +177,6 @@ AVRMEM * avr_locate_mem(AVRPART * p, char * desc) -/* - * transmit and receive a byte of data to/from the AVR device - */ -unsigned char avr_txrx(int fd, unsigned char byte) -{ - int i; - unsigned char r, b, rbyte; - - rbyte = 0; - for (i=0; i<8; i++) { - b = (byte >> (7-i)) & 0x01; - - /* - * read the result bit (it is either valid from a previous clock - * pulse or it is ignored in the current context) - */ - r = ppi_getpin(fd, pgm->pinno[PIN_AVR_MISO]); - - /* set the data input line as desired */ - ppi_setpin(fd, pgm->pinno[PIN_AVR_MOSI], b); - - /* - * pulse the clock line, clocking in the MOSI data, and clocking out - * the next result bit - */ - ppi_pulsepin(fd, pgm->pinno[PIN_AVR_SCK]); - - rbyte = rbyte | (r << (7-i)); - } - - return rbyte; -} - - -/* - * transmit an AVR device command and return the results; 'cmd' and - * 'res' must point to at least a 4 byte data buffer - */ -int avr_cmd(int fd, unsigned char cmd[4], unsigned char res[4]) -{ - int i; - - for (i=0; i<4; i++) { - res[i] = avr_txrx(fd, cmd[i]); - } - -#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; -} - /* * avr_set_bits() @@ -354,16 +295,16 @@ int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data) /* * read a byte of data from the indicated memory region */ -int avr_read_byte(int fd, AVRPART * p, AVRMEM * mem, unsigned long addr, - unsigned char * value) +int avr_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value) { unsigned char cmd[4]; unsigned char res[4]; unsigned char data; OPCODE * readop; - LED_ON(fd, pgm->pinno[PIN_LED_PGM]); - LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + pgm->pgm_led(pgm, ON); + pgm->err_led(pgm, OFF); /* * figure out what opcode to use @@ -392,11 +333,11 @@ int avr_read_byte(int fd, AVRPART * p, AVRMEM * mem, unsigned long addr, avr_set_bits(readop, cmd); avr_set_addr(readop, cmd, addr); - avr_cmd(fd, cmd, res); + pgm->cmd(pgm, cmd, res); data = 0; avr_get_output(readop, res, &data); - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + pgm->pgm_led(pgm, OFF); *value = data; @@ -411,7 +352,8 @@ int avr_read_byte(int fd, AVRPART * p, AVRMEM * mem, unsigned long addr, * * Return the number of bytes read, or < 0 if an error occurs. */ -int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose) +int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, + int verbose) { unsigned char rbyte; unsigned long i; @@ -435,7 +377,7 @@ int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose) printed = 0; for (i=0; iop[AVR_OP_LOADPAGE_LO]) addr = addr / 2; - LED_ON(fd, pgm->pinno[PIN_LED_PGM]); - LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + pgm->pgm_led(pgm, ON); + pgm->err_led(pgm, OFF); memset(cmd, 0, sizeof(cmd)); avr_set_bits(wp, cmd); avr_set_addr(wp, cmd, addr); - avr_cmd(fd, cmd, res); + pgm->cmd(pgm, cmd, res); /* * since we don't know what voltage the target AVR is powered by, be @@ -501,7 +443,7 @@ int avr_write_page(int fd, AVRPART * p, AVRMEM * mem, */ usleep(mem->max_write_delay); - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + pgm->pgm_led(pgm, OFF); return 0; } @@ -509,7 +451,7 @@ int avr_write_page(int fd, AVRPART * p, AVRMEM * mem, /* * write a byte of data at the specified address */ -int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, +int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsigned long addr, unsigned char data) { unsigned char cmd[4]; @@ -529,7 +471,7 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, * value and only write if we are changing the value; we can't * use this optimization for paged addressing. */ - rc = avr_read_byte(fd, p, mem, addr, &b); + rc = avr_read_byte(pgm, p, mem, addr, &b); if (rc != 0) { if (rc != -1) { return -2; @@ -578,15 +520,15 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, } - LED_ON(fd, pgm->pinno[PIN_LED_PGM]); - LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + pgm->pgm_led(pgm, ON); + pgm->err_led(pgm, OFF); 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); + pgm->cmd(pgm, cmd, res); if (mem->paged) { /* @@ -594,7 +536,7 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, * page complete immediately, we only need to delay when we commit * the whole page via the avr_write_page() routine. */ - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + pgm->pgm_led(pgm, OFF); return 0; } @@ -604,7 +546,7 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, * the max programming time and then return */ usleep(mem->max_write_delay); /* maximum write delay */ - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + pgm->pgm_led(pgm, OFF); return 0; } @@ -612,10 +554,10 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, ready = 0; while (!ready) { usleep(mem->min_write_delay); - rc = avr_read_byte(fd, p, mem, addr, &r); + rc = avr_read_byte(pgm, p, mem, addr, &r); if (rc != 0) { - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); - LED_ON(fd, pgm->pinno[PIN_LED_ERR]); + pgm->pgm_led(pgm, OFF); + pgm->err_led(pgm, ON); return -4; } @@ -628,10 +570,10 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, * specified for the chip. */ usleep(mem->max_write_delay); - rc = avr_read_byte(fd, p, mem, addr, &r); + rc = avr_read_byte(pgm, p, mem, addr, &r); if (rc != 0) { - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); - LED_ON(fd, pgm->pinno[PIN_LED_ERR]); + pgm->pgm_led(pgm, OFF); + pgm->err_led(pgm, OFF); return -5; } } @@ -648,15 +590,15 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, * device if the data read back does not match what we wrote. */ usleep(mem->max_write_delay); /* maximum write delay */ - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + pgm->pgm_led(pgm, OFF); fprintf(stderr, "%s: this device must be powered off and back on to continue\n", progname); if (pgm->pinno[PPI_AVR_VCC]) { fprintf(stderr, "%s: attempting to do this now ...\n", progname); - avr_powerdown(fd); + pgm->powerdown(pgm); usleep(250000); - rc = avr_initialize(fd, p); + rc = pgm->initialize(pgm, p); if (rc < 0) { fprintf(stderr, "%s: initialization failed, rc=%d\n", progname, rc); fprintf(stderr, @@ -682,14 +624,14 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, * been plenty of time, the memory cell still doesn't match what * we wrote. Indicate a write error. */ - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); - LED_ON(fd, pgm->pinno[PIN_LED_ERR]); + pgm->pgm_led(pgm, OFF); + pgm->err_led(pgm, ON); return -6; } } - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); + pgm->pgm_led(pgm, OFF); return 0; } @@ -703,7 +645,8 @@ int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, * * Return the number of bytes written, or -1 if an error occurs. */ -int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose) +int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, + int verbose) { int rc; int wsize; @@ -720,7 +663,7 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose) return -1; } - LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + pgm->err_led(pgm, OFF); printed = 0; werror = 0; @@ -745,11 +688,11 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose) printed = 1; } } - rc = avr_write_byte(fd, p, m, i, data); + rc = avr_write_byte(pgm, p, m, i, data); if (rc) { fprintf(stderr, " ***failed; "); fprintf(stderr, "\n"); - LED_ON(fd, pgm->pinno[PIN_LED_ERR]); + pgm->err_led(pgm, ON); werror = 1; } @@ -760,7 +703,7 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose) */ if (((i % m->page_size) == m->page_size-1) || (i == wsize-1)) { - rc = avr_write_page(fd, p, m, i); + rc = avr_write_page(pgm, p, m, i); if (rc) { fprintf(stderr, " *** page %ld (addresses 0x%04lx - 0x%04lx) failed " @@ -768,7 +711,7 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose) i % m->page_size, i - m->page_size + 1, i); fprintf(stderr, "\n"); - LED_ON(fd, pgm->pinno[PIN_LED_ERR]); + pgm->err_led(pgm, ON); werror = 1; } } @@ -779,7 +722,7 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose) * make sure the error led stay on if there was a previous write * error, otherwise it gets cleared in avr_write_byte() */ - LED_ON(fd, pgm->pinno[PIN_LED_ERR]); + pgm->err_led(pgm, ON); } } @@ -790,93 +733,15 @@ int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose) } -/* - * issue the 'program enable' command to the AVR device - */ -int avr_program_enable(int fd, AVRPART * p) -{ - 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 -2; - - return 0; -} - - -/* - * issue the 'chip erase' command to the AVR device - */ -int avr_chip_erase(int fd, AVRPART * p) -{ - unsigned char cmd[4]; - unsigned char res[4]; - int cycles; - int rc; - - if (p->op[AVR_OP_CHIP_ERASE] == NULL) { - fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n", - p->desc); - return -1; - } - - rc = avr_get_cycle_count(fd, p, &cycles); - - /* - * only print out the current cycle count if we aren't going to - * display it below - */ - if (!do_cycles && ((rc >= 0) && (cycles != 0xffffffff))) { - fprintf(stderr, - "%s: current erase-rewrite cycle count is %d%s\n", - progname, cycles, - do_cycles ? "" : " (if being tracked)"); - } - - LED_ON(fd, pgm->pinno[PIN_LED_PGM]); - - 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); - - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); - - if (do_cycles && (cycles != -1)) { - if (cycles == 0x00ffff) { - cycles = 0; - } - cycles++; - fprintf(stderr, "%s: erase-rewrite cycle count is now %d\n", - progname, cycles); - avr_put_cycle_count(fd, p, cycles); - } - - return 0; -} - /* * read the AVR device's signature bytes */ -int avr_signature(int fd, AVRPART * p) +int avr_signature(PROGRAMMER * pgm, AVRPART * p) { int rc; - rc = avr_read(fd, p, "signature", 0, 0); + rc = avr_read(pgm, p, "signature", 0, 0); if (rc < 0) { fprintf(stderr, "%s: error reading signature data for part \"%s\", rc=%d\n", @@ -888,78 +753,6 @@ int avr_signature(int fd, AVRPART * p) } -/* - * apply power to the AVR processor - */ -void avr_powerup(int fd) -{ - ppi_set(fd, PPIDATA, pgm->pinno[PPI_AVR_VCC]); /* power up */ - usleep(100000); -} - - -/* - * remove power from the AVR processor - */ -void avr_powerdown(int fd) -{ - ppi_clr(fd, PPIDATA, pgm->pinno[PPI_AVR_VCC]); /* power down */ -} - - -/* - * initialize the AVR device and prepare it to accept commands - */ -int avr_initialize(int fd, AVRPART * p) -{ - int rc; - int tries; - - avr_powerup(fd); - usleep(20000); - - ppi_setpin(fd, pgm->pinno[PIN_AVR_SCK], 0); - ppi_setpin(fd, pgm->pinno[PIN_AVR_RESET], 0); - usleep(20000); - - ppi_pulsepin(fd, pgm->pinno[PIN_AVR_RESET]); - - usleep(20000); /* 20 ms XXX should be a per-chip parameter */ - - /* - * Enable programming mode. If we are programming an AT90S1200, we - * can only issue the command and hope it worked. If we are using - * one of the other chips, the chip will echo 0x53 when issuing the - * third byte of the command. In this case, try up to 32 times in - * order to possibly get back into sync with the chip if we are out - * of sync. - */ - if (strcmp(p->desc, "AT90S1200")==0) { - avr_program_enable(fd, p); - } - else { - tries = 0; - do { - rc = avr_program_enable(fd, p); - if ((rc == 0)||(rc == -1)) - break; - ppi_pulsepin(fd, pgm->pinno[PIN_AVR_SCK]); - tries++; - } while (tries < 65); - - /* - * can't sync with the device, maybe it's not attached? - */ - if (rc) { - fprintf(stderr, "%s: AVR device not responding\n", progname); - return -1; - } - } - - return 0; -} - - /* * Allocate and initialize memory buffers for each of the device's * defined memory regions. @@ -1043,7 +836,7 @@ int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size) } -int avr_get_cycle_count(int fd, AVRPART * p, int * cycles) +int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles) { AVRMEM * a; int cycle_count; @@ -1055,28 +848,28 @@ int avr_get_cycle_count(int fd, AVRPART * p, int * cycles) return -1; } - rc = avr_read_byte(fd, p, a, a->size-4, &v1); + rc = avr_read_byte(pgm, p, a, a->size-4, &v1); if (rc < 0) { fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n", progname, rc); return -1; } - rc = avr_read_byte(fd, p, a, a->size-3, &v2); + rc = avr_read_byte(pgm, p, a, a->size-3, &v2); if (rc < 0) { fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n", progname, rc); return -1; } - rc = avr_read_byte(fd, p, a, a->size-2, &v3); + rc = avr_read_byte(pgm, p, a, a->size-2, &v3); if (rc < 0) { fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n", progname, rc); return -1; } - rc = avr_read_byte(fd, p, a, a->size-1, &v4); + rc = avr_read_byte(pgm, p, a, a->size-1, &v4); if (rc < 0) { fprintf(stderr, "%s: WARNING: can't read memory for cycle count, rc=%d\n", progname, rc); @@ -1099,7 +892,7 @@ int avr_get_cycle_count(int fd, AVRPART * p, int * cycles) } -int avr_put_cycle_count(int fd, AVRPART * p, int cycles) +int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles) { AVRMEM * a; unsigned char v1, v2, v3, v4; @@ -1115,25 +908,25 @@ int avr_put_cycle_count(int fd, AVRPART * p, int cycles) v2 = (cycles & 0x0ff0000) >> 16; v1 = (cycles & 0x0ff000000) >> 24; - rc = avr_write_byte(fd, p, a, a->size-4, v1); + rc = avr_write_byte(pgm, p, a, a->size-4, v1); if (rc < 0) { fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n", progname, rc); return -1; } - rc = avr_write_byte(fd, p, a, a->size-3, v2); + rc = avr_write_byte(pgm, p, a, a->size-3, v2); if (rc < 0) { fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n", progname, rc); return -1; } - rc = avr_write_byte(fd, p, a, a->size-2, v3); + rc = avr_write_byte(pgm, p, a, a->size-2, v3); if (rc < 0) { fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n", progname, rc); return -1; } - rc = avr_write_byte(fd, p, a, a->size-1, v4); + rc = avr_write_byte(pgm, p, a, a->size-1, v4); if (rc < 0) { fprintf(stderr, "%s: WARNING: can't write memory for cycle count, rc=%d\n", progname, rc); diff --git a/avr.h b/avr.h index 489439e2..c48f1cfa 100644 --- a/avr.h +++ b/avr.h @@ -34,48 +34,9 @@ #include +#include "avrpart.h" #include "lists.h" - - -/* - * AVR serial programming instructions - */ -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 -}; - - -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; +#include "pgm.h" #define AVR_MEMDESCLEN 64 @@ -97,18 +58,6 @@ typedef struct avrmem { } AVRMEM; -#define AVR_DESCLEN 64 -#define AVR_IDLEN 32 -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 */ - - LISTID mem; /* avr memory definitions */ -} AVRPART; - - extern struct avrpart parts[]; @@ -129,32 +78,24 @@ 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]); +int avr_set_bits(OPCODE * op, unsigned char * cmd); -int avr_read_byte(int fd, AVRPART * p, AVRMEM * mem, unsigned long addr, - unsigned char * value); +int avr_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, + unsigned long addr, unsigned char * value); -int avr_read(int fd, AVRPART * p, char * memtype, int size, int verbose); +int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, + int verbose); -int avr_write_page(int fd, AVRPART * p, AVRMEM * mem, +int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsigned long addr); -int avr_write_byte(int fd, AVRPART * p, AVRMEM * mem, +int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsigned long addr, unsigned char data); -int avr_write(int fd, AVRPART * p, char * memtype, int size, int verbose); +int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, + int verbose); -int avr_program_enable(int fd, AVRPART * p); - -int avr_chip_erase(int fd, AVRPART * p); - -int avr_signature(int fd, AVRPART * p); - -void avr_powerup(int fd); - -void avr_powerdown(int fd); - -int avr_initialize(int fd, AVRPART * p); +int avr_signature(PROGRAMMER * pgm, AVRPART * p); char * avr_memtstr(int memtype); @@ -167,8 +108,8 @@ void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type, void avr_display(FILE * f, AVRPART * p, char * prefix, int verbose); -int avr_get_cycle_count(int fd, AVRPART * p, int * cycles); +int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles); -int avr_put_cycle_count(int fd, AVRPART * p, int cycles); +int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles);; #endif diff --git a/avrdude.conf.sample b/avrdude.conf.sample index 3ac84609..5ff61e08 100644 --- a/avrdude.conf.sample +++ b/avrdude.conf.sample @@ -110,6 +110,7 @@ programmer id = "bsd", "default"; desc = "Brian Dean's Programmer"; + type = ppi; vcc = 2, 3, 4, 5; reset = 7; sck = 8; @@ -120,6 +121,7 @@ programmer programmer id = "stk200"; desc = "STK200"; + type = ppi; buff = 4, 5; sck = 6; mosi = 7; @@ -130,6 +132,7 @@ programmer programmer id = "dt006"; desc = "Dontronics DT006"; + type = ppi; reset = 4; sck = 5; mosi = 2; @@ -139,6 +142,7 @@ programmer programmer id = "alf"; desc = "Tony Friebel's Programmer"; + type = ppi; vcc = 2, 3, 4, 5; buff = 6; reset = 7; diff --git a/config.c b/config.c index adca8159..aeaf307f 100644 --- a/config.c +++ b/config.c @@ -274,29 +274,6 @@ void pyytext(void) } -PROGRAMMER * new_programmer(void) -{ - PROGRAMMER * p; - int i; - - p = (PROGRAMMER *)malloc(sizeof(PROGRAMMER)); - if (p == NULL) { - fprintf(stderr, "new_programmer(): out of memory\n"); - exit(1); - } - - memset(p, 0, sizeof(*p)); - - p->id = lcreat(NULL, 0); - p->desc[0] = 0; - - for (i=0; ipinno[i] = 0; - - return p; -} - - char * dup_string(char * str) { char * s; diff --git a/config.h b/config.h index 8b39b95f..544a1677 100644 --- a/config.h +++ b/config.h @@ -53,13 +53,6 @@ typedef struct token_t { } TOKEN; -#define PGM_DESCLEN 80 -typedef struct programmer_t { - LISTID id; - char desc[PGM_DESCLEN]; - unsigned int pinno[N_PINS]; -} PROGRAMMER; - extern FILE * yyin; extern PROGRAMMER * current_prog; extern AVRPART * current_part; diff --git a/config_gram.y b/config_gram.y index 1b0a1d7f..d800c932 100644 --- a/config_gram.y +++ b/config_gram.y @@ -60,8 +60,9 @@ %token K_NUM_PAGES %token K_PART %token K_PGMLED -%token K_PWROFF_AFTER_WRITE +%token K_PPI %token K_PROGRAMMER +%token K_PWROFF_AFTER_WRITE %token K_RDYLED %token K_READBACK_P1 %token K_READBACK_P2 @@ -69,6 +70,8 @@ %token K_RESET %token K_SCK %token K_SIZE +%token K_STK500 +%token K_TYPE %token K_VCC %token K_VFYLED %token K_WRITEPAGE @@ -102,7 +105,7 @@ def : prog_def : K_PROGRAMMER - { current_prog = new_programmer(); } + { current_prog = pgm_new(); } prog_parms { if (lsize(current_prog->id) == 0) { @@ -111,6 +114,11 @@ prog_def : progname, infile, lineno); exit(1); } + if (current_prog->type[0] == 0) { + fprintf(stderr, "%s: error at %s:%d: programmer type not specified\n", + progname, infile, lineno); + exit(1); + } ladd(programmers, current_prog); current_prog = NULL; } @@ -205,6 +213,18 @@ prog_parm : } } | + K_TYPE TKN_EQUAL K_PPI { + { + ppi_initpgm(current_prog); + } + } | + + K_TYPE TKN_EQUAL K_STK500 { + { + fprintf(stderr, "%s: programmer 'stk500' not yet supported\n", progname); + } + } | + K_DESC TKN_EQUAL TKN_STRING { strncpy(current_prog->desc, $3->value.string, PGM_DESCLEN); current_prog->desc[PGM_DESCLEN-1] = 0; @@ -441,6 +461,7 @@ mem_spec : #include "config.h" #include "lists.h" #include "pindefs.h" +#include "pgm.h" #include "avr.h" extern char * progname; diff --git a/lexer.l b/lexer.l index 6d81fbb5..5acf8b81 100644 --- a/lexer.l +++ b/lexer.l @@ -142,14 +142,17 @@ page_size { yylval=NULL; return K_PAGE_SIZE; } paged { yylval=NULL; return K_PAGED; } part { yylval=NULL; return K_PART; } pgmled { yylval=NULL; return K_PGMLED; } -pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; } +ppi { yylval=NULL; return K_PPI; } programmer { yylval=NULL; return K_PROGRAMMER; } +pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; } rdyled { yylval=NULL; return K_RDYLED; } readback_p1 { yylval=NULL; return K_READBACK_P1; } readback_p2 { yylval=NULL; return K_READBACK_P2; } reset { yylval=NULL; return K_RESET; } sck { yylval=NULL; return K_SCK; } size { yylval=NULL; return K_SIZE; } +stk500 { yylval=NULL; return K_STK500; } +type { yylval=NULL; return K_TYPE; } vcc { yylval=NULL; return K_VCC; } vfyled { yylval=NULL; return K_VFYLED; } diff --git a/main.c b/main.c index 4e15d7fd..23c83b39 100644 --- a/main.c +++ b/main.c @@ -94,16 +94,18 @@ #define DEFAULT_PARALLEL "/dev/ppi0" +#define DEFAULT_SERIAL "/dev/cuaa0" extern char * avr_version; extern char * config_version; extern char * fileio_version; extern char * lists_version; extern char * main_version; +extern char * pgm_version; extern char * ppi_version; extern char * term_version; -#define N_MODULES 7 +#define N_MODULES 8 char ** modules[N_MODULES] = { &avr_version, @@ -111,6 +113,7 @@ char ** modules[N_MODULES] = { &fileio_version, &lists_version, &main_version, + &pgm_version, &ppi_version, &term_version }; @@ -126,7 +129,7 @@ char progbuf[PATH_MAX]; /* temporary buffer of spaces the same PROGRAMMER * pgm = NULL; -PROGRAMMER compiled_in_pgm; +PROGRAMMER * compiled_in_pgm; /* * global options @@ -142,7 +145,7 @@ void usage(void) fprintf(stderr, "\nUsage: %s -p partno [-e] [-E exitspec[,exitspec]] [-f format] " "[-F]\n" - " %s[-i filename] [-m memtype] [-o filename] [-P parallel] " + " %s[-i filename] [-m memtype] [-o filename] [-P port] " "[-t]\n" " %s[-c programmer] [-C config-file] [-v [-v]] [-n]\n\n", progname, progbuf, progbuf); @@ -306,75 +309,11 @@ int read_config(char * file) -static char vccpins_buf[64]; -char * vccpins_str(unsigned int pmask) -{ - unsigned int mask; - int pin; - char b2[8]; - char * b; - - b = vccpins_buf; - - b[0] = 0; - for (pin = 2, mask = 1; mask < 0x80; mask = mask << 1, pin++) { - if (pmask & mask) { - sprintf(b2, "%d", pin); - if (b[0] != 0) - strcat(b, ","); - strcat(b, b2); - } - } - - return b; -} - - void pinconfig_display(char * p) { - char vccpins[64]; - char buffpins[64]; + fprintf(stderr, "%sProgrammer Type: %s\n", p, pgm->type); - if (pgm->pinno[PPI_AVR_VCC]) { - snprintf(vccpins, sizeof(vccpins), " = pins %s", - vccpins_str(pgm->pinno[PPI_AVR_VCC])); - } - else { - strcpy(vccpins, " (not used)"); - } - - if (pgm->pinno[PPI_AVR_BUFF]) { - snprintf(buffpins, sizeof(buffpins), " = pins %s", - vccpins_str(pgm->pinno[PPI_AVR_BUFF])); - } - else { - strcpy(buffpins, " (not used)"); - } - - fprintf(stderr, "%sProgrammer Pin Configuration: %s (%s)\n", p, - (char *)ldata(lfirst(pgm->id)), pgm->desc); - - fprintf(stderr, - "%s VCC = 0x%02x%s\n" - "%s BUFF = 0x%02x%s\n" - "%s RESET = %d\n" - "%s SCK = %d\n" - "%s MOSI = %d\n" - "%s MISO = %d\n" - "%s ERR LED = %d\n" - "%s RDY LED = %d\n" - "%s PGM LED = %d\n" - "%s VFY LED = %d\n", - p, pgm->pinno[PPI_AVR_VCC], vccpins, - p, pgm->pinno[PPI_AVR_BUFF], buffpins, - p, pgm->pinno[PIN_AVR_RESET], - p, pgm->pinno[PIN_AVR_SCK], - p, pgm->pinno[PIN_AVR_MOSI], - p, pgm->pinno[PIN_AVR_MISO], - p, pgm->pinno[PIN_LED_ERR], - p, pgm->pinno[PIN_LED_RDY], - p, pgm->pinno[PIN_LED_PGM], - p, pgm->pinno[PIN_LED_VFY]); + pgm->display(pgm, p); } @@ -457,7 +396,6 @@ void list_parts(FILE * f, char * prefix, LISTID parts) */ int main(int argc, char * argv []) { - int fd; /* file descriptor for parallel port */ int rc; /* general return code checking */ int exitrc; /* exit code for main() */ int i; /* general loop counter */ @@ -479,7 +417,7 @@ int main(int argc, char * argv []) char * outputf; /* output file name */ char * inputf; /* input file name */ int ovsigck; /* 1=override sig check, 0=don't */ - char * parallel; /* parallel port device */ + char * port; /* device port (/dev/xxx) */ int terminal; /* 1=enter terminal mode, 0=don't */ FILEFMT filefmt; /* FMT_AUTO, FMT_IHEX, FMT_SREC, FMT_RBIN */ int nowrite; /* don't actually write anything to the chip */ @@ -505,7 +443,7 @@ int main(int argc, char * argv []) partdesc = NULL; readorwrite = 0; - parallel = DEFAULT_PARALLEL; + port = DEFAULT_PARALLEL; outputf = NULL; inputf = NULL; doread = 1; @@ -535,12 +473,11 @@ int main(int argc, char * argv []) /* * initialize compiled-in default programmer */ - pgm = &compiled_in_pgm; - pgm->id = lcreat(NULL, 0); + compiled_in_pgm = pgm_new(); + pgm = compiled_in_pgm; + ppi_initpgm(pgm); ladd(pgm->id, dup_string("avrprog")); strcpy(pgm->desc, "avrprog compiled-in default"); - for (i=0; ipinno[i] = 0; pgm->pinno[PPI_AVR_VCC] = 0x0f; /* ppi pins 2-5, data reg bits 0-3 */ pgm->pinno[PPI_AVR_BUFF] = 0; pgm->pinno[PIN_AVR_RESET] = 7; @@ -674,7 +611,7 @@ int main(int argc, char * argv []) break; case 'P': - parallel = optarg; + port = optarg; break; case 'v': @@ -739,7 +676,7 @@ int main(int argc, char * argv []) pgm = locate_pinconfig(programmers, "default"); if (pgm == NULL) { /* no default config listed, use the compile-in default */ - pgm = &compiled_in_pgm; + pgm = compiled_in_pgm; } } else { @@ -776,7 +713,14 @@ int main(int argc, char * argv []) if (exitspecs != NULL) { - if (getexitspecs(exitspecs, &ppisetbits, &ppiclrbits) < 0) { + if (strcmp(pgm->type, "PPI") != 0) { + fprintf(stderr, + "%s: WARNING: -E option is only valid with \"PPI\" " + "programmer types\n", + progname); + exitspecs = NULL; + } + else if (getexitspecs(exitspecs, &ppisetbits, &ppiclrbits) < 0) { usage(); exit(1); } @@ -799,70 +743,50 @@ int main(int argc, char * argv []) fprintf(stderr, "\n"); - verify_pin_assigned(PIN_AVR_RESET, "AVR RESET"); - verify_pin_assigned(PIN_AVR_SCK, "AVR SCK"); - verify_pin_assigned(PIN_AVR_MISO, "AVR MISO"); - verify_pin_assigned(PIN_AVR_MOSI, "AVR MOSI"); + if (strcmp(pgm->type, "PPI") == 0) { + verify_pin_assigned(PIN_AVR_RESET, "AVR RESET"); + verify_pin_assigned(PIN_AVR_SCK, "AVR SCK"); + verify_pin_assigned(PIN_AVR_MISO, "AVR MISO"); + verify_pin_assigned(PIN_AVR_MOSI, "AVR MOSI"); + } /* - * open the parallel port + * open the programmer */ - fd = open(parallel, O_RDWR); - if (fd < 0) { - fprintf(stderr, "%s: can't open device \"%s\": %s\n\n", - progname, parallel, strerror(errno)); - return 1; - } + pgm->open(pgm, port); exitrc = 0; -#if 0 - ppi_sense(fd); -#endif - - ppidata = ppi_getall(fd, PPIDATA); - if (ppidata < 0) { - fprintf(stderr, "%s: error reading status of ppi data port\n", progname); + rc = pgm->save(pgm); + if (rc < 0) { exitrc = 1; ppidata = 0; /* clear all bits at exit */ goto main_exit; } - ppidata &= ~ppiclrbits; - ppidata |= ppisetbits; + if (strcmp(pgm->type, "PPI") == 0) { + pgm->ppidata &= ~ppiclrbits; + pgm->ppidata |= ppisetbits; + } - /* + + /* + * enable the programmer + */ + pgm->enable(pgm); + + /* * turn off all the status leds */ - LED_OFF(fd, pgm->pinno[PIN_LED_RDY]); - LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); - LED_OFF(fd, pgm->pinno[PIN_LED_PGM]); - LED_OFF(fd, pgm->pinno[PIN_LED_VFY]); - - - /* - * Prepare to start talking to the connected device - pull reset low - * first, delay a few milliseconds, then enable the buffer. This - * sequence allows the AVR to be reset before the buffer is enabled - * to avoid a short period of time where the AVR may be driving the - * programming lines at the same time the programmer tries to. Of - * course, if a buffer is being used, then the /RESET line from the - * programmer needs to be directly connected to the AVR /RESET line - * and not via the buffer chip. - */ - - ppi_setpin(fd, pgm->pinno[PIN_AVR_RESET], 0); - usleep(1); - - /* - * enable the 74367 buffer, if connected; this signal is active low - */ - ppi_clr(fd, PPIDATA, pgm->pinno[PPI_AVR_BUFF]); + pgm->rdy_led(pgm, OFF); + pgm->err_led(pgm, OFF); + pgm->pgm_led(pgm, OFF); + pgm->vfy_led(pgm, OFF); /* * initialize the chip in preperation for accepting commands */ - rc = avr_initialize(fd,p); + rc = pgm->initialize(pgm, p); if (rc < 0) { fprintf(stderr, "%s: initialization failed, rc=%d\n", progname, rc); exitrc = 1; @@ -870,7 +794,7 @@ int main(int argc, char * argv []) } /* indicate ready */ - LED_ON(fd, pgm->pinno[PIN_LED_RDY]); + pgm->rdy_led(pgm, ON); fprintf(stderr, "%s: AVR device initialized and ready to accept instructions\n", @@ -882,7 +806,7 @@ int main(int argc, char * argv []) * against 0xffffffff should ensure that the signature bytes are * valid. */ - rc = avr_signature(fd, p); + rc = avr_signature(pgm, p); if (rc != 0) { fprintf(stderr, "%s: error reading signature data, rc=%d\n", progname, rc); @@ -923,7 +847,7 @@ int main(int argc, char * argv []) } if (set_cycles != -1) { - rc = avr_get_cycle_count(fd, p, &cycles); + rc = avr_get_cycle_count(pgm, p, &cycles); if (rc == 0) { /* * only attempt to update the cycle counter if we can actually @@ -932,7 +856,7 @@ int main(int argc, char * argv []) cycles = set_cycles; fprintf(stderr, "%s: setting erase-rewrite cycle count to %d\n", progname, cycles); - rc = avr_put_cycle_count(fd, p, cycles); + rc = avr_put_cycle_count(pgm, p, cycles); if (rc < 0) { fprintf(stderr, "%s: WARNING: failed to update the erase-rewrite cycle " @@ -948,7 +872,7 @@ int main(int argc, char * argv []) * before the chip can accept new programming */ fprintf(stderr, "%s: erasing chip\n", progname); - avr_chip_erase(fd,p); + pgm->chip_erase(pgm, p); fprintf(stderr, "%s: done.\n", progname); } else if (set_cycles == -1) { @@ -960,7 +884,7 @@ int main(int argc, char * argv []) * see if the cycle count in the last four bytes of eeprom seems * reasonable */ - rc = avr_get_cycle_count(fd, p, &cycles); + rc = avr_get_cycle_count(pgm, p, &cycles); if ((rc >= 0) && (cycles != 0xffffffff)) { fprintf(stderr, "%s: current erase-rewrite cycle count is %d%s\n", @@ -990,7 +914,7 @@ int main(int argc, char * argv []) /* * terminal mode */ - exitrc = terminal_mode(fd, p); + exitrc = terminal_mode(pgm, p); } else if (doread) { /* @@ -998,7 +922,7 @@ int main(int argc, char * argv []) */ fprintf(stderr, "%s: reading %s memory:\n", progname, memtype); - rc = avr_read(fd, p, memtype, 0, 1); + rc = avr_read(pgm, p, memtype, 0, 1); if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", progname, memtype, rc); @@ -1039,7 +963,7 @@ int main(int argc, char * argv []) progname, memtype, size); if (!nowrite) { - rc = avr_write(fd, p, memtype, size, 1); + rc = avr_write(pgm, p, memtype, size, 1); } else { /* @@ -1068,17 +992,17 @@ int main(int argc, char * argv []) * verify that the in memory file (p->mem[AVR_M_FLASH|AVR_M_EEPROM]) * is the same as what is on the chip */ - LED_ON(fd, pgm->pinno[PIN_LED_VFY]); + pgm->vfy_led(pgm, ON); fprintf(stderr, "%s: verifying %s memory against %s:\n", progname, memtype, inputf); fprintf(stderr, "%s: reading on-chip %s data:\n", progname, memtype); - rc = avr_read(fd, v, memtype, vsize, 1); + rc = avr_read(pgm, v, memtype, vsize, 1); if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", progname, memtype, rc); - LED_ON(fd, pgm->pinno[PIN_LED_ERR]); + pgm->err_led(pgm, ON); exitrc = 1; goto main_exit; } @@ -1088,7 +1012,7 @@ int main(int argc, char * argv []) if (rc < 0) { fprintf(stderr, "%s: verification error; content mismatch\n", progname); - LED_ON(fd, pgm->pinno[PIN_LED_ERR]); + pgm->err_led(pgm, ON); exitrc = 1; goto main_exit; } @@ -1096,7 +1020,7 @@ int main(int argc, char * argv []) fprintf(stderr, "%s: %d bytes of %s verified\n", progname, rc, memtype); - LED_OFF(fd, pgm->pinno[PIN_LED_VFY]); + pgm->vfy_led(pgm, OFF); } @@ -1107,19 +1031,15 @@ int main(int argc, char * argv []) * program complete */ - avr_powerdown(fd); + pgm->powerdown(pgm); - ppi_setall(fd, PPIDATA, ppidata); + pgm->restore(pgm); - /* - * disable the 74367 buffer, if connected; this signal is active low - */ - /* ppi_setpin(fd, pgm->pinno[PIN_AVR_BUFF], 1); */ - ppi_set(fd, PPIDATA, pgm->pinno[PPI_AVR_BUFF]); + pgm->disable(pgm); - LED_OFF(fd, pgm->pinno[PIN_LED_RDY]); + pgm->rdy_led(pgm, OFF); - close(fd); + pgm->close(pgm); fprintf(stderr, "\n%s done. Thank you.\n\n", progname); diff --git a/pgm.c b/pgm.c new file mode 100644 index 00000000..5d466338 --- /dev/null +++ b/pgm.c @@ -0,0 +1,135 @@ +/* + * Copyright 2002 Brian S. Dean + * 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$ */ + + +#include +#include + +#include "pgm.h" + +extern char * progname; + +int pgm_default_1 (struct programmer_t *, int); +int pgm_default_2 (struct programmer_t *, AVRPART *); +int pgm_default_3 (struct programmer_t *); +void pgm_default_4 (struct programmer_t *); +int pgm_default_5 (struct programmer_t *, unsigned char cmd[4], + unsigned char res[4]); +void pgm_default_6 (struct programmer_t *, char *); + +char * pgm_version = "$Id$"; + + +PROGRAMMER * pgm_new(void) +{ + int i; + PROGRAMMER * pgm; + + pgm = (PROGRAMMER *)malloc(sizeof(*pgm)); + if (pgm == NULL) { + fprintf(stderr, "%s: out of memory allocating programmer structure\n", + progname); + exit(1); + } + + memset(pgm, 0, sizeof(*pgm)); + + pgm->id = lcreat(NULL, 0); + pgm->desc[0] = 0; + pgm->type[0] = 0; + + for (i=0; ipinno[i] = 0; + + pgm->rdy_led = pgm_default_1; + pgm->err_led = pgm_default_1; + pgm->pgm_led = pgm_default_1; + pgm->vfy_led = pgm_default_1; + pgm->initialize = pgm_default_2; + pgm->display = pgm_default_6; + pgm->save = pgm_default_3; + pgm->restore = pgm_default_4; + pgm->enable = pgm_default_4; + pgm->disable = pgm_default_4; + pgm->powerup = pgm_default_4; + pgm->powerdown = pgm_default_4; + pgm->program_enable = pgm_default_2; + pgm->chip_erase = pgm_default_2; + pgm->cmd = pgm_default_5; + pgm->open = pgm_default_6; + pgm->close = pgm_default_4; + + return pgm; +} + + +void pgm_default(void) +{ + fprintf(stderr, "%s: programmer operation not supported\n", progname); +} + + +int pgm_default_1 (struct programmer_t * pgm, int value) +{ + pgm_default(); + return -1; +} + +int pgm_default_2 (struct programmer_t * pgm, AVRPART * p) +{ + pgm_default(); + return -1; +} + +int pgm_default_3 (struct programmer_t * pgm) +{ + pgm_default(); + return -1; +} + +void pgm_default_4 (struct programmer_t * pgm) +{ + pgm_default(); +} + +int pgm_default_5 (struct programmer_t * pgm, unsigned char cmd[4], + unsigned char res[4]) +{ + pgm_default(); + return -1; +} + +void pgm_default_6 (struct programmer_t * pgm, char * p) +{ + pgm_default(); +} + + diff --git a/pgm.h b/pgm.h new file mode 100644 index 00000000..9738c011 --- /dev/null +++ b/pgm.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2000, 2001, 2002 Brian S. Dean + * 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$ */ + +#ifndef __pgm_h__ +#define __pgm_h__ + +#include "avrpart.h" +#include "lists.h" +#include "pindefs.h" + + +#define ON 1 +#define OFF 0 + +#define PGM_DESCLEN 80 +#define PGM_TYPELEN 32 +typedef struct programmer_t { + LISTID id; + char desc[PGM_DESCLEN]; + char type[PGM_TYPELEN]; + unsigned int pinno[N_PINS]; + int ppidata; + int fd; + int (*rdy_led) (struct programmer_t * pgm, int value); + int (*err_led) (struct programmer_t * pgm, int value); + int (*pgm_led) (struct programmer_t * pgm, int value); + int (*vfy_led) (struct programmer_t * pgm, int value); + int (*initialize) (struct programmer_t * pgm, AVRPART * p); + void (*display) (struct programmer_t * pgm, char * p); + int (*save) (struct programmer_t * pgm); + void (*restore) (struct programmer_t * pgm); + void (*enable) (struct programmer_t * pgm); + void (*disable) (struct programmer_t * pgm); + void (*powerup) (struct programmer_t * pgm); + void (*powerdown) (struct programmer_t * pgm); + int (*program_enable) (struct programmer_t * pgm, AVRPART * p); + int (*chip_erase) (struct programmer_t * pgm, AVRPART * p); + int (*cmd) (struct programmer_t * pgm, unsigned char cmd[4], + unsigned char res[4]); + void (*open) (struct programmer_t * pgm, char * port); + void (*close) (struct programmer_t * pgm); +} PROGRAMMER; + + +PROGRAMMER * pgm_new(void); + +#endif diff --git a/ppi.c b/ppi.c index b4fbd77d..521f5e42 100644 --- a/ppi.c +++ b/ppi.c @@ -30,14 +30,21 @@ /* $Id$ */ #include +#include +#include #include +#include #include +#include "avr.h" +#include "pindefs.h" +#include "pgm.h" #include "ppi.h" #define SLOW_TOGGLE 0 extern char * progname; +extern int do_cycles; struct ppipins_t { int pin; @@ -71,6 +78,32 @@ static struct ppipins_t pins[] = { char * ppi_version = "$Id$"; + + +static char vccpins_buf[64]; +char * vccpins_str(unsigned int pmask) +{ + unsigned int mask; + int pin; + char b2[8]; + char * b; + + b = vccpins_buf; + + b[0] = 0; + for (pin = 2, mask = 1; mask < 0x80; mask = mask << 1, pin++) { + if (pmask & mask) { + sprintf(b2, "%d", pin); + if (b[0] != 0) + strcat(b, ","); + strcat(b, b2); + } + } + + return b; +} + + /* * set 'get' and 'set' appropriately for subsequent passage to ioctl() * to get/set the specified PPI registers. @@ -367,3 +400,383 @@ int ppi_sense(int fd) } + + +/* + * transmit and receive a byte of data to/from the AVR device + */ +unsigned char ppi_txrx(PROGRAMMER * pgm, unsigned char byte) +{ + int i; + unsigned char r, b, rbyte; + + rbyte = 0; + for (i=0; i<8; i++) { + b = (byte >> (7-i)) & 0x01; + + /* + * read the result bit (it is either valid from a previous clock + * pulse or it is ignored in the current context) + */ + r = ppi_getpin(pgm->fd, pgm->pinno[PIN_AVR_MISO]); + + /* set the data input line as desired */ + ppi_setpin(pgm->fd, pgm->pinno[PIN_AVR_MOSI], b); + + /* + * pulse the clock line, clocking in the MOSI data, and clocking out + * the next result bit + */ + ppi_pulsepin(pgm->fd, pgm->pinno[PIN_AVR_SCK]); + + rbyte = rbyte | (r << (7-i)); + } + + return rbyte; +} + + + + + +int ppi_rdy_led(PROGRAMMER * pgm, int value) +{ + ppi_setpin(pgm->fd, pgm->pinno[PIN_LED_RDY], !value); + return 0; +} + +int ppi_err_led(PROGRAMMER * pgm, int value) +{ + ppi_setpin(pgm->fd, pgm->pinno[PIN_LED_ERR], !value); + return 0; +} + +int ppi_pgm_led(PROGRAMMER * pgm, int value) +{ + ppi_setpin(pgm->fd, pgm->pinno[PIN_LED_PGM], !value); + return 0; +} + +int ppi_vfy_led(PROGRAMMER * pgm, int value) +{ + ppi_setpin(pgm->fd, pgm->pinno[PIN_LED_VFY], !value); + return 0; +} + + +/* + * transmit an AVR device command and return the results; 'cmd' and + * 'res' must point to at least a 4 byte data buffer + */ +int ppi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]) +{ + int i; + + for (i=0; i<4; i++) { + res[i] = ppi_txrx(pgm, cmd[i]); + } + +#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; +} + + +/* + * issue the 'chip erase' command to the AVR device + */ +int ppi_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char cmd[4]; + unsigned char res[4]; + int cycles; + int rc; + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) { + fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + + rc = avr_get_cycle_count(pgm, p, &cycles); + + /* + * only print out the current cycle count if we aren't going to + * display it below + */ + if (!do_cycles && ((rc >= 0) && (cycles != 0xffffffff))) { + fprintf(stderr, + "%s: current erase-rewrite cycle count is %d%s\n", + progname, cycles, + do_cycles ? "" : " (if being tracked)"); + } + + pgm->pgm_led(pgm, ON); + + memset(cmd, 0, sizeof(cmd)); + + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); + pgm->cmd(pgm, cmd, res); + usleep(p->chip_erase_delay); + pgm->initialize(pgm, p); + + pgm->pgm_led(pgm, OFF); + + if (do_cycles && (cycles != -1)) { + if (cycles == 0x00ffff) { + cycles = 0; + } + cycles++; + fprintf(stderr, "%s: erase-rewrite cycle count is now %d\n", + progname, cycles); + avr_put_cycle_count(pgm, p, cycles); + } + + return 0; +} + +/* + * issue the 'program enable' command to the AVR device + */ +int ppi_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + 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); + pgm->cmd(pgm, cmd, res); + + if (res[2] != cmd[1]) + return -2; + + return 0; +} + + +/* + * apply power to the AVR processor + */ +void ppi_powerup(PROGRAMMER * pgm) +{ + ppi_set(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_VCC]); /* power up */ + usleep(100000); +} + + +/* + * remove power from the AVR processor + */ +void ppi_powerdown(PROGRAMMER * pgm) +{ + ppi_clr(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_VCC]); /* power down */ +} + + +/* + * initialize the AVR device and prepare it to accept commands + */ +int ppi_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + int rc; + int tries; + + pgm->powerup(pgm); + usleep(20000); + + ppi_setpin(pgm->fd, pgm->pinno[PIN_AVR_SCK], 0); + ppi_setpin(pgm->fd, pgm->pinno[PIN_AVR_RESET], 0); + usleep(20000); + + ppi_pulsepin(pgm->fd, pgm->pinno[PIN_AVR_RESET]); + + usleep(20000); /* 20 ms XXX should be a per-chip parameter */ + + /* + * Enable programming mode. If we are programming an AT90S1200, we + * can only issue the command and hope it worked. If we are using + * one of the other chips, the chip will echo 0x53 when issuing the + * third byte of the command. In this case, try up to 32 times in + * order to possibly get back into sync with the chip if we are out + * of sync. + */ + if (strcmp(p->desc, "AT90S1200")==0) { + pgm->program_enable(pgm, p); + } + else { + tries = 0; + do { + rc = pgm->program_enable(pgm, p); + if ((rc == 0)||(rc == -1)) + break; + ppi_pulsepin(pgm->fd, pgm->pinno[PIN_AVR_SCK]); + tries++; + } while (tries < 65); + + /* + * can't sync with the device, maybe it's not attached? + */ + if (rc) { + fprintf(stderr, "%s: AVR device not responding\n", progname); + return -1; + } + } + + return 0; +} + + +int ppi_save(PROGRAMMER * pgm) +{ + int rc; + + rc = ppi_getall(pgm->fd, PPIDATA); + if (rc < 0) { + fprintf(stderr, "%s: error reading status of ppi data port\n", progname); + return -1; + } + + pgm->ppidata = rc; + + return 0; +} + +void ppi_restore(PROGRAMMER * pgm) +{ + ppi_setall(pgm->fd, PPIDATA, pgm->ppidata); +} + +void ppi_disable(PROGRAMMER * pgm) +{ + ppi_set(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_BUFF]); +} + +void ppi_enable(PROGRAMMER * pgm) +{ + /* + * Prepare to start talking to the connected device - pull reset low + * first, delay a few milliseconds, then enable the buffer. This + * sequence allows the AVR to be reset before the buffer is enabled + * to avoid a short period of time where the AVR may be driving the + * programming lines at the same time the programmer tries to. Of + * course, if a buffer is being used, then the /RESET line from the + * programmer needs to be directly connected to the AVR /RESET line + * and not via the buffer chip. + */ + + ppi_setpin(pgm->fd, pgm->pinno[PIN_AVR_RESET], 0); + usleep(1); + + /* + * enable the 74367 buffer, if connected; this signal is active low + */ + ppi_clr(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_BUFF]); +} + + +void ppi_open(PROGRAMMER * pgm, char * port) +{ + pgm->fd = open(port, O_RDWR); + if (pgm->fd < 0) { + fprintf(stderr, "%s: can't open device \"%s\": %s\n\n", + progname, port, strerror(errno)); + exit(1); + } +} + + +void ppi_close(PROGRAMMER * pgm) +{ + close(pgm->fd); + pgm->fd = -1; +} + + +void ppi_display(PROGRAMMER * pgm, char * p) +{ + char vccpins[64]; + char buffpins[64]; + + if (pgm->pinno[PPI_AVR_VCC]) { + snprintf(vccpins, sizeof(vccpins), " = pins %s", + vccpins_str(pgm->pinno[PPI_AVR_VCC])); + } + else { + strcpy(vccpins, " (not used)"); + } + + if (pgm->pinno[PPI_AVR_BUFF]) { + snprintf(buffpins, sizeof(buffpins), " = pins %s", + vccpins_str(pgm->pinno[PPI_AVR_BUFF])); + } + else { + strcpy(buffpins, " (not used)"); + } + + + fprintf(stderr, "%sProgrammer Pin Configuration: %s (%s)\n", p, + (char *)ldata(lfirst(pgm->id)), pgm->desc); + + fprintf(stderr, + "%s VCC = 0x%02x%s\n" + "%s BUFF = 0x%02x%s\n" + "%s RESET = %d\n" + "%s SCK = %d\n" + "%s MOSI = %d\n" + "%s MISO = %d\n" + "%s ERR LED = %d\n" + "%s RDY LED = %d\n" + "%s PGM LED = %d\n" + "%s VFY LED = %d\n", + + p, pgm->pinno[PPI_AVR_VCC], vccpins, + p, pgm->pinno[PPI_AVR_BUFF], buffpins, + p, pgm->pinno[PIN_AVR_RESET], + p, pgm->pinno[PIN_AVR_SCK], + p, pgm->pinno[PIN_AVR_MOSI], + p, pgm->pinno[PIN_AVR_MISO], + p, pgm->pinno[PIN_LED_ERR], + p, pgm->pinno[PIN_LED_RDY], + p, pgm->pinno[PIN_LED_PGM], + p, pgm->pinno[PIN_LED_VFY]); +} + + +void ppi_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "PPI"); + + pgm->rdy_led = ppi_rdy_led; + pgm->err_led = ppi_err_led; + pgm->pgm_led = ppi_pgm_led; + pgm->vfy_led = ppi_vfy_led; + pgm->initialize = ppi_initialize; + pgm->display = ppi_display; + pgm->save = ppi_save; + pgm->restore = ppi_restore; + pgm->enable = ppi_enable; + pgm->disable = ppi_disable; + pgm->powerup = ppi_powerup; + pgm->powerdown = ppi_powerdown; + pgm->program_enable = ppi_program_enable; + pgm->chip_erase = ppi_chip_erase; + pgm->cmd = ppi_cmd; + pgm->open = ppi_open; + pgm->close = ppi_close; +} + + diff --git a/ppi.h b/ppi.h index 45ffc433..9b2a3bf8 100644 --- a/ppi.h +++ b/ppi.h @@ -32,6 +32,9 @@ #ifndef __ppi_h__ #define __ppi_h__ +#include "config.h" + + /* * PPI registers */ @@ -69,6 +72,47 @@ int ppi_getpinreg (int pin); int ppi_sense (int fd); + +void ppi_initpgm (PROGRAMMER * pgm); + + +int ppi_rdy_led (PROGRAMMER * pgm, int value); + +int ppi_err_led (PROGRAMMER * pgm, int value); + +int ppi_pgm_led (PROGRAMMER * pgm, int value); + +int ppi_vfy_led (PROGRAMMER * pgm, int value); + +int ppi_cmd (PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]); + +int ppi_chip_erase (PROGRAMMER * pgm, AVRPART * p); + +int ppi_program_enable (PROGRAMMER * pgm, AVRPART * p); + +void ppi_powerup (PROGRAMMER * pgm); + +void ppi_powerdown (PROGRAMMER * pgm); + +int ppi_initialize (PROGRAMMER * pgm, AVRPART * p); + +int ppi_save (PROGRAMMER * pgm); + +void ppi_restore (PROGRAMMER * pgm); + +void ppi_disable (PROGRAMMER * pgm); + +void ppi_enable (PROGRAMMER * pgm); + +void ppi_open (PROGRAMMER * pgm, char * port); + +void ppi_close (PROGRAMMER * pgm); + +void ppi_initpgm (PROGRAMMER * pgm); + + + #endif diff --git a/term.c b/term.c index 9952fab7..4925329e 100644 --- a/term.c +++ b/term.c @@ -39,6 +39,7 @@ #include "avr.h" #include "config.h" #include "lists.h" +#include "pgm.h" #include "pindefs.h" #include "ppi.h" @@ -50,28 +51,28 @@ extern PROGRAMMER * pgm; struct command { char * name; - int (*func)(int fd, struct avrpart * p, int argc, char *argv[]); + int (*func)(PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); char * desc; }; char * term_version = "$Id$"; -int cmd_dump (int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_dump (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); -int cmd_write (int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_write (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); -int cmd_erase (int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_erase (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); -int cmd_sig (int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_sig (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); -int cmd_part (int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_part (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); -int cmd_help (int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_help (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); -int cmd_quit (int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_quit (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); -int cmd_send (int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_send (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]); struct command cmd[] = { @@ -204,7 +205,7 @@ int hexdump_buf(FILE * f, int startaddr, unsigned char * buf, int len) } -int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) +int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { static char prevmem[128] = {0}; char * e; @@ -280,7 +281,7 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) } for (i=0; idesc, addr+i, p->desc); @@ -303,7 +304,7 @@ int cmd_dump(int fd, struct avrpart * p, int argc, char * argv[]) } -int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) +int cmd_write(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { char * e; int len, maxsize; @@ -373,10 +374,10 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) } } - LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + pgm->err_led(pgm, OFF); for (werror=0, i=0; ipinno[PIN_LED_ERR]); + pgm->err_led(pgm, ON); } } @@ -408,7 +409,7 @@ int cmd_write(int fd, struct avrpart * p, int argc, char * argv[]) } -int cmd_send(int fd, struct avrpart * p, int argc, char * argv[]) +int cmd_send(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { unsigned char cmd[4], res[4]; char * e; @@ -433,9 +434,9 @@ int cmd_send(int fd, struct avrpart * p, int argc, char * argv[]) } } - LED_OFF(fd, pgm->pinno[PIN_LED_ERR]); + pgm->err_led(pgm, OFF); - avr_cmd(fd, cmd, res); + pgm->cmd(pgm, cmd, res); /* * display results @@ -451,15 +452,15 @@ int cmd_send(int fd, struct avrpart * p, int argc, char * argv[]) } -int cmd_erase(int fd, struct avrpart * p, int argc, char * argv[]) +int cmd_erase(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { fprintf(stderr, "%s: erasing chip\n", progname); - avr_chip_erase(fd,p); + pgm->chip_erase(pgm, p); return 0; } -int cmd_part(int fd, struct avrpart * p, int argc, char * argv[]) +int cmd_part(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { fprintf(stdout, "\n"); avr_display(stdout, p, "", 0); @@ -469,13 +470,13 @@ int cmd_part(int fd, struct avrpart * p, int argc, char * argv[]) } -int cmd_sig(int fd, struct avrpart * p, int argc, char * argv[]) +int cmd_sig(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { int i; int rc; AVRMEM * m; - rc = avr_signature(fd, p); + rc = avr_signature(pgm, p); if (rc != 0) { fprintf(stderr, "error reading signature data, rc=%d\n", rc); @@ -498,13 +499,13 @@ int cmd_sig(int fd, struct avrpart * p, int argc, char * argv[]) } -int cmd_quit(int fd, struct avrpart * p, int argc, char * argv[]) +int cmd_quit(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { return 1; } -int cmd_help(int fd, struct avrpart * p, int argc, char * argv[]) +int cmd_help(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { int i; @@ -599,7 +600,7 @@ int tokenize(char * s, char *** argv) } -int do_cmd(int fd, struct avrpart * p, int argc, char * argv[]) +int do_cmd(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { int i; int hold; @@ -609,7 +610,7 @@ int do_cmd(int fd, struct avrpart * p, int argc, char * argv[]) hold = -1; for (i=0; i 0) { rc = 0; diff --git a/term.h b/term.h index 1936708c..471d6900 100644 --- a/term.h +++ b/term.h @@ -33,7 +33,8 @@ #define __term_h__ #include "avr.h" +#include "pgm.h" -int terminal_mode(int fd, struct avrpart * p); +int terminal_mode(PROGRAMMER * pgm, struct avrpart * p); #endif