diff --git a/avrdude/Makefile b/avrdude/Makefile index 71b3a2f1..4d67530a 100644 --- a/avrdude/Makefile +++ b/avrdude/Makefile @@ -47,11 +47,11 @@ LIBS = -lreadline YYDEF = -DYYSTYPE="struct token_t *" -SRCS = config_gram.c avr.c config.c fileio.c lexer.c lists.c main.c pgm.c \ - ppi.c stk500.c term.c +SRCS = config_gram.c avr.c config.c fileio.c lexer.c lists.c main.c par.c \ + pgm.c ppi.c stk500.c term.c -OBJS = config_gram.o avr.o config.o fileio.o lexer.o lists.o main.o pgm.o \ - ppi.o stk500.o term.o +OBJS = config_gram.o avr.o config.o fileio.o lexer.o lists.o main.o par.o \ + pgm.o ppi.o stk500.o term.o all : depend ${TARGET} diff --git a/avrdude/avrdude.conf.sample b/avrdude/avrdude.conf.sample index 54a474d6..86492ec4 100644 --- a/avrdude/avrdude.conf.sample +++ b/avrdude/avrdude.conf.sample @@ -15,7 +15,7 @@ # programmer # id = [, [, ] ...] ; # are quoted strings # desc = ; # quoted string -# type = ppi | stk500 ; # programmer type +# type = par | stk500 ; # programmer type # vcc = [, ... ] ; # pin number(s) # reset = ; # pin number # sck = ; # pin number @@ -172,7 +172,7 @@ programmer id = "bsd", "default"; desc = "Brian Dean's Programmer"; - type = ppi; + type = par; vcc = 2, 3, 4, 5; reset = 7; sck = 8; @@ -189,7 +189,7 @@ programmer programmer id = "stk200"; desc = "STK200"; - type = ppi; + type = par; buff = 4, 5; sck = 6; mosi = 7; @@ -200,7 +200,7 @@ programmer programmer id = "dt006"; desc = "Dontronics DT006"; - type = ppi; + type = par; reset = 4; sck = 5; mosi = 2; @@ -210,7 +210,7 @@ programmer programmer id = "alf"; desc = "Tony Friebel's Programmer"; - type = ppi; + type = par; vcc = 2, 3, 4, 5; buff = 6; reset = 7; diff --git a/avrdude/config_gram.y b/avrdude/config_gram.y index 765da9b8..727602fc 100644 --- a/avrdude/config_gram.y +++ b/avrdude/config_gram.y @@ -26,6 +26,7 @@ #include "config.h" #include "lists.h" +#include "par.h" #include "pindefs.h" #include "ppi.h" #include "pgm.h" @@ -73,9 +74,9 @@ static int parse_cmdbits(OPCODE * op); %token K_MISO %token K_MOSI %token K_NUM_PAGES +%token K_PAR %token K_PART %token K_PGMLED -%token K_PPI %token K_PROGRAMMER %token K_PWROFF_AFTER_WRITE %token K_RDYLED @@ -228,9 +229,9 @@ prog_parm : } } | - K_TYPE TKN_EQUAL K_PPI { + K_TYPE TKN_EQUAL K_PAR { { - ppi_initpgm(current_prog); + par_initpgm(current_prog); } } | diff --git a/avrdude/lexer.l b/avrdude/lexer.l index 8f24c6a9..cea7fbf7 100644 --- a/avrdude/lexer.l +++ b/avrdude/lexer.l @@ -135,7 +135,7 @@ 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; } -ppi { yylval=NULL; return K_PPI; } +par { yylval=NULL; return K_PAR; } programmer { yylval=NULL; return K_PROGRAMMER; } pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; } rdyled { yylval=NULL; return K_RDYLED; } diff --git a/avrdude/main.c b/avrdude/main.c index bf132778..f01a3986 100644 --- a/avrdude/main.c +++ b/avrdude/main.c @@ -78,6 +78,7 @@ #include "avr.h" #include "config.h" #include "fileio.h" +#include "par.h" #include "pindefs.h" #include "ppi.h" #include "term.h" @@ -128,10 +129,10 @@ int getexitspecs(char *s, int *set, int *clr) while ((cp = strtok(s, ","))) { if (strcmp(cp, "reset") == 0) { - *clr |= ppi_getpinmask(pgm->pinno[PIN_AVR_RESET]); + *clr |= par_getpinmask(pgm->pinno[PIN_AVR_RESET]); } else if (strcmp(cp, "noreset") == 0) { - *set |= ppi_getpinmask(pgm->pinno[PIN_AVR_RESET]); + *set |= par_getpinmask(pgm->pinno[PIN_AVR_RESET]); } else if (strcmp(cp, "vcc") == 0) { if (pgm->pinno[PPI_AVR_VCC]) @@ -341,7 +342,7 @@ int main(int argc, char * argv []) */ compiled_in_pgm = pgm_new(); pgm = compiled_in_pgm; - ppi_initpgm(pgm); + par_initpgm(pgm); ladd(pgm->id, dup_string("avrdude")); strcpy(pgm->desc, "avrdude compiled-in default"); pgm->pinno[PPI_AVR_VCC] = 0x0f; /* ppi pins 2-5, data reg bits 0-3 */ diff --git a/avrdude/par.c b/avrdude/par.c new file mode 100644 index 00000000..316836de --- /dev/null +++ b/avrdude/par.c @@ -0,0 +1,602 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#include +#include +#include +#include +#include +#include + +#if defined(__FreeBSD__) +#include +#elif defined(__linux__) +#include "linux_ppdev.h" +#endif + +#include "avr.h" +#include "pindefs.h" +#include "pgm.h" +#include "par.h" +#include "ppi.h" + +#define SLOW_TOGGLE 0 + +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)) + + +extern char * progname; +extern int do_cycles; + + +static int par_setpin (int fd, int pin, int value); + +static int par_getpin (int fd, int pin); + +static int par_pulsepin (int fd, int pin); + + +static int par_rdy_led (PROGRAMMER * pgm, int value); + +static int par_err_led (PROGRAMMER * pgm, int value); + +static int par_pgm_led (PROGRAMMER * pgm, int value); + +static int par_vfy_led (PROGRAMMER * pgm, int value); + +static int par_cmd (PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]); + +static int par_chip_erase (PROGRAMMER * pgm, AVRPART * p); + +static int par_program_enable (PROGRAMMER * pgm, AVRPART * p); + +static void par_powerup (PROGRAMMER * pgm); + +static void par_powerdown (PROGRAMMER * pgm); + +static int par_initialize (PROGRAMMER * pgm, AVRPART * p); + +static int par_save (PROGRAMMER * pgm); + +static void par_restore (PROGRAMMER * pgm); + +static void par_disable (PROGRAMMER * pgm); + +static void par_enable (PROGRAMMER * pgm); + +static void par_open (PROGRAMMER * pgm, char * port); + +static void par_close (PROGRAMMER * pgm); + + +static int par_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); + +#if SLOW_TOGGLE + usleep(1000); +#endif + + return 0; +} + + +static int par_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; +} + + +static int par_pulsepin(int fd, int pin) +{ + + if (pin < 1 || pin > 17) + return -1; + + pin--; + + ppi_toggle(fd, pins[pin].reg, pins[pin].bit); + +#if SLOW_TOGGLE + usleep(1000); +#endif + + ppi_toggle(fd, pins[pin].reg, pins[pin].bit); + +#if SLOW_TOGGLE + usleep(1000); +#endif + + return 0; +} + +int par_getpinmask(int pin) +{ + if (pin < 1 || pin > 17) + return -1; + + return pins[pin-1].bit; +} + + +static char vccpins_buf[64]; +static 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; +} + + + +/* + * transmit and receive a byte of data to/from the AVR device + */ +static unsigned char par_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 = par_getpin(pgm->fd, pgm->pinno[PIN_AVR_MISO]); + + /* set the data input line as desired */ + par_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 + */ + par_pulsepin(pgm->fd, pgm->pinno[PIN_AVR_SCK]); + + rbyte = rbyte | (r << (7-i)); + } + + return rbyte; +} + + + + + +static int par_rdy_led(PROGRAMMER * pgm, int value) +{ + par_setpin(pgm->fd, pgm->pinno[PIN_LED_RDY], !value); + return 0; +} + +static int par_err_led(PROGRAMMER * pgm, int value) +{ + par_setpin(pgm->fd, pgm->pinno[PIN_LED_ERR], !value); + return 0; +} + +static int par_pgm_led(PROGRAMMER * pgm, int value) +{ + par_setpin(pgm->fd, pgm->pinno[PIN_LED_PGM], !value); + return 0; +} + +static int par_vfy_led(PROGRAMMER * pgm, int value) +{ + par_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 + */ +static int par_cmd(PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]) +{ + int i; + + for (i=0; i<4; i++) { + res[i] = par_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 + */ +static int par_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 + */ +static int par_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 + */ +static void par_powerup(PROGRAMMER * pgm) +{ + ppi_set(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_VCC]); /* power up */ + usleep(100000); +} + + +/* + * remove power from the AVR processor + */ +static void par_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 + */ +static int par_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + int rc; + int tries; + + pgm->powerup(pgm); + usleep(20000); + + par_setpin(pgm->fd, pgm->pinno[PIN_AVR_SCK], 0); + par_setpin(pgm->fd, pgm->pinno[PIN_AVR_RESET], 0); + usleep(20000); + + par_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; + par_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; +} + + +static int par_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; +} + +static void par_restore(PROGRAMMER * pgm) +{ + ppi_setall(pgm->fd, PPIDATA, pgm->ppidata); +} + +static void par_disable(PROGRAMMER * pgm) +{ + ppi_set(pgm->fd, PPIDATA, pgm->pinno[PPI_AVR_BUFF]); +} + +static void par_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. + */ + + par_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]); +} + + +static void par_open(PROGRAMMER * pgm, char * port) +{ + pgm->fd = ppi_open(port); + if (pgm->fd < 0) { + fprintf(stderr, "%s: failed to open parallel port \"%s\"\n\n", + progname, port); + exit(1); + } + + ppi_claim(pgm); +} + + +static void par_close(PROGRAMMER * pgm) +{ + ppi_release(pgm); + + ppi_close(pgm->fd); + pgm->fd = -1; +} + + +static void par_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 par_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "PPI"); + + pgm->rdy_led = par_rdy_led; + pgm->err_led = par_err_led; + pgm->pgm_led = par_pgm_led; + pgm->vfy_led = par_vfy_led; + pgm->initialize = par_initialize; + pgm->display = par_display; + pgm->save = par_save; + pgm->restore = par_restore; + pgm->enable = par_enable; + pgm->disable = par_disable; + pgm->powerup = par_powerup; + pgm->powerdown = par_powerdown; + pgm->program_enable = par_program_enable; + pgm->chip_erase = par_chip_erase; + pgm->cmd = par_cmd; + pgm->open = par_open; + pgm->close = par_close; +} + + diff --git a/avrdude/par.h b/avrdude/par.h new file mode 100644 index 00000000..dece58a1 --- /dev/null +++ b/avrdude/par.h @@ -0,0 +1,33 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef __par_h__ +#define __par_h__ + +#include "config.h" + +void par_initpgm (PROGRAMMER * pgm); + +int par_getpinmask(int pin); + +#endif + + diff --git a/avrdude/ppi.c b/avrdude/ppi.c index ddc327f8..4aa16bbd 100644 --- a/avrdude/ppi.c +++ b/avrdude/ppi.c @@ -19,6 +19,8 @@ /* $Id$ */ +#if defined(__FreeBSD__) || defined(__linux__) + #include #include #include @@ -37,147 +39,13 @@ #include "pgm.h" #include "ppi.h" -#define SLOW_TOGGLE 0 - extern char * progname; -extern int do_cycles; - -/* - * PPI registers - */ -enum { - PPIDATA, - PPICTRL, - PPISTATUS -}; - -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)) - - -int ppi_getops (int reg, unsigned long * get, unsigned long * set); - -int ppi_set (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_toggle (int fd, int reg, int bit); - -int ppi_getall (int fd, int reg); - -int ppi_setall (int fd, int reg, int val); - -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_getpinreg (int pin); - -int ppi_sense (int fd); - - -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); - - - - - - - - - -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. */ -int ppi_getops(int reg, unsigned long * get, unsigned long * set) +static int ppi_getops(int reg, unsigned long * get, unsigned long * set) { switch (reg) { case PPIDATA: @@ -322,534 +190,26 @@ int ppi_setall(int fd, int reg, int val) return 0; } -/* - * pulse the indicated bit of the specified register. - */ -int ppi_pulse(int fd, int reg, int bit) + +int ppi_open(char * port) { - ppi_toggle(fd, reg, bit); + int fd; -#if SLOW_TOGGLE - usleep(1000); -#endif - - ppi_toggle(fd, reg, bit); - -#if SLOW_TOGGLE - usleep(1000); -#endif - - return 0; -} - - -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); - -#if SLOW_TOGGLE - usleep(1000); -#endif - - 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); - -#if SLOW_TOGGLE - usleep(1000); -#endif - - ppi_toggle(fd, pins[pin].reg, pins[pin].bit); - -#if SLOW_TOGGLE - usleep(1000); -#endif - - 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(int fd) -{ - unsigned int pr; - int count; - char buf[128]; - int i; - - count = 0; - - fprintf(stderr, - "parallel port data:\n" - " 111111111\n" - "123456789012345678\n"); - - buf[17] = 0; - pr = 1; - do { - 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] = '.'; - } - fprintf(stderr, "\r \r%s", buf); - - } while(1); - - return 0; -} - - - - -/* - * 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", + fd = open(port, O_RDWR); + if (fd < 0) { + fprintf(stderr, "%s: can't open device \"%s\": %s\n", progname, port, strerror(errno)); - exit(1); + return -1; } - ppi_claim(pgm); + return fd; } -void ppi_close(PROGRAMMER * pgm) +void ppi_close(int fd) { - ppi_release(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; + close(fd); } +#endif diff --git a/avrdude/ppi.h b/avrdude/ppi.h index bf319462..487ddecb 100644 --- a/avrdude/ppi.h +++ b/avrdude/ppi.h @@ -24,10 +24,15 @@ #include "config.h" +/* + * PPI registers + */ +enum { + PPIDATA, + PPICTRL, + PPISTATUS +}; -void ppi_initpgm (PROGRAMMER * pgm); - -int ppi_getpinmask(int pin); #if !defined(ppi_claim) # define ppi_claim(pgm) @@ -37,6 +42,22 @@ int ppi_getpinmask(int pin); # define ppi_release(pgm) #endif +int ppi_get (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_getall (int fd, int reg); + +int ppi_setall (int fd, int reg, int val); + +int ppi_toggle (int fd, int reg, int bit); + +int ppi_open (char * port); + +void ppi_close (int fd); + #endif diff --git a/avrdude/stk500.c b/avrdude/stk500.c index b2508a20..0fda13e9 100644 --- a/avrdude/stk500.c +++ b/avrdude/stk500.c @@ -46,7 +46,7 @@ extern char * progname; extern int do_cycles; -int static stk500_send(PROGRAMMER * pgm, char * buf, int buflen) +static int stk500_send(PROGRAMMER * pgm, char * buf, int buflen) { struct timeval timeout; fd_set wfds; @@ -97,7 +97,7 @@ int static stk500_send(PROGRAMMER * pgm, char * buf, int buflen) -int static stk500_recv(PROGRAMMER * pgm, char * buf, int n) +static int stk500_recv(PROGRAMMER * pgm, char * buf, int n) { struct timeval timeout; fd_set rfds; @@ -144,7 +144,7 @@ int static stk500_recv(PROGRAMMER * pgm, char * buf, int n) } -int static stk500_drain(PROGRAMMER * pgm, int display) +static int stk500_drain(PROGRAMMER * pgm, int display) { struct timeval timeout; fd_set rfds; @@ -227,22 +227,22 @@ static int stk500_getsync(PROGRAMMER * pgm) } -int stk500_rdy_led(PROGRAMMER * pgm, int value) +static int stk500_rdy_led(PROGRAMMER * pgm, int value) { return 0; } -int stk500_err_led(PROGRAMMER * pgm, int value) +static int stk500_err_led(PROGRAMMER * pgm, int value) { return 0; } -int stk500_pgm_led(PROGRAMMER * pgm, int value) +static int stk500_pgm_led(PROGRAMMER * pgm, int value) { return 0; } -int stk500_vfy_led(PROGRAMMER * pgm, int value) +static int stk500_vfy_led(PROGRAMMER * pgm, int value) { return 0; } @@ -252,7 +252,8 @@ int stk500_vfy_led(PROGRAMMER * pgm, int value) * transmit an AVR device command and return the results; 'cmd' and * 'res' must point to at least a 4 byte data buffer */ -int stk500_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]) +static int stk500_cmd(PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]) { unsigned char buf[32]; @@ -290,7 +291,7 @@ int stk500_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]) /* * issue the 'chip erase' command to the AVR device */ -int stk500_chip_erase(PROGRAMMER * pgm, AVRPART * p) +static int stk500_chip_erase(PROGRAMMER * pgm, AVRPART * p) { unsigned char cmd[4]; unsigned char res[4]; @@ -343,7 +344,7 @@ int stk500_chip_erase(PROGRAMMER * pgm, AVRPART * p) /* * issue the 'program enable' command to the AVR device */ -int stk500_program_enable(PROGRAMMER * pgm, AVRPART * p) +static int stk500_program_enable(PROGRAMMER * pgm, AVRPART * p) { unsigned char buf[16]; int tries=0; @@ -394,7 +395,7 @@ int stk500_program_enable(PROGRAMMER * pgm, AVRPART * p) /* * apply power to the AVR processor */ -void stk500_powerup(PROGRAMMER * pgm) +static void stk500_powerup(PROGRAMMER * pgm) { return; } @@ -403,7 +404,7 @@ void stk500_powerup(PROGRAMMER * pgm) /* * remove power from the AVR processor */ -void stk500_powerdown(PROGRAMMER * pgm) +static void stk500_powerdown(PROGRAMMER * pgm) { return; } @@ -412,7 +413,7 @@ void stk500_powerdown(PROGRAMMER * pgm) /* * initialize the AVR device and prepare it to accept commands */ -int stk500_initialize(PROGRAMMER * pgm, AVRPART * p) +static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p) { unsigned char buf[32]; AVRMEM * m; @@ -531,17 +532,17 @@ int stk500_initialize(PROGRAMMER * pgm, AVRPART * p) } -int stk500_save(PROGRAMMER * pgm) +static int stk500_save(PROGRAMMER * pgm) { return 0; } -void stk500_restore(PROGRAMMER * pgm) +static void stk500_restore(PROGRAMMER * pgm) { return; } -void stk500_disable(PROGRAMMER * pgm) +static void stk500_disable(PROGRAMMER * pgm) { unsigned char buf[16]; int tries=0; @@ -588,13 +589,13 @@ void stk500_disable(PROGRAMMER * pgm) return; } -void stk500_enable(PROGRAMMER * pgm) +static void stk500_enable(PROGRAMMER * pgm) { return; } -int static stk500_setattr(int fd) +static int stk500_setattr(int fd) { int rc; struct termios termios; @@ -634,7 +635,7 @@ int static stk500_setattr(int fd) } -void stk500_open(PROGRAMMER * pgm, char * port) +static void stk500_open(PROGRAMMER * pgm, char * port) { int rc; @@ -672,7 +673,7 @@ void stk500_open(PROGRAMMER * pgm, char * port) } -void stk500_close(PROGRAMMER * pgm) +static void stk500_close(PROGRAMMER * pgm) { close(pgm->fd); pgm->fd = -1; @@ -726,8 +727,8 @@ static int stk500_loadaddr(PROGRAMMER * pgm, unsigned int addr) } -int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - int page_size, int n_bytes) +static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) { unsigned char buf[16]; int memtype; @@ -817,8 +818,8 @@ int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, } -int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - int page_size, int n_bytes) +static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) { unsigned char buf[16]; int memtype; @@ -960,7 +961,7 @@ static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value) } -void stk500_display(PROGRAMMER * pgm, char * p) +static void stk500_display(PROGRAMMER * pgm, char * p) { unsigned maj, min, hdw;