From fc56e6b4f9cffbb6932dc369580d569abdf80321 Mon Sep 17 00:00:00 2001 From: "Brian S. Dean" Date: Wed, 24 Jan 2001 18:45:58 +0000 Subject: [PATCH] Rearrange the pinout for the programmer to be a little more logical. Provide hooks to support a buffered programmer, pin 6 is now used to enable a buffer that can be used to isolate the target system from the parallel port pins. This is important when programming the target in-system. Totally change the way the pin definitions are defined. Actually set/clear pins based on the way more intuitive pin number, instead of PPI data register, bit number combination. A table of pin data is used so that any hardware inversion done by the parallel port is accounted for, what you set is actually what appears at the pin. Retain the old method for handling Vcc, however, because the hold method is much easier to use when setting / retrieving multiple pins simultaneously. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@49 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avr.c | 22 +++++---- avr.h | 34 +++++++------- main.c | 63 +++++++++++++++++--------- ppi.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- ppi.h | 28 ++++++++---- 5 files changed, 218 insertions(+), 67 deletions(-) diff --git a/avr.c b/avr.c index ebed6dc9..88d93754 100644 --- a/avr.c +++ b/avr.c @@ -110,19 +110,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_get(fd, PPISTATUS, AVR_DATA); + r = ppi_getpin(fd, PIN_AVR_MISO); /* set the data input line as desired */ - if (bit) - ppi_set(fd, PPIDATA, AVR_INSTR); - else - ppi_clr(fd, PPIDATA, AVR_INSTR); + ppi_setpin(fd, PIN_AVR_MOSI, bit); /* * pulse the clock line, clocking in the MOSI data, and clocking out * the next result bit */ - ppi_pulse(fd, PPIDATA, AVR_CLOCK); + ppi_pulsepin(fd, PIN_AVR_SCK); return r; } @@ -400,7 +397,7 @@ int avr_signature ( int fd, unsigned char sig[4] ) */ void avr_powerup ( int fd ) { - ppi_set(fd, PPIDATA, AVR_POWER); /* power up */ + ppi_set(fd, PPIDATA, PPI_AVR_VCC); /* power up */ usleep(100000); } @@ -410,7 +407,7 @@ void avr_powerup ( int fd ) */ void avr_powerdown ( int fd ) { - ppi_clr(fd, PPIDATA, AVR_POWER); /* power down */ + ppi_clr(fd, PPIDATA, PPI_AVR_VCC); /* power down */ } @@ -424,9 +421,10 @@ int avr_initialize ( int fd, struct avrpart * p ) avr_powerup(fd); - ppi_clr(fd, PPIDATA, AVR_CLOCK); - ppi_clr(fd, PPIDATA, AVR_RESET); - ppi_pulse(fd, PPIDATA, AVR_RESET); + + ppi_setpin(fd, PIN_AVR_SCK, 0); + ppi_setpin(fd, PIN_AVR_RESET, 0); + ppi_pulsepin(fd, PIN_AVR_RESET); usleep(20000); /* 20 ms XXX should be a per-chip parameter */ @@ -447,7 +445,7 @@ int avr_initialize ( int fd, struct avrpart * p ) rc = avr_program_enable ( fd ); if (rc == 0) break; - ppi_pulse(fd, PPIDATA, AVR_CLOCK); + ppi_pulsepin(fd, PIN_AVR_SCK); tries++; } while (tries < 32); diff --git a/avr.h b/avr.h index 9a22e5d8..a77adca5 100644 --- a/avr.h +++ b/avr.h @@ -34,14 +34,18 @@ #include -/* - * bit definitions for AVR device connections - */ -#define AVR_POWER 0xf1 /* bit 0 and 4...7 of data register */ -#define AVR_CLOCK 0x02 /* bit 1 of data register */ -#define AVR_INSTR 0x04 /* bit 2 of data register */ -#define AVR_RESET 0x08 /* bit 3 of data register */ -#define AVR_DATA 0x40 /* bit 6 of status register */ + +#define PPI_AVR_VCC 0x0f /* ppi pins 2-5, data reg bits 0-3 */ +#define PIN_AVR_BUFF 6 +#define PIN_AVR_RESET 7 +#define PIN_AVR_SCK 8 +#define PIN_AVR_MOSI 9 +#define PIN_AVR_MISO 10 +#define PIN_LED_ERR 1 +#define PIN_LED_RDY 14 +#define PIN_LED_PGM 16 +#define PIN_LED_VFY 17 + /* @@ -61,7 +65,7 @@ struct avrmem { AVRMEM memtype; int startaddr; int size; - unsigned char buf; + unsigned char * buf; struct avrmem * next; }; #endif @@ -72,20 +76,14 @@ struct avrpart { int memsize[AVR_MAXMEMTYPES]; /* sizes for eeprom, flash, etc, indexed by AVR_EEPROM or AVR_FLASH */ -#if 0 - int flash_size; /* size in bytes of flash */ - int eeprom_size; /* size in bytes of eeprom */ -#endif unsigned char f_readback; /* flash write polled readback value */ unsigned char e_readback[2]; /* eeprom write polled readback values */ int min_write_delay; /* microseconds */ int max_write_delay; /* microseconds */ int chip_erase_delay; /* microseconds */ - unsigned char * mem[AVR_MAXMEMTYPES]; -#if 0 - unsigned char * flash; - unsigned char * eeprom; -#endif + unsigned char * mem[AVR_MAXMEMTYPES]; /* pointers to avr memory + buffers, indexed by + AVR_EEPROM or AVR_FLASH */ }; extern struct avrpart parts[]; diff --git a/main.c b/main.c index 06165500..2a365eaf 100644 --- a/main.c +++ b/main.c @@ -32,25 +32,44 @@ /* * Code to program an Atmel AVR AT90S device using the parallel port. * - * Make the following connections: + * Make the following (minimal) connections: * - * Parallel Port Atmel AVR - * ------------- ---------------------------- - * Pin 2 -> Vcc (see NOTE below) - * Pin 3 -> SCK CLOCK IN - * Pin 4 -> MOSI Instruction input - * Pin 5 -> /RESET - * Pin 6,7,8,9 -> Vcc (Can be tied together with Schottky diodes) - * Pin 10 <- MISO Data out - * Pin 18 <- GND + * Parallel Port Programmer Function + * ------------- ----------------------------- + * Pins 2-5 -> Vcc (see note below) + * Pin 7 -> AVR /RESET + * Pin 8 -> AVR SCK (clock input) + * Pin 9 -> AVR MOSI (instruction in) + * Pin 10 <- AVR MISO (data out) + * Pin 18 Signal Ground + * + * Additionally, the following conntections can be made to enable + * additional features: + * + * Parallel Port Programmer Function + * ------------- ----------------------------- + * Pin 1 STATUS LED, active low (program or verify error) + * Pin 6 -> /ENABLE ('367 bus driver) + * Pin 14 STATUS LED, active low (ready) + * Pin 16 STATUS LED, active low (programming) + * Pin 17 STATUS LED, active low (verifying) + * + * Pin 6 can be tied to the enable line of a 74HC367 in order to + * isolate and buffer the data to and from the PC parallel port. + * This is useful for connecting to a device in-circuit, and keeps + * the state of the parallel port pins from interfering with the + * normal operation of the target system. When programming is + * complete, this pin is driven high, causing to pins of the '367 to + * float. * * NOTE on Vcc connection: make sure your parallel port can supply an - * adequate amount of current to power your device. 6-10 mA is - * common for parallel port signal lines, but is not guaranteed, - * especially for notebook computers. Optionally, you can tie pins - * 6, 7, 8, and 9 also to Vcc with Schottky diodes to supply - * additional current. If in doubt, don't risk damaging your - * parallel port, use an external power supply. + * adequate amount of current to power your device. 6-10 mA per pin + * is common for parallel port signal lines, but is not guaranteed, + * especially for notebook computers. For additional power, use + * multiple pins tied together with Schottky diodes. If in doubt, + * don't risk damaging your parallel port, use an external power + * supply. + * */ #include @@ -104,16 +123,16 @@ int getexitspecs ( char *s, int *set, int *clr ) while ((cp = strtok(s, ","))) { if (strcmp(cp, "reset") == 0) { - *clr |= AVR_RESET; + *clr |= ppi_getpinmask(PIN_AVR_RESET); } else if (strcmp(cp, "noreset") == 0) { - *set |= AVR_RESET; + *set |= ppi_getpinmask(PIN_AVR_RESET); } else if (strcmp(cp, "vcc") == 0) { - *set |= AVR_POWER; + *set |= PPI_AVR_VCC; } else if (strcmp(cp, "novcc") == 0) { - *clr |= AVR_POWER; + *clr |= PPI_AVR_VCC; } else { return -1; @@ -374,6 +393,10 @@ int main ( int argc, char * argv [] ) 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); diff --git a/ppi.c b/ppi.c index 0c85a3ba..286f613b 100644 --- a/ppi.c +++ b/ppi.c @@ -37,6 +37,36 @@ extern char * progname; +struct ppipins_t { + int pin; + int reg; + int bit; + int inverted; +}; + +static struct ppipins_t pins[] = { + { 1, PPICTRL, 0x01, 1 }, + { 2, PPIDATA, 0x01, 0 }, + { 3, PPIDATA, 0x02, 0 }, + { 4, PPIDATA, 0x04, 0 }, + { 5, PPIDATA, 0x08, 0 }, + { 6, PPIDATA, 0x10, 0 }, + { 7, PPIDATA, 0x20, 0 }, + { 8, PPIDATA, 0x40, 0 }, + { 9, PPIDATA, 0x80, 0 }, + { 10, PPISTATUS, 0x40, 0 }, + { 11, PPISTATUS, 0x80, 1 }, + { 12, PPISTATUS, 0x20, 0 }, + { 13, PPISTATUS, 0x10, 0 }, + { 14, PPICTRL, 0x02, 1 }, + { 15, PPISTATUS, 0x08, 0 }, + { 16, PPICTRL, 0x04, 0 }, + { 17, PPICTRL, 0x08, 1 } +}; + +#define NPINS (sizeof(pins)/sizeof(struct ppipins_t)) + + /* * set 'get' and 'set' appropriately for subsequent passage to ioctl() * to get/set the specified PPI registers. @@ -125,7 +155,7 @@ int ppi_get ( int fd, int reg, int bit ) ioctl(fd, get, &v); v &= bit; - return (v == bit); + return v; /* v == bit */ } /* @@ -198,24 +228,114 @@ int ppi_pulse ( int fd, int reg, int bit ) } +int ppi_setpin ( int fd, int pin, int value ) +{ + + if (pin < 1 || pin > 17) + return -1; + + pin--; + + if (pins[pin].inverted) + value = !value; + + if (value) + ppi_set(fd, pins[pin].reg, pins[pin].bit); + else + ppi_clr(fd, pins[pin].reg, pins[pin].bit); + + return 0; +} + + +int ppi_getpin ( int fd, int pin ) +{ + int value; + + if (pin < 1 || pin > 17) + return -1; + + pin--; + + value = ppi_get(fd, pins[pin].reg, pins[pin].bit); + + if (value) + value = 1; + + if (pins[pin].inverted) + value = !value; + + return value; +} + + +int ppi_pulsepin ( int fd, int pin ) +{ + + if (pin < 1 || pin > 17) + return -1; + + pin--; + + ppi_toggle(fd, pins[pin].reg, pins[pin].bit); + ppi_toggle(fd, pins[pin].reg, pins[pin].bit); + + return 0; +} + + +int ppi_getpinmask ( int pin ) +{ + if (pin < 1 || pin > 17) + return -1; + + return pins[pin-1].bit; +} + + +int ppi_getpinreg ( int pin ) +{ + if (pin < 1 || pin > 17) + return -1; + + return pins[pin-1].reg; +} + + /* * infinite loop, sensing on the pin that we use to read data out of * the device; this is a debugging aid, you can insert a call to this * function in 'main()' and can use it to determine whether your sense * pin is actually sensing. */ -int ppi_sense_test ( int fd, int reg, int bit ) +int ppi_sense ( int fd ) { - unsigned char v, pv; + unsigned int r, pr; + unsigned int v; + int count; + char buf[128]; + int i; - pv = 1; + count = 0; + + fprintf ( stderr, + "parallel port data:\n" + " 111111111\n" + "123456789012345678\n" ); + + buf[17] = 0; + pr = 1; do { - usleep(100000); /* check every 100 ms */ - v = ppi_get(fd, reg, bit); - if (v != pv) { - fprintf ( stderr, "sense bit = %d\n", v ); + usleep(1); /* don't be too much of a cpu hog */ + for (i=1; i<=17; i++) { + buf[i-1] = ppi_getpin(fd, i); + if (buf[i-1]) + buf[i-1] = '|'; + else + buf[i-1] = '.'; } - pv = v; + fprintf(stderr, "\r \r%s", buf); + } while(1); return 0; diff --git a/ppi.h b/ppi.h index 66c51764..1225e6fa 100644 --- a/ppi.h +++ b/ppi.h @@ -41,21 +41,33 @@ enum { PPISTATUS }; -int ppi_getops ( int reg, unsigned long * get, unsigned long * set ); +int ppi_getops ( int reg, unsigned long * get, unsigned long * set ); -int ppi_set ( int fd, int reg, int bit ); +int ppi_set ( int fd, int reg, int bit ); -int ppi_clr ( int fd, int reg, int bit ); +int ppi_clr ( int fd, int reg, int bit ); -int ppi_get ( int fd, int reg, int bit ); +int ppi_get ( int fd, int reg, int bit ); -int ppi_toggle ( int fd, int reg, int bit ); +int ppi_toggle ( int fd, int reg, int bit ); -int ppi_getall ( int fd, int reg ); +int ppi_getall ( int fd, int reg ); -int ppi_setall ( int fd, int reg, int val ); +int ppi_setall ( int fd, int reg, int val ); -int ppi_pulse ( int fd, int reg, int bit ); +int ppi_pulse ( int fd, int reg, int bit ); + +int ppi_setpin ( int fd, int pin, int value ); + +int ppi_getpin ( int fd, int pin ); + +int ppi_pulsepin ( int fd, int pin ); + +int ppi_getpinmask ( int pin ); + +int ppi_getpinreg ( int pin ); + +int ppi_sense ( int fd ); #endif