From 52ae1740731b7dfd39ce877d8c928a8879cfe1fd Mon Sep 17 00:00:00 2001 From: "Brian S. Dean" Date: Sat, 5 Aug 2000 05:12:50 +0000 Subject: [PATCH] This commit was generated by cvs2svn to compensate for changes in r2, which included commits to RCS files with non-trunk default branches. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@3 81a1dc3b-b13d-400b-aceb-764788c761c2 --- Makefile | 16 ++ avrprog.c | 716 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 732 insertions(+) create mode 100644 Makefile create mode 100644 avrprog.c diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..fabd1ac1 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +# +# $Id$ +# + +TARGET = avrprog + +all : ${TARGET} + +CFLAGS = -Wall + +${TARGET} : avrprog.c + ${CC} ${CFLAGS} -o ${TARGET} avrprog.c + +clean : + rm -f *.o ${TARGET} *~ + diff --git a/avrprog.c b/avrprog.c new file mode 100644 index 00000000..5898b946 --- /dev/null +++ b/avrprog.c @@ -0,0 +1,716 @@ +/* + * Copyright 2000, Brian Dean + * All Rights Reserved. + */ + +/* $Id$ */ + +/* + * Code to program an Atmel AVR device using the parallel port. + * + * Make the following connections: + * + * Pin 2 -> PB7(SCK) CLOCK IN (data bit 0) + * Pin 3 -> PB5(MOSI) Instruction input (data bit 1) + * Pin 4 -> /RESET (data bit 2) + * Pin 10 <- PB6(MISO) Data out (status bit 6) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PARALLEL "/dev/ppi0" + +char * progname; + + +#define AVR_CLOCK 0x01 /* bit 0 of data register */ +#define AVR_INSTR 0x02 /* bit 1 of data register */ +#define AVR_RESET 0x04 /* bit 2 of data register */ +#define AVR_DATA 0x40 /* bit 6 of status register */ + + +enum { + PPIDATA, + PPICTRL, + PPISTATUS +}; + + +enum { + AVR_EEPROM, + AVR_FLASH, + AVR_FLASH_LO, + AVR_FLASH_HI +}; + + +int dprintf ( FILE * f, char * format, ... ) +{ +#if DEBUG + va_list ap; + int rc; + + va_start(ap,format); + rc = vfprintf(f,format,ap); + va_end(ap); + + return rc; +#else + return 0; +#endif +} + + +int ppi_getops ( int reg, unsigned long * get, unsigned long * set ) +{ + switch (reg) { + case PPIDATA: + *set = PPISDATA; + *get = PPIGDATA; + break; + case PPICTRL: + *set = PPISCTRL; + *get = PPIGCTRL; + break; + case PPISTATUS: + *set = PPISSTATUS; + *get = PPIGSTATUS; + break; + default: + fprintf ( stderr, "%s: avr_set(): invalid register=%d\n", + progname, reg ); + return -1; + break; + } + + return 0; +} + + +int ppi_set ( int fd, int reg, int bit ) +{ + unsigned char v; + unsigned long get, set; + int rc; + + rc = ppi_getops ( reg, &get, &set ); + if (rc) + return -1; + + ioctl(fd, get, &v); + v |= bit; + ioctl(fd, set, &v); + + return 0; +} + + +int ppi_clr ( int fd, int reg, int bit ) +{ + unsigned char v; + unsigned long get, set; + int rc; + + rc = ppi_getops ( reg, &get, &set ); + if (rc) + return -1; + + ioctl(fd, get, &v); + v &= ~bit; + ioctl(fd, set, &v); + + return 0; +} + + +int ppi_get ( int fd, int reg, int bit ) +{ + unsigned char v; + unsigned long get, set; + int rc; + + rc = ppi_getops ( reg, &get, &set ); + if (rc) + return -1; + + ioctl(fd, get, &v); + v &= bit; + + return (v == bit); +} + + +int ppi_toggle ( int fd, int reg, int bit ) +{ + unsigned char v; + unsigned long get, set; + int rc; + + rc = ppi_getops ( reg, &get, &set ); + if (rc) + return -1; + + ioctl(fd, get, &v); + v |= bit; + ioctl(fd, set, &v); + + v &= ~bit; + ioctl(fd, set, &v); + + return 0; +} + + +int avr_txrx_bit ( int fd, int bit ) +{ + unsigned char d; + int r; + + ioctl(fd, PPIGDATA, &d); + + r = ppi_get(fd, PPISTATUS, AVR_DATA); + + if (bit) + ppi_set(fd, PPIDATA, AVR_INSTR); + else + ppi_clr(fd, PPIDATA, AVR_INSTR); + + ppi_toggle(fd, PPIDATA, AVR_CLOCK); + + return r; +} + + +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; + r = avr_txrx_bit ( fd, b ); + rbyte = rbyte | (r << (7-i)); + } + + return rbyte; +} + + +unsigned char avr_read_byte ( int fd, unsigned short addr, int memtype ) +{ + unsigned char r; + + switch (memtype) { + case AVR_FLASH_LO: + avr_txrx(fd, 0x20); + break; + case AVR_FLASH_HI: + avr_txrx(fd, 0x28); + break; + case AVR_EEPROM: + avr_txrx(fd, 0xa0); + addr &= 0x7f; + break; + default: + fprintf(stderr, "%s: avr_read_byte(); internal error: invalid memtype=%d\n", + progname, memtype); + exit(1); + break; + } + + avr_txrx(fd, addr >> 8); /* high order bits of address */ + avr_txrx(fd, addr & 0x0ff); /* low order bits of address */ + r = avr_txrx(fd, 0); /* don't care */ + + return r; +} + + +int avr_read ( int fd, int memtype, unsigned start, unsigned n, + unsigned char * buf, int bufsize ) +{ + unsigned char rbyte; + unsigned short data; + unsigned short end, i, bi; + + switch (memtype) { + case AVR_FLASH : + case AVR_EEPROM : + break; + default: + fprintf(stderr, "%s: avr_read(); internal error: invalid memtype=%d\n", + progname, memtype); + exit(1); + break; + } + + end = start+n; + + bi = 0; + + for (i=start; i> 8); /* high order bits of address */ + avr_txrx(fd, addr & 0x0ff); /* low order bits of address */ + avr_txrx(fd, data); /* data */ + + tries = 0; + ready = 0; + while (!ready) { + usleep(5000); /* flash write delay */ + r = avr_read_byte ( fd, addr, memtype ); + if (data == 0x7f) { + usleep(20000); + ready = 1; + } + else if (r == data) { + ready = 1; + } + tries++; + if (!ready && tries > 10) { + fprintf(stderr, "**" ); + ready = 1; + } + } + + return 0; +} + + +int avr_write ( int fd, int memtype, unsigned start, + unsigned char * buf, int size ) +{ + unsigned char data; + unsigned short end, i, bi; + + switch (memtype) { + case AVR_FLASH : + end = start+size/2; + break; + case AVR_EEPROM : + end = start+size; + break; + default: + fprintf(stderr, "%s: avr_write(); internal error: invalid memtype=%d\n", + progname, memtype); + exit(1); + break; + } + + bi = 0; + + for (i=start; i