Submitted by Brett Hagman:

Add support for the "Wiring" board/bootloader
* wiring.c: New file.
* wiring.h: (Ditto.)
* Makefile.am: Add new files.
* stk500v2_private.h: Reorganize so some functions and struct
pdata are globally known.
* stk500v2.c: (Ditto.)
* stk500v2.h: (Ditto.)
* lexer.l: Add new programmer keywords.
* config_gram.y: (Ditto.)
* avrdude.conf.in: Add "wiring" programmer entry.
* avrdude.1: Document the new programmer.
* doc/avrdude.texi: (Ditto.)
* AUTHORS: Add Brett Hagman.




git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@987 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Joerg Wunsch 2011-08-26 20:22:09 +00:00
parent 822378d009
commit 86432b91d9
14 changed files with 405 additions and 53 deletions

View File

@ -20,5 +20,7 @@ Contributors:
Ville Voipio Ville Voipio
Hannes Weisbach Hannes Weisbach
Doug Springer Doug Springer
Brett Hagman
For minor contributions, please see the ChangeLog files. For minor contributions, please see the ChangeLog files.

View File

@ -1,3 +1,21 @@
2011-08-26 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Brett Hagman:
Add support for the "Wiring" board/bootloader
* wiring.c: New file.
* wiring.h: (Ditto.)
* Makefile.am: Add new files.
* stk500v2_private.h: Reorganize so some functions and struct
pdata are globally known.
* stk500v2.c: (Ditto.)
* stk500v2.h: (Ditto.)
* lexer.l: Add new programmer keywords.
* config_gram.y: (Ditto.)
* avrdude.conf.in: Add "wiring" programmer entry.
* avrdude.1: Document the new programmer.
* doc/avrdude.texi: (Ditto.)
* AUTHORS: Add Brett Hagman.
2011-08-26 Joerg Wunsch <j.gnu@uriah.heep.sax.de> 2011-08-26 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by an anonymous contributor on the mailinglist: Submitted by an anonymous contributor on the mailinglist:

View File

@ -152,7 +152,9 @@ libavrdude_a_SOURCES = \
usbtiny.h \ usbtiny.h \
usbtiny.c \ usbtiny.c \
update.h \ update.h \
update.c update.c \
wiring.h \
wiring.c
avrdude_SOURCES = \ avrdude_SOURCES = \
main.c \ main.c \

1
NEWS
View File

@ -16,6 +16,7 @@ Current:
- TPI programming through bitbang programmers (both, serial - TPI programming through bitbang programmers (both, serial
and parallel ones) and parallel ones)
- FT2232 (and relatives) based programmers (MPSSE bitbang mode) - FT2232 (and relatives) based programmers (MPSSE bitbang mode)
- Wiring environment (http://wiring.org.co/)
* Bugfixes * Bugfixes

View File

@ -107,6 +107,10 @@ Using firmware version 2, high-voltage programming is also supported,
both parallel and serial both parallel and serial
(programmer types stk500pp and stk500hvsp). (programmer types stk500pp and stk500hvsp).
.Pp .Pp
Wiring boards are supported, utilizing STK500 V2.x protocol, but
a simple DTR/RTS toggle is used to set the boards into programming mode.
The programmer type is ``wiring''.
.Pp
The Arduino (which is very similar to the STK500 1.x) is supported via The Arduino (which is very similar to the STK500 1.x) is supported via
its own programmer type specification ``arduino''. its own programmer type specification ``arduino''.
.Pp .Pp
@ -975,6 +979,18 @@ and
.Ar speed= .Ar speed=
parameters unavailable. parameters unavailable.
.El .El
.It Ar Wiring
When using the Wiring programmer type, the
following optional extended parameter is accepted:
.Bl -tag -offset indent -width indent
.It Ar snooze=<0..32767>
After performing the port open phase, AVRDUDE will wait/snooze for
.Ar snooze
milliseconds before continuing to the protocol sync phase.
No toggling of DTR/RTS is performed if
.Ar snooze
is greater than 0.
.El
.El .El
.Sh FILES .Sh FILES
.Bl -tag -offset indent -width /dev/ppi0XXX .Bl -tag -offset indent -width /dev/ppi0XXX

View File

@ -21,7 +21,7 @@
# jtagmki | jtagmkii | jtagmkii_isp | jtagmkii_dw | # jtagmki | jtagmkii | jtagmkii_isp | jtagmkii_dw |
# jtagmkII_avr32 | jtagmkii_pdi | # jtagmkII_avr32 | jtagmkii_pdi |
# dragon_dw | dragon_jtag | dragon_isp | dragon_pp | # dragon_dw | dragon_jtag | dragon_isp | dragon_pp |
# dragon_hvsp | dragon_pdi | arduino; # programmer type # dragon_hvsp | dragon_pdi | arduino | wiring; # programmer type
# baudrate = <num> ; # baudrate for avr910-programmer # baudrate = <num> ; # baudrate for avr910-programmer
# vcc = <num1> [, <num2> ... ] ; # pin number(s) # vcc = <num1> [, <num2> ... ] ; # pin number(s)
# reset = <num> ; # pin number # reset = <num> ; # pin number
@ -322,6 +322,15 @@ default_serial = "@DEFAULT_SER_PORT@";
# PROGRAMMER DEFINITIONS # PROGRAMMER DEFINITIONS
# #
# http://wiring.org.co/
# Basically STK500v2 protocol, with some glue to trigger the
# bootloader.
programmer
id = "wiring";
desc = "Wiring";
type = wiring;
;
programmer programmer
id = "arduino"; id = "arduino";
desc = "Arduino"; desc = "Arduino";

View File

@ -40,6 +40,7 @@
#include "arduino.h" #include "arduino.h"
#include "buspirate.h" #include "buspirate.h"
#include "stk500v2.h" #include "stk500v2.h"
#include "wiring.h"
#include "stk500generic.h" #include "stk500generic.h"
#include "avr910.h" #include "avr910.h"
#include "butterfly.h" #include "butterfly.h"
@ -162,6 +163,7 @@ static int parse_cmdbits(OPCODE * op);
%token K_TYPE %token K_TYPE
%token K_VCC %token K_VCC
%token K_VFYLED %token K_VFYLED
%token K_WIRING
%token K_NO %token K_NO
%token K_YES %token K_YES
@ -416,6 +418,12 @@ prog_parm :
} }
} | } |
K_TYPE TKN_EQUAL K_WIRING {
{
wiring_initpgm(current_prog);
}
} |
K_TYPE TKN_EQUAL K_STK500HVSP { K_TYPE TKN_EQUAL K_STK500HVSP {
{ {
stk500hvsp_initpgm(current_prog); stk500hvsp_initpgm(current_prog);

View File

@ -214,6 +214,10 @@ option might be required to achieve a stable ISP communication.
For ATxmega devices, the AVR Dragon is supported in PDI mode, provided it For ATxmega devices, the AVR Dragon is supported in PDI mode, provided it
has a firmware version of at least 6.11 (decimal). has a firmware version of at least 6.11 (decimal).
Wiring boards are supported, utilizing STK500 V2.x protocol, but
a simple DTR/RTS toggle to set the boards into programming mode.
The programmer type is ``wiring''.
The Arduino (which is very similar to the STK500 1.x) is supported via The Arduino (which is very similar to the STK500 1.x) is supported via
its own programmer type specification ``arduino''. its own programmer type specification ``arduino''.
@ -571,6 +575,9 @@ USBtiny simple USB programmer,@*
@url{http://www.ladyada.net/make/usbtinyisp/} @url{http://www.ladyada.net/make/usbtinyisp/}
@item @code{xil} @tab @item @code{xil} @tab
Xilinx JTAG cable Xilinx JTAG cable
@item @code{wiring} @tab
Wiring board, utilizing STK500 V2.x protocol,@*
@url{http://wiring.org.co/}
@end multitable @end multitable
@ -1014,6 +1021,17 @@ and
parameters unavailable. parameters unavailable.
@end table @end table
@item Wiring
When using the Wiring programmer type, the
following optional extended parameter is accepted:
@table @code
@item @samp{snooze=@var{0..32767}}
After performing the port open phase, AVRDUDE will wait/snooze for
@var{snooze} milliseconds before continuing to the protocol sync phase.
No toggling of DTR/RTS is performed if @var{snooze} > 0.
@end table
@end table @end table
@page @page

View File

@ -206,6 +206,7 @@ usbvendor { yylval=NULL; return K_USBVENDOR; }
usbvid { yylval=NULL; return K_USBVID; } usbvid { yylval=NULL; return K_USBVID; }
vcc { yylval=NULL; return K_VCC; } vcc { yylval=NULL; return K_VCC; }
vfyled { yylval=NULL; return K_VFYLED; } vfyled { yylval=NULL; return K_VFYLED; }
wiring { yylval=NULL; return K_WIRING; }
timeout { yylval=NULL; return K_TIMEOUT; } timeout { yylval=NULL; return K_TIMEOUT; }
stabdelay { yylval=NULL; return K_STABDELAY; } stabdelay { yylval=NULL; return K_STABDELAY; }

View File

@ -69,6 +69,12 @@
#define STK500V2_XTAL 7372800U #define STK500V2_XTAL 7372800U
// Timeout (in seconds) for waiting for serial response
#define SERIAL_TIMEOUT 2
// Retry count
#define RETRIES 5
#if 0 #if 0
#define DEBUG(...) fprintf(stderr, __VA_ARGS__) #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#else #else
@ -87,46 +93,6 @@ enum hvmode
}; };
/*
* Private data for this programmer.
*/
struct pdata
{
/*
* See stk500pp_read_byte() for an explanation of the flash and
* EEPROM page caches.
*/
unsigned char *flash_pagecache;
unsigned long flash_pageaddr;
unsigned int flash_pagesize;
unsigned char *eeprom_pagecache;
unsigned long eeprom_pageaddr;
unsigned int eeprom_pagesize;
unsigned char command_sequence;
enum
{
PGMTYPE_UNKNOWN,
PGMTYPE_STK500,
PGMTYPE_AVRISP,
PGMTYPE_AVRISP_MKII,
PGMTYPE_JTAGICE_MKII,
PGMTYPE_STK600,
}
pgmtype;
AVRPART *lastpart;
/*
* Chained pdata for the JTAG ICE mkII backend. This is used when
* calling the backend functions for ISP/HVSP/PP programming
* functionality of the JTAG ICE mkII and AVR Dragon.
*/
void *chained_pdata;
};
#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) #define PDATA(pgm) ((struct pdata *)(pgm->cookie))
@ -314,7 +280,7 @@ static void stk600_setup_xprog(PROGRAMMER * pgm);
static void stk600_setup_isp(PROGRAMMER * pgm); static void stk600_setup_isp(PROGRAMMER * pgm);
static int stk600_xprog_program_enable(PROGRAMMER * pgm, AVRPART * p); static int stk600_xprog_program_enable(PROGRAMMER * pgm, AVRPART * p);
static void stk500v2_setup(PROGRAMMER * pgm) void stk500v2_setup(PROGRAMMER * pgm)
{ {
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) { if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
fprintf(stderr, fprintf(stderr,
@ -350,7 +316,7 @@ static void stk500v2_jtagmkII_setup(PROGRAMMER * pgm)
PDATA(pgm)->chained_pdata = theircookie; PDATA(pgm)->chained_pdata = theircookie;
} }
static void stk500v2_teardown(PROGRAMMER * pgm) void stk500v2_teardown(PROGRAMMER * pgm)
{ {
free(pgm->cookie); free(pgm->cookie);
} }
@ -486,7 +452,7 @@ static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
} }
static int stk500v2_drain(PROGRAMMER * pgm, int display) int stk500v2_drain(PROGRAMMER * pgm, int display)
{ {
return serial_drain(&pgm->fd, display); return serial_drain(&pgm->fd, display);
} }
@ -554,7 +520,7 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize)
int timeout = 0; int timeout = 0;
unsigned char c, checksum = 0; unsigned char c, checksum = 0;
long timeoutval = 5; // seconds long timeoutval = SERIAL_TIMEOUT; // seconds
struct timeval tv; struct timeval tv;
double tstart, tnow; double tstart, tnow;
@ -647,7 +613,7 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize)
tnow = tv.tv_sec; tnow = tv.tv_sec;
if (tnow-tstart > timeoutval) { // wuff - signed/unsigned/overflow if (tnow-tstart > timeoutval) { // wuff - signed/unsigned/overflow
timedout: timedout:
fprintf(stderr, "%s: stk500_2_ReceiveMessage(): timeout\n", fprintf(stderr, "%s: stk500v2_ReceiveMessage(): timeout\n",
progname); progname);
return -1; return -1;
} }
@ -660,7 +626,7 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize)
static int stk500v2_getsync(PROGRAMMER * pgm) { int stk500v2_getsync(PROGRAMMER * pgm) {
int tries = 0; int tries = 0;
unsigned char buf[1], resp[32]; unsigned char buf[1], resp[32];
int status; int status;
@ -713,7 +679,7 @@ retry:
progname, pgmname[PDATA(pgm)->pgmtype]); progname, pgmname[PDATA(pgm)->pgmtype]);
return 0; return 0;
} else { } else {
if (tries > 33) { if (tries > RETRIES) {
fprintf(stderr, fprintf(stderr,
"%s: stk500v2_getsync(): can't communicate with device: resp=0x%02x\n", "%s: stk500v2_getsync(): can't communicate with device: resp=0x%02x\n",
progname, resp[0]); progname, resp[0]);
@ -724,7 +690,7 @@ retry:
// or if we got a timeout // or if we got a timeout
} else if (status == -1) { } else if (status == -1) {
if (tries > 33) { if (tries > RETRIES) {
fprintf(stderr,"%s: stk500v2_getsync(): timeout communicating with programmer\n", fprintf(stderr,"%s: stk500v2_getsync(): timeout communicating with programmer\n",
progname); progname);
return -1; return -1;
@ -733,7 +699,7 @@ retry:
// or any other error // or any other error
} else { } else {
if (tries > 33) { if (tries > RETRIES) {
fprintf(stderr,"%s: stk500v2_getsync(): error communicating with programmer: (%d)\n", fprintf(stderr,"%s: stk500v2_getsync(): error communicating with programmer: (%d)\n",
progname,status); progname,status);
} else } else
@ -750,7 +716,7 @@ static int stk500v2_command(PROGRAMMER * pgm, unsigned char * buf,
int status; int status;
DEBUG("STK500V2: stk500v2_command("); DEBUG("STK500V2: stk500v2_command(");
for (i=0;i<len;i++) DEBUG("0x%02hhx ",buf[i]); for (i=0;i<len;i++) DEBUG("0x%02x ",buf[i]);
DEBUG(", %d)\n",len); DEBUG(", %d)\n",len);
retry: retry:
@ -840,7 +806,7 @@ retry:
// otherwise try to sync up again // otherwise try to sync up again
status = stk500v2_getsync(pgm); status = stk500v2_getsync(pgm);
if (status != 0) { if (status != 0) {
if (tries > 33) { if (tries > RETRIES) {
fprintf(stderr,"%s: stk500v2_command(): failed miserably to execute command 0x%02x\n", fprintf(stderr,"%s: stk500v2_command(): failed miserably to execute command 0x%02x\n",
progname,buf[0]); progname,buf[0]);
return -1; return -1;

View File

@ -38,6 +38,11 @@ void stk600_initpgm (PROGRAMMER * pgm);
void stk600hvsp_initpgm (PROGRAMMER * pgm); void stk600hvsp_initpgm (PROGRAMMER * pgm);
void stk600pp_initpgm (PROGRAMMER * pgm); void stk600pp_initpgm (PROGRAMMER * pgm);
void stk500v2_setup(PROGRAMMER * pgm);
void stk500v2_teardown(PROGRAMMER * pgm);
int stk500v2_drain(PROGRAMMER * pgm, int display);
int stk500v2_getsync(PROGRAMMER * pgm);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -9,6 +9,8 @@
//* //*
//************************************************************************** //**************************************************************************
#include "pgm.h"
// *****************[ STK message constants ]*************************** // *****************[ STK message constants ]***************************
#define MESSAGE_START 0x1B //= ESC = 27 decimal #define MESSAGE_START 0x1B //= ESC = 27 decimal
@ -278,3 +280,43 @@
#define ANSWER_CKSUM_ERROR 0xB0 #define ANSWER_CKSUM_ERROR 0xB0
/*
* Private data for this programmer.
*/
struct pdata
{
/*
* See stk500pp_read_byte() for an explanation of the flash and
* EEPROM page caches.
*/
unsigned char *flash_pagecache;
unsigned long flash_pageaddr;
unsigned int flash_pagesize;
unsigned char *eeprom_pagecache;
unsigned long eeprom_pageaddr;
unsigned int eeprom_pagesize;
unsigned char command_sequence;
enum
{
PGMTYPE_UNKNOWN,
PGMTYPE_STK500,
PGMTYPE_AVRISP,
PGMTYPE_AVRISP_MKII,
PGMTYPE_JTAGICE_MKII,
PGMTYPE_STK600,
}
pgmtype;
AVRPART *lastpart;
/*
* Chained pdata for the JTAG ICE mkII backend. This is used when
* calling the backend functions for ISP/HVSP/PP programming
* functionality of the JTAG ICE mkII and AVR Dragon.
*/
void *chained_pdata;
};

235
wiring.c Normal file
View File

@ -0,0 +1,235 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2011 Brett Hagman
*
* 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$ */
/*
* avrdude interface for Wiring bootloaders
*
* http://wiring.org.co/
*
* The Wiring bootloader uses a near-complete STK500v2 protocol.
* (Only ISP specific programming commands are not implemented
* e.g. chip erase).
* DTR and RTS signals are diddled to set the board into programming mode.
*
* Also includes an extended parameter to introduce a delay after opening
* to accommodate multi-layered programmers/bootloaders. If the extended
* parameter 'snooze' > 0, then no DTR/RTS toggle takes place, and
* AVRDUDE will wait that amount of time in milliseconds before syncing.
*
* Unfortunately, there is no way to easily chain private programmer data
* when we "inherit" programmer types as we have (stk500v2). Sooooo, a
* *cringe* global variable is used to store the snooze time.
*/
#include "ac_cfg.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "avrdude.h"
#include "pgm.h"
#include "stk500v2_private.h"
#include "stk500v2.h"
#include "serial.h"
/*
* Private data for this programmer.
*/
struct wiringpdata
{
/*
* We just have the single snooze integer to carry around for now.
*/
int snoozetime;
};
/* wiringpdata is our private data */
/* pdata is stk500v2's private data (inherited) */
#define WIRINGPDATA(x) ((struct wiringpdata *)(x))
#define STK500V2PDATA(pgm) ((struct pdata *)(pgm->cookie))
static void wiring_setup(PROGRAMMER * pgm)
{
void *mycookie;
/*
* First, have STK500v2 backend allocate its own private data.
*/
stk500v2_setup(pgm);
/*
* Now prepare our data
*/
if ((mycookie = malloc(sizeof(struct wiringpdata))) == 0) {
fprintf(stderr,
"%s: wiring_setup(): Out of memory allocating private data\n",
progname);
exit(1);
}
memset(mycookie, 0, sizeof(struct wiringpdata));
WIRINGPDATA(mycookie)->snoozetime = 0;
/*
* Store our own cookie in a safe place for the time being.
*/
STK500V2PDATA(pgm)->chained_pdata = mycookie;
}
static void wiring_teardown(PROGRAMMER * pgm)
{
void *mycookie;
mycookie = STK500V2PDATA(pgm)->chained_pdata;
free(mycookie);
stk500v2_teardown(pgm);
}
static int wiring_parseextparms(PROGRAMMER * pgm, LISTID extparms)
{
LNODEID ln;
const char *extended_param;
int rv = 0;
void *mycookie = STK500V2PDATA(pgm)->chained_pdata;
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
extended_param = ldata(ln);
if (strncmp(extended_param, "snooze=", strlen("snooze=")) == 0) {
int newsnooze;
if (sscanf(extended_param, "snooze=%i", &newsnooze) != 1 ||
newsnooze < 0) {
fprintf(stderr,
"%s: wiring_parseextparms(): invalid snooze time '%s'\n",
progname, extended_param);
rv = -1;
continue;
}
if (verbose >= 2) {
fprintf(stderr,
"%s: wiring_parseextparms(): snooze time set to %d ms\n",
progname, newsnooze);
}
WIRINGPDATA(mycookie)->snoozetime = newsnooze;
continue;
}
fprintf(stderr,
"%s: wiring_parseextparms(): invalid extended parameter '%s'\n",
progname, extended_param);
rv = -1;
}
return rv;
}
static int wiring_open(PROGRAMMER * pgm, char * port)
{
int timetosnooze;
void *mycookie = STK500V2PDATA(pgm)->chained_pdata;
strcpy(pgm->port, port);
serial_open(port, pgm->baudrate ? pgm->baudrate: 115200, &pgm->fd);
/* If we have a snoozetime, then we wait and do NOT toggle DTR/RTS */
if (WIRINGPDATA(mycookie)->snoozetime > 0) {
timetosnooze = WIRINGPDATA(mycookie)->snoozetime;
if (verbose >= 2) {
fprintf(stderr,
"%s: wiring_open(): snoozing for %d ms\n",
progname, timetosnooze);
}
while (timetosnooze--)
usleep(1000);
if (verbose >= 2) {
fprintf(stderr,
"%s: wiring_open(): done snoozing\n",
progname);
}
} else {
/* Perform Wiring programming mode RESET. */
/* This effectively *releases* both DTR and RTS. */
/* i.e. both DTR and RTS rise to a HIGH logic level */
/* since they are active LOW signals. */
if (verbose >= 2) {
fprintf(stderr,
"%s: wiring_open(): releasing DTR/RTS\n",
progname);
}
serial_set_dtr_rts(&pgm->fd, 0);
usleep(50*1000);
/* After releasing for 50 milliseconds, DTR and RTS */
/* are asserted (i.e. logic LOW) again. */
if (verbose >= 2) {
fprintf(stderr,
"%s: wiring_open(): asserting DTR/RTS\n",
progname);
}
serial_set_dtr_rts(&pgm->fd, 1);
usleep(50*1000);
}
/* drain any extraneous input */
stk500v2_drain(pgm, 0);
if (stk500v2_getsync(pgm) < 0)
return -1;
return 0;
}
static void wiring_close(PROGRAMMER * pgm)
{
serial_set_dtr_rts(&pgm->fd, 0);
serial_close(&pgm->fd);
pgm->fd.ifd = -1;
}
void wiring_initpgm(PROGRAMMER * pgm)
{
/* The Wiring bootloader uses a near-complete STK500v2 protocol. */
stk500v2_initpgm(pgm);
strcpy(pgm->type, "Wiring");
pgm->open = wiring_open;
pgm->close = wiring_close;
pgm->setup = wiring_setup;
pgm->teardown = wiring_teardown;
pgm->parseextparams = wiring_parseextparms;
}

29
wiring.h Normal file
View File

@ -0,0 +1,29 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2011 Brett Hagman
*
* 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 wiring_h__
#define wiring_h__
void wiring_initpgm(PROGRAMMER * pgm);
#endif