From 6c47ddd78360eeb346428ad5a70178bd5af8351b Mon Sep 17 00:00:00 2001 From: bsd Date: Wed, 19 Sep 2001 17:04:25 +0000 Subject: [PATCH] Make the pin definitions configurable based on entries in a config file. This makes supporting other programmers much easier. Rename AVRprog.pdf to avrprog.pdf. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@67 81a1dc3b-b13d-400b-aceb-764788c761c2 --- Makefile | 22 +- avr.c | 41 ++-- avrdude.1 | 27 +++ avrdude.conf.sample | 27 +++ AVRprog.pdf => avrdude.pdf | Bin fileio.c | 3 + fileio.h | 2 - main.c | 450 ++++++++++++++++++++++++++++++++++--- pindefs.h | 19 ++ term.c | 4 +- 10 files changed, 533 insertions(+), 62 deletions(-) create mode 100644 avrdude.conf.sample rename AVRprog.pdf => avrdude.pdf (100%) diff --git a/Makefile b/Makefile index 9fbc98c7..47943097 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,13 @@ BINDIR = ${PREFIX}/bin MANDIR = ${PREFIX}/man/man1 MANUAL = avrprog.1 DOCDIR = ${PREFIX}/share/doc/avrprog +CONFIGDIR = ${PREFIX}/etc -DIRS = ${BINDIR} ${MANDIR} ${DOCDIR} +DIRS = ${BINDIR} ${MANDIR} ${DOCDIR} ${CONFIGDIR} INSTALL = /usr/bin/install -c -o root -g wheel -CFLAGS += -Wall --pedantic +CFLAGS = -g -Wall --pedantic -DCONFIG_DIR=\"${CONFIGDIR}\" LDFLAGS = @@ -39,7 +40,11 @@ ${TARGET} : ${OBJS} clean : rm -f *~ *.core ${TARGET} *.o -install : dirs ${BINDIR}/${TARGET} ${MANDIR}/${MANUAL} ${DOCDIR}/AVRprog.pdf +install : dirs \ + ${BINDIR}/${TARGET} \ + ${MANDIR}/${MANUAL} \ + ${DOCDIR}/avrprog.pdf \ + ${CONFIGDIR}/avrprog.conf.sample dirs : @@ -51,11 +56,14 @@ dirs : done ${BINDIR}/${TARGET} : ${TARGET} - ${INSTALL_PROGRAM} ${TARGET} ${BINDIR} + ${INSTALL_PROGRAM} ${TARGET} $@ ${MANDIR}/${MANUAL} : ${MANUAL} - ${INSTALL_MANUAL} ${MANUAL} ${MANDIR} + ${INSTALL_MANUAL} ${MANUAL} $@ -${DOCDIR}/AVRprog.pdf : AVRprog.pdf - ${INSTALL_DATA} AVRprog.pdf ${DOCDIR}/AVRprog.pdf +${DOCDIR}/avrprog.pdf : avrprog.pdf + ${INSTALL_DATA} avrprog.pdf $@ + +${CONFIGDIR}/avrprog.conf.sample : avrprog.conf.sample + ${INSTALL_DATA} avrprog.conf.sample $@ diff --git a/avr.c b/avr.c index 0936dd6f..10965ad0 100644 --- a/avr.c +++ b/avr.c @@ -114,16 +114,16 @@ int avr_txrx_bit ( int fd, int bit ) * 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, PIN_AVR_MISO); + r = ppi_getpin(fd, pinno[PIN_AVR_MISO]); /* set the data input line as desired */ - ppi_setpin(fd, PIN_AVR_MOSI, bit); + ppi_setpin(fd, pinno[PIN_AVR_MOSI], bit); /* * pulse the clock line, clocking in the MOSI data, and clocking out * the next result bit */ - ppi_pulsepin(fd, PIN_AVR_SCK); + ppi_pulsepin(fd, pinno[PIN_AVR_SCK]); return r; } @@ -176,8 +176,8 @@ unsigned char avr_read_byte ( int fd, struct avrpart * p, /* order here is very important, AVR_EEPROM, AVR_FLASH, AVR_FLASH+1 */ static unsigned char cmdbyte[3] = { 0xa0, 0x20, 0x28 }; - LED_ON(fd, PIN_LED_PGM); - LED_OFF(fd, PIN_LED_ERR); + LED_ON(fd, pinno[PIN_LED_PGM]); + LED_OFF(fd, pinno[PIN_LED_ERR]); offset = 0; @@ -193,7 +193,7 @@ unsigned char avr_read_byte ( int fd, struct avrpart * p, avr_cmd(fd, cmd, res); - LED_OFF(fd, PIN_LED_PGM); + LED_OFF(fd, pinno[PIN_LED_PGM]); return res[3]; } @@ -253,8 +253,8 @@ int avr_write_byte ( int fd, struct avrpart * p, AVRMEM memtype, return 0; } - LED_ON(fd, PIN_LED_PGM); - LED_OFF(fd, PIN_LED_ERR); + LED_ON(fd, pinno[PIN_LED_PGM]); + LED_OFF(fd, pinno[PIN_LED_ERR]); offset = 0; @@ -297,13 +297,14 @@ int avr_write_byte ( int fd, struct avrpart * p, AVRMEM memtype, * we couldn't write the data, indicate our displeasure by * returning an error code */ - LED_OFF(fd, PIN_LED_PGM); - LED_ON(fd, PIN_LED_ERR); + LED_OFF(fd, pinno[PIN_LED_PGM]); + LED_ON(fd, pinno[PIN_LED_ERR]); + return -1; } } - LED_OFF(fd, PIN_LED_PGM); + LED_OFF(fd, pinno[PIN_LED_PGM]); return 0; } @@ -326,7 +327,7 @@ int avr_write ( int fd, struct avrpart * p, AVRMEM memtype, int size ) unsigned char data; int werror; - LED_OFF(fd, PIN_LED_ERR); + LED_OFF(fd, pinno[PIN_LED_ERR]); werror = 0; @@ -351,7 +352,7 @@ int avr_write ( int fd, struct avrpart * p, AVRMEM memtype, int size ) if (rc) { fprintf(stderr, " ***failed; "); fprintf(stderr, "\n"); - LED_ON(fd, PIN_LED_ERR); + LED_ON(fd, pinno[PIN_LED_ERR]); werror = 1; } if (werror) { @@ -359,7 +360,7 @@ int avr_write ( int fd, struct avrpart * p, AVRMEM memtype, int size ) * 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, PIN_LED_ERR); + LED_ON(fd, pinno[PIN_LED_ERR]); } } @@ -394,13 +395,13 @@ int avr_chip_erase ( int fd, struct avrpart * p ) unsigned char data[4] = {0xac, 0x80, 0x00, 0x00}; unsigned char res[4]; - LED_ON(fd, PIN_LED_PGM); + LED_ON(fd, pinno[PIN_LED_PGM]); avr_cmd(fd, data, res); usleep(p->chip_erase_delay); avr_initialize(fd, p); - LED_OFF(fd, PIN_LED_PGM); + LED_OFF(fd, pinno[PIN_LED_PGM]); return 0; } @@ -455,9 +456,9 @@ int avr_initialize ( int fd, struct avrpart * p ) avr_powerup(fd); - ppi_setpin(fd, PIN_AVR_SCK, 0); - ppi_setpin(fd, PIN_AVR_RESET, 0); - ppi_pulsepin(fd, PIN_AVR_RESET); + ppi_setpin(fd, pinno[PIN_AVR_SCK], 0); + ppi_setpin(fd, pinno[PIN_AVR_RESET], 0); + ppi_pulsepin(fd, pinno[PIN_AVR_RESET]); usleep(20000); /* 20 ms XXX should be a per-chip parameter */ @@ -478,7 +479,7 @@ int avr_initialize ( int fd, struct avrpart * p ) rc = avr_program_enable ( fd ); if (rc == 0) break; - ppi_pulsepin(fd, PIN_AVR_SCK); + ppi_pulsepin(fd, pinno[PIN_AVR_SCK]); tries++; } while (tries < 32); diff --git a/avrdude.1 b/avrdude.1 index b732690c..0dc3934d 100644 --- a/avrdude.1 +++ b/avrdude.1 @@ -113,6 +113,31 @@ ll. 8515 AT90S8515 8535 AT90S8535 .TE +.It Fl c Ar Pin-Configuration +Use the pin configuration specified by the argument. Pin +configurations are read from the config file (see the +.Fl C +option). New pin configurations can be easily added or modified +through the use of a config file to make +.Nm avrprog +work with different programmers as long as the programmer supports the +Atmel AVR serial program method. +.It Fl C Ar Config-File +Use the specified config file to locate the desired pin configuration. +Pin configurations are specified in the config file using a colon +seperated field format. The configuration name is the first field, +the remaining fields are of the form: +.Ar PIN=VALUE , +where +.Ar PIN +can be +.Ar VCC , RESET , SCK , MOSI , MISO , BUFF , PGMLED , RDYLED , VFYLED , ERRLED . +The value is the pin number of the PC parallel port assigned to that +function. The +.Ar VCC +pin can take multible values seperated by a comma. It's value(s) must +come from pins 2 through 9. The default configuration file is +.Pa /usr/local/etc/avrprog.conf . .It Fl e Causes a chip erase to be executed. This will reset the contents of the flash ROM and EEPROM to the value @@ -300,6 +325,8 @@ ll. .It Pa /dev/ppi0 default device to be used for communication with the programming hardware +.It Pa /usr/local/etc/avrprog.conf +default pin configuration file .It Pa ~/.inputrc Initialization file for the .Xr readline 3 diff --git a/avrdude.conf.sample b/avrdude.conf.sample new file mode 100644 index 00000000..6dd081ca --- /dev/null +++ b/avrdude.conf.sample @@ -0,0 +1,27 @@ +# $Id$ +# +# Programmer Pin Configurations +# +# The format of these entries is as follows: +# name:[desc=:][[=:]...] +# +# Example: for a programmer called PGM-1 that uses pin 2 and 3 for +# power, pins 4, 5, and 6 for RESET, SCK, and MOSI, and pin 10 for +# MISO, we could use the following entry: +# +# pgm-1 : desc=Programmer 1:vcc=2,3:reset=4:sck=5:mosi=6:miso=10 +# +# Continuation lines are supported, use a backslash (\) as the last +# character of the line and the next line will included as part of the +# configuration data. +# + +bsd : desc=Brian Dean's programmer:vcc=2,3,4,5:reset=7:sck=8:\ + mosi=9:miso=10 + +dt006 : desc=Dontronics DT006:reset=4:sck=5:mosi=2:miso=11 + +alf : desc=Tony Freibel's programmer:vcc=2,3,4,5:buff=6:\ + reset=7:sck=8:mosi=9:miso=10:errled=1:rdyled=14:pgmled=16:\ + vfyled=17 + diff --git a/AVRprog.pdf b/avrdude.pdf similarity index 100% rename from AVRprog.pdf rename to avrdude.pdf diff --git a/fileio.c b/fileio.c index 920fe32c..abb441a7 100644 --- a/fileio.c +++ b/fileio.c @@ -42,6 +42,9 @@ #define IHEX_MAXDATA 256 +#define MAX_LINE_LEN 256 /* max line length for ASCII format input files */ + + struct ihexrec { unsigned char reclen; unsigned short loadofs; diff --git a/fileio.h b/fileio.h index 87477bc0..e7edf10b 100644 --- a/fileio.h +++ b/fileio.h @@ -52,8 +52,6 @@ enum { FIO_WRITE }; -#define MAX_LINE_LEN 256 /* max line length for ASCII format input files */ - char * fmtstr ( FILEFMT format ); int fileio_setparms ( int op, struct fioparms * fp ); diff --git a/main.c b/main.c index 300cc2d3..6e9246dc 100644 --- a/main.c +++ b/main.c @@ -73,12 +73,14 @@ */ #include +#include #include #include #include #include #include #include +#include #include "avr.h" #include "fileio.h" @@ -114,6 +116,8 @@ char progbuf[PATH_MAX]; /* temporary buffer of spaces the same length as progname; used for lining up multiline messages */ +unsigned int pinno[N_PINS]; + /* * usage message */ @@ -138,16 +142,18 @@ int getexitspecs ( char *s, int *set, int *clr ) while ((cp = strtok(s, ","))) { if (strcmp(cp, "reset") == 0) { - *clr |= ppi_getpinmask(PIN_AVR_RESET); + *clr |= ppi_getpinmask(pinno[PIN_AVR_RESET]); } else if (strcmp(cp, "noreset") == 0) { - *set |= ppi_getpinmask(PIN_AVR_RESET); + *set |= ppi_getpinmask(pinno[PIN_AVR_RESET]); } else if (strcmp(cp, "vcc") == 0) { - *set |= PPI_AVR_VCC; + if (pinno[PPI_AVR_VCC]) + *set |= pinno[PPI_AVR_VCC]; } else if (strcmp(cp, "novcc") == 0) { - *clr |= PPI_AVR_VCC; + if (pinno[PPI_AVR_VCC]) + *clr |= pinno[PPI_AVR_VCC]; } else { return -1; @@ -259,6 +265,329 @@ int print_module_versions ( FILE * outf, char * timestamp ) +#define MAX_LINE_LEN 1024 +#define MAX_PIN_NAME 64 + +int parse_config(int lineno, char * infile, char * config, char * s, + unsigned int * pinno, char * desc, int desclen) +{ + char pin_name[MAX_PIN_NAME]; + char * p; + int i; + int pins; + unsigned int value; + unsigned int v; + char * e; + + pins = 0; + p = s; + + while (1) { + + while (*p && isspace(*p)) + p++; + + if (*p == 0) { + if (pins == 0) { + fprintf(stderr, + "%s: warning: no pins configured using config entry \"%s\" " + "at line %d of %s\n", + progname, config, lineno, infile); + } + return 0; + } + + /* + * parse the pin name + */ + pin_name[0] = 0; + i = 0; + while (*p && (i 9)) { + fprintf(stderr, + "%s: error at line %d of %s: VCC must be one or more " + "pins from the range 2-9\n", + progname, lineno, infile); + return -1; + } + value |= (1 << (v-2)); + } + else { + if ((v <= 0) || (v >= 18)) { + fprintf(stderr, + "%s: error at line %d of %s: pin must be in the " + "range 1-17\n", + progname, lineno, infile); + return -1; + } + value = v; + } + + p = e; + while (*p && (isspace(*p)||(*p == ','))) + p++; + } + + if (strcasecmp(pin_name, "VCC")==0) + pinno[PPI_AVR_VCC] = value; + else if (strcasecmp(pin_name, "BUFF")==0) + pinno[PIN_AVR_BUFF] = value; + else if (strcasecmp(pin_name, "RESET")==0) + pinno[PIN_AVR_RESET] = value; + else if (strcasecmp(pin_name, "SCK")==0) + pinno[PIN_AVR_SCK] = value; + else if (strcasecmp(pin_name, "MOSI")==0) + pinno[PIN_AVR_MOSI] = value; + else if (strcasecmp(pin_name, "MISO")==0) + pinno[PIN_AVR_MISO] = value; + else if (strcasecmp(pin_name, "ERRLED")==0) + pinno[PIN_LED_ERR] = value; + else if (strcasecmp(pin_name, "RDYLED")==0) + pinno[PIN_LED_RDY] = value; + else if (strcasecmp(pin_name, "PGMLED")==0) + pinno[PIN_LED_PGM] = value; + else if (strcasecmp(pin_name, "VFYLED")==0) + pinno[PIN_LED_VFY] = value; + else { + fprintf(stderr, + "%s: error at line %d of %s: invalid pin name \"%s\"\n", + progname, lineno, infile, pin_name); + return -1; + } + + pins++; + } + } + + while (*p && (*p == ':')) + p++; + } + + return 0; +} + + + +int read_config(char * infile, char * config, unsigned int * pinno, + char * desc, int desclen) +{ + FILE * f; + char line[MAX_LINE_LEN]; + char buf[MAX_LINE_LEN]; + char configname[MAX_PIN_NAME]; + int len, lineno, rc, cont; + char * p, * q; + int i; + + for (i=0; i= MAX_LINE_LEN) { + fprintf(stderr, + "%s: buffer length of %d exceed at line %d of \"%s\"\n", + progname, MAX_LINE_LEN, lineno, infile); + return -2; + } + + if (cont) + continue; /* continuation line, keep going */ + + /* + * read the configuration name from the beginning of the line + */ + p = buf; + i = 0; + while (*p && (i < MAX_PIN_NAME) && (!(isspace(*p)||(*p == ':')))) { + configname[i++] = *p; + p++; + } + if (i == MAX_PIN_NAME) { + fprintf(stderr, "%s: configuration name too long at line %d of \"%s\"\n", + progname, lineno, infile); + return -3; + } + configname[i] = 0; + + /* + * position 'p' to the beginning of the pin information + */ + while (*p && (isspace(*p) || (*p == ':'))) + p++; + + if (strcasecmp(configname, config) == 0) { + rc = parse_config(lineno, infile, config, p, pinno, desc, desclen); + if (rc) { + fprintf(stderr, "%s: error parsing config file \"%s\" at line %d\n", + progname, infile, lineno); + return -3; + } + + return 0; + } + + buf[0] = 0; + } + + /* + * config entry not found + */ + + fprintf(stderr, "%s: config entry \"%s\" not found in file \"%s\"\n", + progname, config, infile); + + return -5; +} + + + + +void pinconfig_display(char * p, char * config, char * desc) +{ + fprintf(stderr, "%sProgrammer Pin Configuration: %s (%s)\n", p, + config ? config : "DEFAULT", desc); + fprintf(stderr, + "%s VCC = 0x%02x\n" + "%s BUFF = %d\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, pinno[PPI_AVR_VCC], + p, pinno[PIN_AVR_BUFF], + p, pinno[PIN_AVR_RESET], + p, pinno[PIN_AVR_SCK], + p, pinno[PIN_AVR_MOSI], + p, pinno[PIN_AVR_MISO], + p, pinno[PIN_LED_ERR], + p, pinno[PIN_LED_RDY], + p, pinno[PIN_LED_PGM], + p, pinno[PIN_LED_VFY]); +} + + + +void verify_pin_assigned(int pin, char * desc) +{ + if (pinno[pin] == 0) { + fprintf(stderr, "%s: error: no pin has been assigned for %s\n", + progname, desc); + exit(1); + } +} + + + +#define MAX_DESC_LEN 80 + /* * main routine */ @@ -279,6 +608,9 @@ int main ( int argc, char * argv [] ) int ppidata; /* cached value of the ppi data register */ int vsize=-1; /* number of bytes to verify */ char timestamp[64]; + char configfile[PATH_MAX]; /* pin configuration file */ + char * pinconfig; + char desc[MAX_DESC_LEN]; /* options / operating mode variables */ int memtype; /* AVR_FLASH or AVR_EEPROM */ @@ -295,20 +627,46 @@ int main ( int argc, char * argv [] ) int ppisetbits; /* bits to set in ppi data register at exit */ int ppiclrbits; /* bits to clear in ppi data register at exit */ - readorwrite = 0; - parallel = DEFAULT_PARALLEL; - outputf = NULL; - inputf = NULL; - doread = 1; - memtype = AVR_FLASH; - erase = 0; - p = NULL; - ovsigck = 0; - terminal = 0; - filefmt = FMT_AUTO; - nowrite = 0; - verify = 1; /* on by default; XXX can't turn it off */ - ppisetbits = ppiclrbits = 0; + readorwrite = 0; + parallel = DEFAULT_PARALLEL; + outputf = NULL; + inputf = NULL; + doread = 1; + memtype = AVR_FLASH; + erase = 0; + p = NULL; + ovsigck = 0; + terminal = 0; + filefmt = FMT_AUTO; + nowrite = 0; + verify = 1; /* on by default; XXX can't turn it off */ + ppisetbits = ppiclrbits = 0; + pinconfig = NULL; + + strcpy(configfile, CONFIG_DIR); + i = strlen(configfile); + if (i && (configfile[i-1] != '/')) + strcat(configfile, "/"); + strcat(configfile, "avrprog.conf"); + + for (i=0; imem[AVR_FLASH|AVR_EEPROM]) * is the same as what is on the chip */ - LED_ON(fd, PIN_LED_VFY); + LED_ON(fd, pinno[PIN_LED_VFY]); fprintf(stderr, "%s: verifying %s memory against %s:\n", progname, avr_memtstr(memtype), inputf); @@ -702,7 +1090,7 @@ int main ( int argc, char * argv [] ) if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", progname, avr_memtstr(memtype), rc); - LED_ON(fd, PIN_LED_ERR); + LED_ON(fd, pinno[PIN_LED_ERR]); exitrc = 1; goto main_exit; } @@ -712,7 +1100,7 @@ int main ( int argc, char * argv [] ) if (rc < 0) { fprintf(stderr, "%s: verification error; content mismatch\n", progname); - LED_ON(fd, PIN_LED_ERR); + LED_ON(fd, pinno[PIN_LED_ERR]); exitrc = 1; goto main_exit; } @@ -720,7 +1108,7 @@ int main ( int argc, char * argv [] ) fprintf(stderr, "%s: %d bytes of %s verified\n", progname, rc, avr_memtstr(memtype)); - LED_OFF(fd, PIN_LED_VFY); + LED_OFF(fd, pinno[PIN_LED_VFY]); } @@ -737,9 +1125,9 @@ int main ( int argc, char * argv [] ) /* * disable the 74367 buffer, if connected; this signal is active low */ - ppi_setpin(fd, PIN_AVR_BUFF, 1); + ppi_setpin(fd, pinno[PIN_AVR_BUFF], 1); - LED_OFF(fd, PIN_LED_RDY); + LED_OFF(fd, pinno[PIN_LED_RDY]); close(fd); diff --git a/pindefs.h b/pindefs.h index 10c60309..f41e1021 100644 --- a/pindefs.h +++ b/pindefs.h @@ -32,6 +32,24 @@ #ifndef __pindefs_h__ #define __pindefs_h__ +#if 1 +enum { + PPI_AVR_VCC=1, + PIN_AVR_BUFF, + PIN_AVR_RESET, + PIN_AVR_SCK, + PIN_AVR_MOSI, + PIN_AVR_MISO, + PIN_LED_ERR, + PIN_LED_RDY, + PIN_LED_PGM, + PIN_LED_VFY, + N_PINS +}; + +extern unsigned int pinno[N_PINS]; + +#else #define PPI_AVR_VCC 0x0f /* ppi pins 2-5, data reg bits 0-3 */ #define PIN_AVR_BUFF 6 #define PIN_AVR_RESET 7 @@ -42,6 +60,7 @@ #define PIN_LED_RDY 14 #define PIN_LED_PGM 16 #define PIN_LED_VFY 17 +#endif #define LED_ON(fd,pin) ppi_setpin(fd,pin,0) #define LED_OFF(fd,pin) ppi_setpin(fd,pin,1) diff --git a/term.c b/term.c index 80cc8008..b6ae24f4 100644 --- a/term.c +++ b/term.c @@ -355,7 +355,7 @@ int cmd_write ( int fd, struct avrpart * p, int argc, char * argv[] ) } } - LED_OFF(fd, PIN_LED_ERR); + LED_OFF(fd, pinno[PIN_LED_ERR]); for (werror=0, i=0; i