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
This commit is contained in:
Brian S. Dean 2001-01-24 18:45:58 +00:00
parent 6593c1e534
commit fc56e6b4f9
5 changed files with 218 additions and 67 deletions

22
avr.c
View File

@ -110,19 +110,16 @@ int avr_txrx_bit ( int fd, int bit )
* read the result bit (it is either valid from a previous clock * read the result bit (it is either valid from a previous clock
* pulse or it is ignored in the current context) * 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 */ /* set the data input line as desired */
if (bit) ppi_setpin(fd, PIN_AVR_MOSI, bit);
ppi_set(fd, PPIDATA, AVR_INSTR);
else
ppi_clr(fd, PPIDATA, AVR_INSTR);
/* /*
* pulse the clock line, clocking in the MOSI data, and clocking out * pulse the clock line, clocking in the MOSI data, and clocking out
* the next result bit * the next result bit
*/ */
ppi_pulse(fd, PPIDATA, AVR_CLOCK); ppi_pulsepin(fd, PIN_AVR_SCK);
return r; return r;
} }
@ -400,7 +397,7 @@ int avr_signature ( int fd, unsigned char sig[4] )
*/ */
void avr_powerup ( int fd ) void avr_powerup ( int fd )
{ {
ppi_set(fd, PPIDATA, AVR_POWER); /* power up */ ppi_set(fd, PPIDATA, PPI_AVR_VCC); /* power up */
usleep(100000); usleep(100000);
} }
@ -410,7 +407,7 @@ void avr_powerup ( int fd )
*/ */
void avr_powerdown ( 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); avr_powerup(fd);
ppi_clr(fd, PPIDATA, AVR_CLOCK);
ppi_clr(fd, PPIDATA, AVR_RESET); ppi_setpin(fd, PIN_AVR_SCK, 0);
ppi_pulse(fd, PPIDATA, AVR_RESET); ppi_setpin(fd, PIN_AVR_RESET, 0);
ppi_pulsepin(fd, PIN_AVR_RESET);
usleep(20000); /* 20 ms XXX should be a per-chip parameter */ 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 ); rc = avr_program_enable ( fd );
if (rc == 0) if (rc == 0)
break; break;
ppi_pulse(fd, PPIDATA, AVR_CLOCK); ppi_pulsepin(fd, PIN_AVR_SCK);
tries++; tries++;
} while (tries < 32); } while (tries < 32);

34
avr.h
View File

@ -34,14 +34,18 @@
#include <stdio.h> #include <stdio.h>
/*
* bit definitions for AVR device connections #define PPI_AVR_VCC 0x0f /* ppi pins 2-5, data reg bits 0-3 */
*/ #define PIN_AVR_BUFF 6
#define AVR_POWER 0xf1 /* bit 0 and 4...7 of data register */ #define PIN_AVR_RESET 7
#define AVR_CLOCK 0x02 /* bit 1 of data register */ #define PIN_AVR_SCK 8
#define AVR_INSTR 0x04 /* bit 2 of data register */ #define PIN_AVR_MOSI 9
#define AVR_RESET 0x08 /* bit 3 of data register */ #define PIN_AVR_MISO 10
#define AVR_DATA 0x40 /* bit 6 of status register */ #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; AVRMEM memtype;
int startaddr; int startaddr;
int size; int size;
unsigned char buf; unsigned char * buf;
struct avrmem * next; struct avrmem * next;
}; };
#endif #endif
@ -72,20 +76,14 @@ struct avrpart {
int memsize[AVR_MAXMEMTYPES]; /* sizes for eeprom, int memsize[AVR_MAXMEMTYPES]; /* sizes for eeprom,
flash, etc, indexed by flash, etc, indexed by
AVR_EEPROM or AVR_FLASH */ 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 f_readback; /* flash write polled readback value */
unsigned char e_readback[2]; /* eeprom write polled readback values */ unsigned char e_readback[2]; /* eeprom write polled readback values */
int min_write_delay; /* microseconds */ int min_write_delay; /* microseconds */
int max_write_delay; /* microseconds */ int max_write_delay; /* microseconds */
int chip_erase_delay; /* microseconds */ int chip_erase_delay; /* microseconds */
unsigned char * mem[AVR_MAXMEMTYPES]; unsigned char * mem[AVR_MAXMEMTYPES]; /* pointers to avr memory
#if 0 buffers, indexed by
unsigned char * flash; AVR_EEPROM or AVR_FLASH */
unsigned char * eeprom;
#endif
}; };
extern struct avrpart parts[]; extern struct avrpart parts[];

63
main.c
View File

@ -32,25 +32,44 @@
/* /*
* Code to program an Atmel AVR AT90S device using the parallel port. * 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 * Parallel Port Programmer Function
* ------------- ---------------------------- * ------------- -----------------------------
* Pin 2 -> Vcc (see NOTE below) * Pins 2-5 -> Vcc (see note below)
* Pin 3 -> SCK CLOCK IN * Pin 7 -> AVR /RESET
* Pin 4 -> MOSI Instruction input * Pin 8 -> AVR SCK (clock input)
* Pin 5 -> /RESET * Pin 9 -> AVR MOSI (instruction in)
* Pin 6,7,8,9 -> Vcc (Can be tied together with Schottky diodes) * Pin 10 <- AVR MISO (data out)
* Pin 10 <- MISO Data out * Pin 18 Signal Ground
* Pin 18 <- GND *
* 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 * NOTE on Vcc connection: make sure your parallel port can supply an
* adequate amount of current to power your device. 6-10 mA is * adequate amount of current to power your device. 6-10 mA per pin
* common for parallel port signal lines, but is not guaranteed, * is common for parallel port signal lines, but is not guaranteed,
* especially for notebook computers. Optionally, you can tie pins * especially for notebook computers. For additional power, use
* 6, 7, 8, and 9 also to Vcc with Schottky diodes to supply * multiple pins tied together with Schottky diodes. If in doubt,
* additional current. If in doubt, don't risk damaging your * don't risk damaging your parallel port, use an external power
* parallel port, use an external power supply. * supply.
*
*/ */
#include <stdio.h> #include <stdio.h>
@ -104,16 +123,16 @@ int getexitspecs ( char *s, int *set, int *clr )
while ((cp = strtok(s, ","))) { while ((cp = strtok(s, ","))) {
if (strcmp(cp, "reset") == 0) { if (strcmp(cp, "reset") == 0) {
*clr |= AVR_RESET; *clr |= ppi_getpinmask(PIN_AVR_RESET);
} }
else if (strcmp(cp, "noreset") == 0) { else if (strcmp(cp, "noreset") == 0) {
*set |= AVR_RESET; *set |= ppi_getpinmask(PIN_AVR_RESET);
} }
else if (strcmp(cp, "vcc") == 0) { else if (strcmp(cp, "vcc") == 0) {
*set |= AVR_POWER; *set |= PPI_AVR_VCC;
} }
else if (strcmp(cp, "novcc") == 0) { else if (strcmp(cp, "novcc") == 0) {
*clr |= AVR_POWER; *clr |= PPI_AVR_VCC;
} }
else { else {
return -1; return -1;
@ -374,6 +393,10 @@ int main ( int argc, char * argv [] )
exitrc = 0; exitrc = 0;
#if 0
ppi_sense(fd);
#endif
ppidata = ppi_getall(fd, PPIDATA); ppidata = ppi_getall(fd, PPIDATA);
if (ppidata < 0) { if (ppidata < 0) {
fprintf ( stderr, "%s: error reading status of ppi data port\n", progname); fprintf ( stderr, "%s: error reading status of ppi data port\n", progname);

138
ppi.c
View File

@ -37,6 +37,36 @@
extern char * progname; 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() * set 'get' and 'set' appropriately for subsequent passage to ioctl()
* to get/set the specified PPI registers. * to get/set the specified PPI registers.
@ -125,7 +155,7 @@ int ppi_get ( int fd, int reg, int bit )
ioctl(fd, get, &v); ioctl(fd, get, &v);
v &= bit; 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 * 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 * 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 * function in 'main()' and can use it to determine whether your sense
* pin is actually sensing. * 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 { do {
usleep(100000); /* check every 100 ms */ usleep(1); /* don't be too much of a cpu hog */
v = ppi_get(fd, reg, bit); for (i=1; i<=17; i++) {
if (v != pv) { buf[i-1] = ppi_getpin(fd, i);
fprintf ( stderr, "sense bit = %d\n", v ); if (buf[i-1])
buf[i-1] = '|';
else
buf[i-1] = '.';
} }
pv = v; fprintf(stderr, "\r \r%s", buf);
} while(1); } while(1);
return 0; return 0;

28
ppi.h
View File

@ -41,21 +41,33 @@ enum {
PPISTATUS 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 #endif