Add initial support for the Atmel STK600, for

"classic" AVRs (AT90, ATtiny, ATmega) in both,
ISP and high-voltage programming modes.
* Makefile.am: Add -lm.
* avrdude.conf.in: Add stk600, stk600pp, and stk600hvsp.
* config_gram.y: Add support for the stk600* keywords.
* lexer.l: (Ditto.)
* pgm.h: Add the "chan" parameter to set_varef().
* stk500.c: (Ditto.)
* serial.h: Add USB endpoint support to struct filedescriptor.
* stk500v2.c: Implement the meat of the STK600 support.
* stk500v2.h: Add new prototypes for stk600*() programmers.
* stk500v2_private.h: Add new constants used in the STK600.
* term.c: Add AREF channel support.
* usb_libusb.c: Automatically determine the correct write
endpoint ID, the STK600 uses 0x83 while all other tools use
0x82.  Propagate the EP to use through struct filedescriptor.
* usbdevs.h: Add the STK600 USB product ID.
* tools/get-stk600-cards.xsl: XSL transformation for
targetboards.xml to obtain the list of socket and routing
card IDs, to be used in stk500v2.c (for displaying the
names).
* tools/get-stk600-devices.xsl: XSL transformation for
targetboards.xml to obtain the table of socket/routing cards
and their respective AVR device support for doc/avrdude.texi.
* avrdude.1: Document all the STK600 stuff.
* doc/avrdude.texi: Ditto.  Added a new chapter for
Programmer Specific Information.

Thanks to Eirik Rasmussen from Atmel Norway for his support in
getting this code running within that short amount of time!


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@768 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Joerg Wunsch 2008-03-14 13:00:08 +00:00
parent 255f873185
commit ec2df64017
19 changed files with 1101 additions and 80 deletions

View File

@ -1,3 +1,34 @@
2008-03-14 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Add initial support for the Atmel STK600, for
"classic" AVRs (AT90, ATtiny, ATmega) in both,
ISP and high-voltage programming modes.
* Makefile.am: Add -lm.
* avrdude.conf.in: Add stk600, stk600pp, and stk600hvsp.
* config_gram.y: Add support for the stk600* keywords.
* lexer.l: (Ditto.)
* pgm.h: Add the "chan" parameter to set_varef().
* stk500.c: (Ditto.)
* serial.h: Add USB endpoint support to struct filedescriptor.
* stk500v2.c: Implement the meat of the STK600 support.
* stk500v2.h: Add new prototypes for stk600*() programmers.
* stk500v2_private.h: Add new constants used in the STK600.
* term.c: Add AREF channel support.
* usb_libusb.c: Automatically determine the correct write
endpoint ID, the STK600 uses 0x83 while all other tools use
0x82. Propagate the EP to use through struct filedescriptor.
* usbdevs.h: Add the STK600 USB product ID.
* tools/get-stk600-cards.xsl: XSL transformation for
targetboards.xml to obtain the list of socket and routing
card IDs, to be used in stk500v2.c (for displaying the
names).
* tools/get-stk600-devices.xsl: XSL transformation for
targetboards.xml to obtain the table of socket/routing cards
and their respective AVR device support for doc/avrdude.texi.
* avrdude.1: Document all the STK600 stuff.
* doc/avrdude.texi: Ditto. Added a new chapter for
Programmer Specific Information.
2008-01-26 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* stk500v2.c (stk500v2_recv): Make length computation unsigned so

View File

@ -52,7 +52,7 @@ avrdude_CFLAGS = @ENABLE_WARNINGS@
libavrdude_a_CFLAGS = @ENABLE_WARNINGS@
avrdude_LDADD = $(top_builddir)/$(noinst_LIBRARIES) @LIBUSB@ @LIBHID@
avrdude_LDADD = $(top_builddir)/$(noinst_LIBRARIES) @LIBUSB@ @LIBHID@ -lm
bin_PROGRAMS = avrdude

3
NEWS
View File

@ -13,6 +13,9 @@ Current:
* Add support for JTAG daisy-chains, using the -x daisychain=
option.
* Add support for the Atmel STK600 for "classic" AVRs (AT90, ATtiny,
ATmega), using either ISP or high-voltage programming modes.
Version 5.5:
* Add support for the USBtinyISP programmer (patch #6233)

View File

@ -19,7 +19,7 @@
.\"
.\" $Id$
.\"
.Dd DATE November 6, 2007
.Dd DATE March 14, 2008
.Os
.Dt AVRDUDE 1
.Sh NAME
@ -59,6 +59,7 @@ microcontrollers.
.Nm Avrdude
supports Atmel's STK500 programmer,
Atmel's AVRISP and AVRISP mkII devices,
Atmel's STK600,
Atmel's JTAG ICE (both mkI and mkII, the latter also in ISP mode),
programmers complying to AppNote AVR910 and AVR109 (including the Butterfly),
as well as a simple hard-wired
@ -106,6 +107,9 @@ Using firmware version 2, high-voltage programming is also supported,
both parallel and serial
(programmer types stk500pp and stk500hvsp).
.Pp
Atmel's STK600 programmer is supported in ISP and high-voltage
programming modes, and connects through the USB.
.Pp
The simple serial programmer described in Atmel's application note
AVR910, and the bootloader described in Atmel's application note
AVR109 (which is also used by the AVR Butterfly evaluation board), are
@ -161,7 +165,7 @@ been code-protected previously, of course) and store the data in a
file. Finally, a ``terminal'' mode is available that allows one to
interactively communicate with the MCU, and to display or program
individual memory cells.
On the STK500 programmer, several operational parameters (target supply
On the STK500 and STK600 programmer, several operational parameters (target supply
voltage, target Aref voltage, master clock) can be examined and changed
from within terminal mode as well.
.Ss Options
@ -661,15 +665,19 @@ device, read/write timing, etc.
Set the target's supply voltage to
.Ar voltage
Volts.
.Em Only supported on the STK500 programmer.
.It Ar varef voltage
.Em Only supported on the STK500 and STK600 programmer.
.It Ar varef Op channel Ar voltage
Set the adjustable voltage source to
.Ar voltage
Volts.
This voltage is normally used to drive the target's
.Em Aref
input on the STK500.
.Em Only supported on the STK500 programmer.
On the Atmel STK600, two reference voltages are available, which
can be selected by the optional
.Ar channel
argument (either 0 or 1).
.Em Only supported on the STK500 and STK600 programmer.
.It Ar fosc freq Ns Op M Ns \&| Ns k
Set the master oscillator to
.Ar freq
@ -679,12 +687,12 @@ An optional trailing letter
multiplies by 1E6, a trailing letter
.Ar \&k
by 1E3.
.Em Only supported on the STK500 programmer.
.Em Only supported on the STK500 and STK600 programmer.
.It Ar fosc off
Turn the master oscillator off.
.Em Only supported on the STK500 programmer.
.Em Only supported on the STK500 and STK600 programmer.
.It Ar sck period
.Em STK500 programmer only:
.Em STK500 and STK600 programmer only:
Set the SCK clock period to
.Ar period
microseconds.
@ -699,7 +707,7 @@ software signs off from the JTAG ICE.
This parameter can also be used on the JTAG ICE mkII to specify the
ISP clock period when operating the ICE in ISP mode.
.It Ar parms
.Em STK500 programmer only:
.Em STK500 and STK600 programmer only:
Display the current voltage and master oscillator parameters.
.Pp
.Em JTAG ICE only:
@ -844,7 +852,7 @@ Page-mode programming the EEPROM through JTAG (i.e. through an
.Fl U
option) requires a prior chip erase.
This is an inherent feature of the way JTAG EEPROM programming works.
This also applies to the STK500 in parallel programming mode.
This also applies to the STK500 and STK600 in parallel programming mode.
.Pp
The USBasp and USBtinyISP drivers do not offer any option to distinguish multiple
devices connected simultaneously, so effectively only a single device

View File

@ -16,6 +16,7 @@
# id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
# desc = <description> ; # quoted string
# type = par | stk500 | stk500v2 | stk500pp | stk500hvsp | stk500generic |
# stk600 | stk600pp | stk600hvsp |
# avr910 | butterfly | usbasp |
# jtagmki | jtagmkii | jtagmkii_isp | jtagmkii_dw |
# dragon_dw | dragon_jtag | dragon_isp | dragon_pp |
@ -367,6 +368,24 @@ programmer
type = stk500hvsp;
;
programmer
id = "stk600";
desc = "Atmel STK600";
type = stk600;
;
programmer
id = "stk600pp";
desc = "Atmel STK600 in parallel programming mode";
type = stk600pp;
;
programmer
id = "stk600hvsp";
desc = "Atmel STK600 in high-voltage serial programming mode";
type = stk600hvsp;
;
programmer
id = "avr910";
desc = "Atmel Low Cost Serial Programmer";

View File

@ -135,6 +135,9 @@ static int parse_cmdbits(OPCODE * op);
%token K_STK500PP
%token K_STK500V2
%token K_STK500GENERIC
%token K_STK600
%token K_STK600HVSP
%token K_STK600PP
%token K_AVR910
%token K_USBASP
%token K_USBTINY
@ -411,6 +414,24 @@ prog_parm :
}
} |
K_TYPE TKN_EQUAL K_STK600 {
{
stk600_initpgm(current_prog);
}
} |
K_TYPE TKN_EQUAL K_STK600HVSP {
{
stk600hvsp_initpgm(current_prog);
}
} |
K_TYPE TKN_EQUAL K_STK600PP {
{
stk600pp_initpgm(current_prog);
}
} |
K_TYPE TKN_EQUAL K_AVR910 {
{
avr910_initpgm(current_prog);

View File

@ -30,7 +30,7 @@ For avrdude version @value{VERSION}, @value{UPDATED}.
Copyright @copyright{} 2003, 2005 Brian Dean
Copyright @copyright{} 2006, 2007 J@"org Wunsch
Copyright @copyright{} 2006 - 2008 J@"org Wunsch
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@ -67,7 +67,7 @@ Use @uref{http://savannah.nongnu.org/bugs/?group=avrdude} to report bugs.
Copyright @copyright{} 2003,2005 Brian S. Dean
Copyright @copyright{} 2006 J@"org Wunsch
Copyright @copyright{} 2006 - 2008 J@"org Wunsch
@sp 2
Permission is granted to make and distribute verbatim copies of
@ -113,6 +113,7 @@ Copyright @copyright{} 2006 J@"org Wunsch
* Command Line Options::
* Terminal Mode Operation::
* Configuration File::
* Programmer Specific Information::
* Platform Dependent Information::
* Troubleshooting::
@end menu
@ -143,6 +144,7 @@ programming fuse/lock bits, etc.
AVRDUDE supports the following basic programmer types: Atmel's STK500,
Atmel's AVRISP and AVRISP mkII devices,
Atmel's STK600,
Atmel's JTAG ICE (both mkI and mkII, the latter also in ISP mode), appnote
avr910, appnote avr109 (including the AVR Butterfly),
serial bit-bang adapters,
@ -164,7 +166,10 @@ emulated on top of USB is likely to not work at all, or to work
abysmally slow.
The STK500, JTAG ICE, avr910, and avr109/butterfly use the serial port to communicate with the PC.
The STK500, JTAG ICE, and avr910 contain on-board logic to control the programming of the target
The STK600, JTAG ICE mkII, AVRISP mkII, USBasp, and USBtinyISP
programmers communicate through the USB, using @code{libusb} as a
platform abstraction layer.
The STK500, STK600, JTAG ICE, and avr910 contain on-board logic to control the programming of the target
device.
The avr109 bootloader implements a protocol similar to avr910, but is
actually implemented in the boot area of the target's flash ROM, as
@ -186,7 +191,6 @@ For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported.
See below for the limitations of debugWire.
The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP, debugWire).
(High-voltage programming is not yet supported.)
When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a
JTAG ICE mkII, so all device-specific comments for that device
will apply as well.
@ -463,6 +467,12 @@ Atmel STK500 in parallel programming mode (version 2.xfirmware only)
Atmel STK500, running a version 1.x firmware
@item @code{stk500v2} @tab
Atmel STK500, running a version 2.x firmware
@item @code{stk600} @tab
Atmel STK600 in ISP mode
@item @code{stk600hvsp} @tab
Atmel STK600 in high-voltage serial programming mode
@item @code{stk600pp} @tab
Atmel STK600 in parallel programming mode
@item @code{usbasp} @tab
USBasp,@*
@url{http://www.fischl.de/usbasp/}
@ -1043,17 +1053,20 @@ Leave terminal mode and thus AVRDUDE.
@noindent
In addition, the following commands are supported on the STK500
programmer:
and STK600 programmer:
@table @code
@item vtarg @var{voltage}
Set the target's supply voltage to @var{voltage} Volts.
@item varef @var{voltage}
@item varef @var{[channel]} @var{voltage}
Set the adjustable voltage source to @var{voltage} Volts.
This voltage is normally used to drive the target's
@emph{Aref} input on the STK500.
@emph{Aref} input on the STK500 and STK600.
The STK600 offers two reference voltages, which can be
selected by the optional parameter @var{channel} (either
0 or 1).
@item fosc @var{freq}[@var{M}|@var{k}]
Set the master oscillator to @var{freq} Hz.
@ -1064,7 +1077,7 @@ multiplies by 1E6, a trailing letter @var{k} by 1E3.
Turn the master oscillator off.
@item sck @var{period}
@emph{STK500 only:}
@emph{STK500 and STK600 only:}
Set the SCK clock period to @var{period} microseconds.
@emph{JTAG ICE only:}
@ -1076,7 +1089,7 @@ This parameter can also be used on the JTAG ICE mkII to specify the
ISP clock period when operating the ICE in ISP mode.
@item parms
@emph{STK500 only:}
@emph{STK500 and STK600 only:}
Display the current voltage and master oscillator parameters.
@emph{JTAG ICE only:}
@ -1191,7 +1204,7 @@ avrdude>
@c
@c Node
@c
@node Configuration File, Platform Dependent Information, Terminal Mode Operation, Top
@node Configuration File, Programmer Specific Information, Terminal Mode Operation, Top
@chapter Configuration File
@noindent
@ -1432,11 +1445,87 @@ functionality does not make sense for these boot loaders.
@end itemize
@c
@c Node
@c
@node Programmer Specific Information, Platform Dependent Information, Configuration File, Top
@chapter Programmer Specific Information
@menu
* Atmel STK600::
@end menu
@c
@c Node
@c
@node Platform Dependent Information, Troubleshooting, Configuration File, Top
@node Atmel STK600, , Programmer Specific Information, Programmer Specific Information
@section Atmel STK600
@c
@c Update the table below by running the tools/get-stk600-devices.xsl
@c XSLT transformation on targetboard.xml as shipped by the latest
@c release of AVR Studio.
@c
The following devices are supported by the respective STK600 routing
and socket card:
@multitable @columnfractions .25 .25 .5
@headitem Routing card @tab Socket card @tab Devices
@item @code{STK600-RC008T-2} @tab @code{STK600-DIP} @tab ATtiny11 ATtiny12 ATtiny13 ATtiny25 ATtiny45 ATtiny85
@item @code{STK600-RC008T-7} @tab @code{STK600-DIP} @tab ATtiny15
@item @code{STK600-RC020T-1} @tab @code{STK600-DIP} @tab ATtiny2313
@item @code{} @tab @code{STK600-TinyX3U} @tab ATtiny43U
@item @code{STK600-RC014T-12} @tab @code{STK600-DIP} @tab ATtiny24 ATtiny44 ATtiny84
@item @code{STK600-RC020T-8} @tab @code{STK600-DIP} @tab ATtiny26 ATtiny261 ATtiny461 ATtiny861
@item @code{STK600-RC020T-23} @tab @code{STK600-SOIC} @tab ATtiny167
@item @code{STK600-RC028T-3} @tab @code{STK600-DIP} @tab ATtiny28
@item @code{STK600-RC028M-6} @tab @code{STK600-DIP} @tab ATtiny48 ATtiny88 ATmega8 ATmega48 ATmega88 ATmega168 ATmega48P ATmega88P ATmega168P ATmega328P
@item @code{STK600-RC040M-4} @tab @code{STK600-DIP} @tab ATmega8515 ATmega162
@item @code{STK600-RC040M-5} @tab @code{STK600-DIP} @tab ATmega8535 ATmega16 ATmega32 ATmega164P ATmega324P ATmega644 ATmega644P ATmega1284P
@item @code{STK600-RC064M-9} @tab @code{STK600-TQFP64} @tab ATmega64 ATmega128 ATmega1281 ATmega2561 AT90CAN32 AT90CAN64 AT90CAN128
@item @code{STK600-RC064M-10} @tab @code{STK600-TQFP64} @tab ATmega165 ATmega165P ATmega169 ATmega169P ATmega325 ATmega325P ATmega329 ATmega329P ATmega645 ATmega649
@item @code{STK600-RC100M-11} @tab @code{STK600-TQFP100} @tab ATmega640 ATmega1280 ATmega2560
@item @code{} @tab @code{STK600-ATMEGA2560} @tab ATmega2560
@item @code{STK600-RC100M-18} @tab @code{STK600-TQFP100} @tab ATmega3250 ATmega3250P ATmega3290 ATmega3290P ATmega6450 ATmega6490
@item @code{STK600-RC32U-20} @tab @code{STK600-TQFP32} @tab AT90USB82 AT90USB162
@item @code{STK600-RC044U-25} @tab @code{STK600-TQFP44} @tab ATmega32U4
@item @code{STK600-RC064U-17} @tab @code{STK600-TQFP64} @tab AT90USB646 AT90USB1286 AT90USB647 AT90USB1287
@item @code{STK600-RCPWM-22} @tab @code{STK600-TQFP32} @tab ATmega32C1 ATmega32M1
@item @code{STK600-RCPWM-19} @tab @code{STK600-SOIC} @tab AT90PWM2 AT90PWM3 AT90PWM2B AT90PWM3B AT90PWM216 AT90PWM316
@item @code{STK600-RC044M-24} @tab @code{STK600-TSSOP44} @tab ATmega32HVB
@item @code{STK600-RC100X-13} @tab @code{STK600-TQFP100} @tab ATxmega128A1 ATxmega128A1_revD ATxmega64A1
@item @code{} @tab @code{STK600-uC3-144} @tab AT32UC3A0512 AT32UC3A0256 AT32UC3A0128
@item @code{STK600-RCuC3B0-21} @tab @code{STK600-TQFP64-2} @tab AT32UC3B0256 AT32UC3B0128 AT32UC3B064
@end multitable
Ensure the correct socket and routing card are mounted @emph{before}
powering on the STK600. While the STK600 firmware ensures the socket
and routing card mounted match each other (using a table stored
internally in nonvolatile memory), it cannot handle the case where a
wrong routing card is used, e. g. the routing card
@code{STK600-RC040M-5} (which is meant for 40-pin DIP AVRs that have
an ADC, with the power supply pins in the center of the package) was
used but an ATmega8515 inserted (which uses the ``industry standard''
pinout with Vcc and GND at opposite corners).
Note that for devices that use the routing card @code{STK600-RC008T-2},
in order to use ISP mode, the jumper for @code{AREF0} must be removed
as it would otherwise block one of the ISP signals. High-voltage
serial programming can be used even with that jumper installed.
The ISP system of the STK600 contains a detection against shortcuts
and other wiring errors. AVRDUDE initiates a connection check before
trying to enter ISP programming mode, and display the result if the
target is not found ready to be ISP programmed.
High-voltage programming requires the target voltage to be set to at
least 4.5 V in order to work. This can be done using
@emph{Terminal Mode}, see @ref{Terminal Mode Operation}.
@c
@c Node
@c
@node Platform Dependent Information, Troubleshooting, Programmer Specific Information, Top
@appendix Platform Dependent Information
@menu
@ -1951,7 +2040,7 @@ programming works, and is documented that way in the Atmel AVR
datasheets.
In order to successfully program the EEPROM that way, a prior chip
erase (with the EESAVE fuse unprogrammed) is required.
This also applies to the STK500 in high-voltage programming mode.
This also applies to the STK500 and STK600 in high-voltage programming mode.
@item
Problem: How do I turn off the @var{DWEN} fuse?

View File

@ -183,6 +183,9 @@ stk500pp { yylval=NULL; return K_STK500PP; }
stk500v2 { yylval=NULL; return K_STK500V2; }
stk500generic { yylval=NULL; return K_STK500GENERIC; }
stk500_devcode { yylval=NULL; return K_STK500_DEVCODE; }
stk600 { yylval=NULL; return K_STK600; }
stk600hvsp { yylval=NULL; return K_STK600HVSP; }
stk600pp { yylval=NULL; return K_STK600PP; }
type { yylval=NULL; return K_TYPE; }
vcc { yylval=NULL; return K_VCC; }
vfyled { yylval=NULL; return K_VFYLED; }

2
pgm.h
View File

@ -92,7 +92,7 @@ typedef struct programmer_t {
int (*read_sig_bytes) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m);
void (*print_parms) (struct programmer_t * pgm);
int (*set_vtarget) (struct programmer_t * pgm, double v);
int (*set_varef) (struct programmer_t * pgm, double v);
int (*set_varef) (struct programmer_t * pgm, unsigned int chan, double v);
int (*set_fosc) (struct programmer_t * pgm, double v);
int (*set_sck_period) (struct programmer_t * pgm, double v);
int (*setpin) (struct programmer_t * pgm, int pin, int value);

View File

@ -35,6 +35,11 @@ union filedescriptor
{
int ifd;
void *pfd;
struct
{
void *handle;
int ep;
} usb;
};
struct serial_device

View File

@ -913,7 +913,8 @@ static int stk500_set_vtarget(PROGRAMMER * pgm, double v)
}
static int stk500_set_varef(PROGRAMMER * pgm, double v)
static int stk500_set_varef(PROGRAMMER * pgm, unsigned int chan /* unused */,
double v)
{
unsigned uaref, utarg;

View File

@ -38,6 +38,7 @@
#include "ac_cfg.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -109,6 +110,16 @@ struct pdata
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
/*
* Data structure for displaying STK600 routing and socket cards.
*/
struct carddata
{
int id;
const char *name;
};
/* XXX That should become part of the private pgm-> data. */
static enum
{
PGMTYPE_UNKNOWN,
@ -116,6 +127,7 @@ static enum
PGMTYPE_AVRISP,
PGMTYPE_AVRISP_MKII,
PGMTYPE_JTAGICE_MKII,
PGMTYPE_STK600,
}
pgmtype;
@ -126,8 +138,12 @@ static const char *pgmname[] =
"AVRISP",
"AVRISP mkII",
"JTAG ICE mkII",
"STK600",
};
/* XXX That should become part of the private pgm-> data. */
static AVRPART *lastpart;
struct jtagispentry
{
unsigned char cmd;
@ -191,6 +207,9 @@ static struct jtagispentry jtagispcmds[] = {
static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value);
static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value);
static int stk500v2_getparm2(PROGRAMMER * pgm, unsigned char parm, unsigned int * value);
static int stk500v2_setparm2(PROGRAMMER * pgm, unsigned char parm, unsigned int value);
static int stk500v2_setparm_real(PROGRAMMER * pgm, unsigned char parm, unsigned char value);
static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p);
static int stk500v2_is_page_empty(unsigned int address, int page_size,
const unsigned char *buf);
@ -199,6 +218,8 @@ static unsigned int stk500v2_mode_for_pagesize(unsigned int pagesize);
static int stk500v2_set_sck_period_mk2(PROGRAMMER * pgm, double v);
static int stk600_set_sck_period(PROGRAMMER * pgm, double v);
static void stk500v2_setup(PROGRAMMER * pgm)
{
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
@ -301,7 +322,7 @@ static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
unsigned char buf[275 + 6]; // max MESSAGE_BODY of 275 bytes, 6 bytes overhead
int i;
if (pgmtype == PGMTYPE_AVRISP_MKII)
if (pgmtype == PGMTYPE_AVRISP_MKII || pgmtype == PGMTYPE_STK600)
return stk500v2_send_mk2(pgm, data, len);
else if (pgmtype == PGMTYPE_JTAGICE_MKII)
return stk500v2_jtagmkII_send(pgm, data, len);
@ -399,7 +420,7 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize)
struct timeval tv;
double tstart, tnow;
if (pgmtype == PGMTYPE_AVRISP_MKII)
if (pgmtype == PGMTYPE_AVRISP_MKII || pgmtype == PGMTYPE_STK600)
return stk500v2_recv_mk2(pgm, msg, maxsize);
else if (pgmtype == PGMTYPE_JTAGICE_MKII)
return stk500v2_jtagmkII_recv(pgm, msg, maxsize);
@ -535,6 +556,9 @@ retry:
} else if (siglen >= strlen("AVRISP_MK2") &&
memcmp(resp + 3, "AVRISP_MK2", strlen("AVRISP_MK2")) == 0) {
pgmtype = PGMTYPE_AVRISP_MKII;
} else if (siglen >= strlen("STK600") &&
memcmp(resp + 3, "STK600", strlen("STK600")) == 0) {
pgmtype = PGMTYPE_STK600;
} else {
resp[siglen + 3] = 0;
if (verbose)
@ -740,12 +764,38 @@ static int stk500hvsp_chip_erase(PROGRAMMER * pgm, AVRPART * p)
return stk500hv_chip_erase(pgm, p, HVSPMODE);
}
static struct
{
unsigned int state;
const char *description;
} connection_status[] =
{
{ STATUS_CONN_FAIL_MOSI, "MOSI fail" },
{ STATUS_CONN_FAIL_RST, "RST fail" },
{ STATUS_CONN_FAIL_SCK, "SCK fail" },
{ STATUS_TGT_NOT_DETECTED, "Target not detected" },
{ STATUS_TGT_REVERSE_INSERTED, "Target reverse inserted" },
{ STATUS_CONN_FAIL_MOSI | STATUS_CONN_FAIL_RST,
"MOSI and RST fail" },
{ STATUS_CONN_FAIL_MOSI | STATUS_CONN_FAIL_RST | STATUS_CONN_FAIL_SCK,
"MOSI, RST, and SCK fail" },
{ STATUS_CONN_FAIL_RST | STATUS_CONN_FAIL_SCK,
"RST and SCK fail" },
{ STATUS_CONN_FAIL_MOSI | STATUS_CONN_FAIL_SCK,
"MOSI and SCK fail" },
};
/*
* issue the 'program enable' command to the AVR device
*/
static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p)
{
unsigned char buf[16];
size_t i;
const char *msg;
int rv;
lastpart = p;
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
fprintf(stderr, "%s: stk500v2_program_enable(): program enable instruction not defined for part \"%s\"\n",
@ -753,6 +803,35 @@ static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p)
return -1;
}
if (pgmtype == PGMTYPE_STK500 || pgmtype == PGMTYPE_STK600)
/* Activate AVR-style (low active) RESET */
stk500v2_setparm_real(pgm, PARAM_RESET_POLARITY, 0x01);
if (pgmtype == PGMTYPE_STK600) {
buf[0] = CMD_CHECK_TARGET_CONNECTION;
if (stk500v2_command(pgm, buf, 1, sizeof(buf)) < 0) {
fprintf(stderr, "%s: stk500v2_program_enable(): cannot get connection status\n",
progname);
return -1;
}
if (buf[2] != STATUS_ISP_READY) {
msg = "Unknown";
for (i = 0;
i < sizeof connection_status / sizeof connection_status[0];
i++)
if (connection_status[i].state == (unsigned)buf[2]) {
msg = connection_status[i].description;
break;
}
fprintf(stderr, "%s: stk500v2_program_enable():"
" bad STK600 connection status: %s (0x%02x)\n",
progname, msg, buf[2]);
return -1;
}
}
buf[0] = CMD_ENTER_PROGMODE_ISP;
buf[1] = p->timeout;
buf[2] = p->stabdelay;
@ -762,8 +841,34 @@ static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p)
buf[6] = p->pollvalue;
buf[7] = p->pollindex;
avr_set_bits(p->op[AVR_OP_PGM_ENABLE], buf+8);
buf[10] = buf[11] = 0;
return stk500v2_command(pgm, buf, 12, sizeof(buf));
rv = stk500v2_command(pgm, buf, 12, sizeof(buf));
if (rv < 0) {
buf[0] = CMD_CHECK_TARGET_CONNECTION;
if (stk500v2_command(pgm, buf, 1, sizeof(buf)) < 0) {
fprintf(stderr, "%s: stk500v2_program_enable(): cannot get connection status\n",
progname);
return -1;
}
msg = "Unknown";
for (i = 0;
i < sizeof connection_status / sizeof connection_status[0];
i++)
if (connection_status[i].state == (unsigned)buf[2]) {
msg = connection_status[i].description;
break;
}
fprintf(stderr, "%s: stk500v2_program_enable():"
" bad STK600 connection status: %s (0x%02x)\n",
progname, msg, buf[2]);
}
return rv;
}
/*
@ -773,6 +878,8 @@ static int stk500pp_program_enable(PROGRAMMER * pgm, AVRPART * p)
{
unsigned char buf[16];
lastpart = p;
buf[0] = CMD_ENTER_PROGMODE_PP;
buf[1] = p->hventerstabdelay;
buf[2] = p->progmodedelay;
@ -792,7 +899,11 @@ static int stk500hvsp_program_enable(PROGRAMMER * pgm, AVRPART * p)
{
unsigned char buf[16];
buf[0] = CMD_ENTER_PROGMODE_HVSP;
lastpart = p;
buf[0] = pgmtype == PGMTYPE_STK600?
CMD_ENTER_PROGMODE_HVSP_STK600:
CMD_ENTER_PROGMODE_HVSP;
buf[1] = p->hventerstabdelay;
buf[2] = p->hvspcmdexedelay;
buf[3] = p->synchcycles;
@ -934,7 +1045,10 @@ static void stk500hv_disable(PROGRAMMER * pgm, enum hvmode mode)
free(PDATA(pgm)->eeprom_pagecache);
PDATA(pgm)->eeprom_pagecache = NULL;
buf[0] = mode == PPMODE? CMD_LEAVE_PROGMODE_PP: CMD_LEAVE_PROGMODE_HVSP;
buf[0] = mode == PPMODE? CMD_LEAVE_PROGMODE_PP:
(pgmtype == PGMTYPE_STK600?
CMD_LEAVE_PROGMODE_HVSP_STK600:
CMD_LEAVE_PROGMODE_HVSP);
buf[1] = 15; // p->hvleavestabdelay;
buf[2] = 15; // p->resetdelay;
@ -1033,6 +1147,56 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port)
}
static int stk600_open(PROGRAMMER * pgm, char * port)
{
long baud = 115200;
DEBUG("STK500V2: stk600_open()\n");
if (pgm->baudrate)
baud = pgm->baudrate;
pgmtype = PGMTYPE_UNKNOWN;
/*
* If the port name starts with "usb", divert the serial routines
* to the USB ones. The serial_open() function for USB overrides
* the meaning of the "baud" parameter to be the USB device ID to
* search for.
*/
if (strncmp(port, "usb", 3) == 0) {
#if defined(HAVE_LIBUSB)
serdev = &usb_serdev_frame;
baud = USB_DEVICE_STK600;
pgmtype = PGMTYPE_STK600;
pgm->set_sck_period = stk600_set_sck_period;
#else
fprintf(stderr, "avrdude was compiled without usb support.\n");
return -1;
#endif
}
strcpy(pgm->port, port);
serial_open(port, baud, &pgm->fd);
/*
* drain any extraneous input
*/
stk500v2_drain(pgm, 0);
stk500v2_getsync(pgm);
stk500v2_drain(pgm, 0);
if (pgm->bitclock != 0.0) {
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0)
return -1;
}
return 0;
}
static void stk500v2_close(PROGRAMMER * pgm)
{
DEBUG("STK500V2: stk500v2_close()\n");
@ -1837,7 +2001,8 @@ static int stk500v2_set_vtarget(PROGRAMMER * pgm, double v)
}
static int stk500v2_set_varef(PROGRAMMER * pgm, double v)
static int stk500v2_set_varef(PROGRAMMER * pgm, unsigned int chan /* unused */,
double v)
{
unsigned char uaref, utarg;
@ -2006,6 +2171,122 @@ static int stk500v2_set_sck_period(PROGRAMMER * pgm, double v)
}
static int stk600_set_vtarget(PROGRAMMER * pgm, double v)
{
unsigned char utarg;
unsigned int uaref;
int rv;
utarg = (unsigned)((v + 0.049) * 10);
if (stk500v2_getparm2(pgm, PARAM2_AREF0, &uaref) != 0) {
fprintf(stderr,
"%s: stk500v2_set_vtarget(): cannot obtain V[aref][0]\n",
progname);
return -1;
}
if (uaref > (unsigned)utarg * 10) {
fprintf(stderr,
"%s: stk500v2_set_vtarget(): reducing V[aref][0] from %.2f to %.1f\n",
progname, uaref / 100.0, v);
uaref = 10 * (unsigned)utarg;
if (stk500v2_setparm2(pgm, PARAM2_AREF0, uaref)
!= 0)
return -1;
}
if (stk500v2_getparm2(pgm, PARAM2_AREF1, &uaref) != 0) {
fprintf(stderr,
"%s: stk500v2_set_vtarget(): cannot obtain V[aref][1]\n",
progname);
return -1;
}
if (uaref > (unsigned)utarg * 10) {
fprintf(stderr,
"%s: stk500v2_set_vtarget(): reducing V[aref][1] from %.2f to %.1f\n",
progname, uaref / 100.0, v);
uaref = 10 * (unsigned)utarg;
if (stk500v2_setparm2(pgm, PARAM2_AREF1, uaref)
!= 0)
return -1;
}
/*
* Vtarget on the STK600 can only be adjusted while not being in
* programming mode.
*/
pgm->disable(pgm);
rv = stk500v2_setparm(pgm, PARAM_VTARGET, utarg);
pgm->program_enable(pgm, lastpart);
return rv;
}
static int stk600_set_varef(PROGRAMMER * pgm, unsigned int chan, double v)
{
unsigned char utarg;
unsigned int uaref;
uaref = (unsigned)((v + 0.0049) * 100);
if (stk500v2_getparm(pgm, PARAM_VTARGET, &utarg) != 0) {
fprintf(stderr,
"%s: stk500v2_set_varef(): cannot obtain V[target]\n",
progname);
return -1;
}
if (uaref > (unsigned)utarg * 10) {
fprintf(stderr,
"%s: stk500v2_set_varef(): V[aref] must not be greater than "
"V[target] = %.1f\n",
progname, utarg / 10.0);
return -1;
}
switch (chan)
{
case 0:
return stk500v2_setparm2(pgm, PARAM2_AREF0, uaref);
case 1:
return stk500v2_setparm2(pgm, PARAM2_AREF1, uaref);
default:
fprintf(stderr,
"%s: stk500v2_set_varef(): invalid channel %d\n",
progname, chan);
return -1;
}
}
static int stk600_set_fosc(PROGRAMMER * pgm, double v)
{
unsigned int oct, dac;
oct = 1.443 * log(v / 1039.0);
dac = 2048 - (2078.0 * pow(2, (double)(10 + oct))) / v;
return stk500v2_setparm2(pgm, PARAM2_CLOCK_CONF, (oct << 12) | (dac << 2));
}
static int stk600_set_sck_period(PROGRAMMER * pgm, double v)
{
unsigned int sck;
sck = ceil((16e6 / (2 * 1.0 / v)) - 1);
if (sck >= 4096)
sck = 4095;
return stk500v2_setparm2(pgm, PARAM2_SCK_DURATION, sck);
}
static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value)
{
unsigned char buf[32];
@ -2059,9 +2340,108 @@ static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char
return stk500v2_setparm_real(pgm, parm, value);
}
static int stk500v2_getparm2(PROGRAMMER * pgm, unsigned char parm, unsigned int * value)
{
unsigned char buf[32];
buf[0] = CMD_GET_PARAMETER;
buf[1] = parm;
if (stk500v2_command(pgm, buf, 2, sizeof(buf)) < 0) {
fprintf(stderr,"%s: stk500v2_getparm2(): failed to get parameter 0x%02x\n",
progname, parm);
return -1;
}
*value = ((unsigned)buf[2] << 8) | buf[3];
return 0;
}
static int stk500v2_setparm2(PROGRAMMER * pgm, unsigned char parm, unsigned int value)
{
unsigned char buf[32];
buf[0] = CMD_SET_PARAMETER;
buf[1] = parm;
buf[2] = value >> 8;
buf[3] = value;
if (stk500v2_command(pgm, buf, 4, sizeof(buf)) < 0) {
fprintf(stderr, "\n%s: stk500v2_setparm2(): failed to set parameter 0x%02x\n",
progname, parm);
return -1;
}
return 0;
}
/*
* These two tables can be semi-automatically updated from
* targetboards.xml using tools/get-stk600-cards.xsl.
*/
static struct carddata routing_cards[] =
{
{ 0x01, "STK600-RC020T-1" },
{ 0x03, "STK600-RC028T-3" },
{ 0x05, "STK600-RC040M-5" },
{ 0x08, "STK600-RC020T-8" },
{ 0x0A, "STK600-RC040M-4" },
{ 0x0C, "STK600-RC008T-2" },
{ 0x0D, "STK600-RC028M-6" },
{ 0x10, "STK600-RC064M-10" },
{ 0x11, "STK600-RC100M-11" },
{ 0x13, "STK600-RC100X-13" },
{ 0x18, "STK600-RC100M-18" },
{ 0x19, "STK600-RCPWM-19" },
{ 0x1B, "STK600-RC32U-20" },
{ 0x1C, "STK600-RC014T-12" },
{ 0x1E, "STK600-RC064U-17" },
{ 0x1F, "STK600-RCuC3B0-21" },
{ 0x20, "STK600-RCPWM-22" },
{ 0x21, "STK600-RC020T-23" },
{ 0x22, "STK600-RC044M-24" },
{ 0x23, "STK600-RC044U-25" },
{ 0x55, "STK600-RC064M-9" },
{ 0xA0, "STK600-RC008T-7" },
};
static struct carddata socket_cards[] =
{
{ 0x02, "STK600-TQFP32" },
{ 0x03, "STK600-TQFP100" },
{ 0x04, "STK600-SOIC" },
{ 0x09, "STK600-TinyX3U" },
{ 0x0C, "STK600-TSSOP44" },
{ 0x0D, "STK600-TQFP44" },
{ 0x0E, "STK600-TQFP64-2" },
{ 0x0F, "STK600-ATMEGA2560" },
{ 0x55, "STK600-TQFP64" },
{ 0x69, "STK600-uC3-144" },
{ 0xF1, "STK600-DIP" },
};
static const char *stk600_get_cardname(const struct carddata *table,
size_t nele, int id)
{
const struct carddata *cdp;
if (id == 0xFF)
/* 0xFF means this card is not present at all. */
return "Not present";
for (cdp = table; nele > 0; cdp++, nele--)
if (cdp->id == id)
return cdp->name;
return "Unknown";
}
static void stk500v2_display(PROGRAMMER * pgm, const char * p)
{
unsigned char maj, min, hdw, topcard;
unsigned char maj, min, hdw, topcard, maj_s1, min_s1, maj_s2, min_s2;
unsigned int rev;
const char *topcard_name, *pgmname;
switch (pgmtype) {
@ -2069,6 +2449,7 @@ static void stk500v2_display(PROGRAMMER * pgm, const char * p)
case PGMTYPE_STK500: pgmname = "STK500"; break;
case PGMTYPE_AVRISP: pgmname = "AVRISP"; break;
case PGMTYPE_AVRISP_MKII: pgmname = "AVRISP mkII"; break;
case PGMTYPE_STK600: pgmname = "STK600"; break;
default: pgmname = "None";
}
if (pgmtype != PGMTYPE_JTAGICE_MKII) {
@ -2077,7 +2458,15 @@ static void stk500v2_display(PROGRAMMER * pgm, const char * p)
stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
stk500v2_getparm(pgm, PARAM_SW_MINOR, &min);
fprintf(stderr, "%sHardware Version: %d\n", p, hdw);
fprintf(stderr, "%sFirmware Version: %d.%02d\n", p, maj, min);
fprintf(stderr, "%sFirmware Version Master : %d.%02d\n", p, maj, min);
if (pgmtype == PGMTYPE_STK600) {
stk500v2_getparm(pgm, PARAM_SW_MAJOR_SLAVE1, &maj_s1);
stk500v2_getparm(pgm, PARAM_SW_MINOR_SLAVE1, &min_s1);
stk500v2_getparm(pgm, PARAM_SW_MAJOR_SLAVE2, &maj_s2);
stk500v2_getparm(pgm, PARAM_SW_MINOR_SLAVE2, &min_s2);
fprintf(stderr, "%sFirmware Version Slave 1: %d.%02d\n", p, maj_s1, min_s1);
fprintf(stderr, "%sFirmware Version Slave 2: %d.%02d\n", p, maj_s2, min_s2);
}
}
if (pgmtype == PGMTYPE_STK500) {
@ -2092,17 +2481,50 @@ static void stk500v2_display(PROGRAMMER * pgm, const char * p)
default: topcard_name = "Unknown"; break;
}
fprintf(stderr, "%sTopcard : %s\n", p, topcard_name);
} else if (pgmtype == PGMTYPE_STK600) {
stk500v2_getparm(pgm, PARAM_ROUTINGCARD_ID, &topcard);
fprintf(stderr, "%sRouting card : %s\n", p,
stk600_get_cardname(routing_cards,
sizeof routing_cards / sizeof routing_cards[0],
topcard));
stk500v2_getparm(pgm, PARAM_SOCKETCARD_ID, &topcard);
fprintf(stderr, "%sSocket card : %s\n", p,
stk600_get_cardname(socket_cards,
sizeof socket_cards / sizeof socket_cards[0],
topcard));
stk500v2_getparm2(pgm, PARAM2_RC_ID_TABLE_REV, &rev);
fprintf(stderr, "%sRC_ID table rev : %d\n", p, rev);
stk500v2_getparm2(pgm, PARAM2_EC_ID_TABLE_REV, &rev);
fprintf(stderr, "%sEC_ID table rev : %d\n", p, rev);
}
stk500v2_print_parms1(pgm, p);
return;
}
static double
f_to_kHz_MHz(double f, const char **unit)
{
if (f > 1e6) {
f /= 1e6;
*unit = "MHz";
} else if (f > 1e3) {
f /= 1000;
*unit = "kHz";
} else
*unit = "Hz";
return f;
}
static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p)
{
unsigned char vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
unsigned int sck_stk600, clock_conf, dac, oct, varef;
unsigned char vtarget_jtag[4];
int prescale;
double f;
const char *unit;
if (pgmtype == PGMTYPE_JTAGICE_MKII) {
jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget_jtag);
@ -2112,20 +2534,22 @@ static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p)
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
}
stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
if (pgmtype == PGMTYPE_STK500) {
switch (pgmtype) {
case PGMTYPE_STK500:
stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust);
stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale);
stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch);
fprintf(stderr, "%sSCK period : %.1f us\n", p,
sck_duration * 8.0e6 / STK500V2_XTAL + 0.05);
fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0);
fprintf(stderr, "%sOscillator : ", p);
if (osc_pscale == 0)
fprintf(stderr, "Off\n");
else {
int prescale = 1;
double f = STK500V2_XTAL / 2;
const char *unit;
prescale = 1;
f = STK500V2_XTAL / 2;
switch (osc_pscale) {
case 2: prescale = 8; break;
@ -2137,23 +2561,40 @@ static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p)
}
f /= prescale;
f /= (osc_cmatch + 1);
if (f > 1e6) {
f /= 1e6;
unit = "MHz";
} else if (f > 1e3) {
f /= 1000;
unit = "kHz";
} else
unit = "Hz";
f = f_to_kHz_MHz(f, &unit);
fprintf(stderr, "%.3f %s\n", f, unit);
}
}
if (pgmtype == PGMTYPE_AVRISP_MKII || pgmtype == PGMTYPE_JTAGICE_MKII)
break;
case PGMTYPE_AVRISP_MKII:
case PGMTYPE_JTAGICE_MKII:
stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
fprintf(stderr, "%sSCK period : %.2f us\n", p,
(float) 1000000 / avrispmkIIfreqs[sck_duration]);
else
(float) 1000000 / avrispmkIIfreqs[sck_duration]);
break;
case PGMTYPE_STK600:
stk500v2_getparm2(pgm, PARAM2_AREF0, &varef);
fprintf(stderr, "%sVaref 0 : %.2f V\n", p, varef / 100.0);
stk500v2_getparm2(pgm, PARAM2_AREF1, &varef);
fprintf(stderr, "%sVaref 1 : %.2f V\n", p, varef / 100.0);
stk500v2_getparm2(pgm, PARAM2_SCK_DURATION, &sck_stk600);
fprintf(stderr, "%sSCK period : %.2f us\n", p,
(float) (sck_stk600 + 1) / 8.0);
stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf);
oct = (clock_conf & 0xf000) >> 12u;
dac = (clock_conf & 0x0ffc) >> 2u;
f = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0);
f = f_to_kHz_MHz(f, &unit);
fprintf(stderr, "%sOscillator : %.3f %s\n",
p, f, unit);
break;
default:
fprintf(stderr, "%sSCK period : %.1f us\n", p,
sck_duration * 8.0e6 / STK500V2_XTAL + 0.05);
break;
}
return;
}
@ -2181,7 +2622,6 @@ static int stk500v2_perform_osccal(PROGRAMMER * pgm)
return 0;
}
/*
* Wrapper functions for the JTAG ICE mkII in ISP mode. This mode
* uses the normal JTAG ICE mkII packet stream to communicate with the
@ -2612,3 +3052,105 @@ void stk500v2_dragon_hvsp_initpgm(PROGRAMMER * pgm)
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256;
}
void stk600_initpgm(PROGRAMMER * pgm)
{
strcpy(pgm->type, "STK600");
/*
* mandatory functions
*/
pgm->initialize = stk500v2_initialize;
pgm->display = stk500v2_display;
pgm->enable = stk500v2_enable;
pgm->disable = stk500v2_disable;
pgm->program_enable = stk500v2_program_enable;
pgm->chip_erase = stk500v2_chip_erase;
pgm->cmd = stk500v2_cmd;
pgm->open = stk600_open;
pgm->close = stk500v2_close;
pgm->read_byte = avr_read_byte_default;
pgm->write_byte = avr_write_byte_default;
/*
* optional functions
*/
pgm->paged_write = stk500v2_paged_write;
pgm->paged_load = stk500v2_paged_load;
pgm->print_parms = stk500v2_print_parms;
pgm->set_vtarget = stk600_set_vtarget;
pgm->set_varef = stk600_set_varef;
pgm->set_fosc = stk600_set_fosc;
pgm->set_sck_period = stk600_set_sck_period;
pgm->perform_osccal = stk500v2_perform_osccal;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256;
}
void stk600pp_initpgm(PROGRAMMER * pgm)
{
strcpy(pgm->type, "STK600PP");
/*
* mandatory functions
*/
pgm->initialize = stk500pp_initialize;
pgm->display = stk500v2_display;
pgm->enable = stk500v2_enable;
pgm->disable = stk500pp_disable;
pgm->program_enable = stk500pp_program_enable;
pgm->chip_erase = stk500pp_chip_erase;
pgm->open = stk600_open;
pgm->close = stk500v2_close;
pgm->read_byte = stk500pp_read_byte;
pgm->write_byte = stk500pp_write_byte;
/*
* optional functions
*/
pgm->paged_write = stk500pp_paged_write;
pgm->paged_load = stk500pp_paged_load;
pgm->print_parms = stk500v2_print_parms;
pgm->set_vtarget = stk600_set_vtarget;
pgm->set_varef = stk600_set_varef;
pgm->set_fosc = stk600_set_fosc;
pgm->set_sck_period = stk600_set_sck_period;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256;
}
void stk600hvsp_initpgm(PROGRAMMER * pgm)
{
strcpy(pgm->type, "STK600HVSP");
/*
* mandatory functions
*/
pgm->initialize = stk500hvsp_initialize;
pgm->display = stk500v2_display;
pgm->enable = stk500v2_enable;
pgm->disable = stk500hvsp_disable;
pgm->program_enable = stk500hvsp_program_enable;
pgm->chip_erase = stk500hvsp_chip_erase;
pgm->open = stk600_open;
pgm->close = stk500v2_close;
pgm->read_byte = stk500hvsp_read_byte;
pgm->write_byte = stk500hvsp_write_byte;
/*
* optional functions
*/
pgm->paged_write = stk500hvsp_paged_write;
pgm->paged_load = stk500hvsp_paged_load;
pgm->print_parms = stk500v2_print_parms;
pgm->set_vtarget = stk600_set_vtarget;
pgm->set_varef = stk600_set_varef;
pgm->set_fosc = stk600_set_fosc;
pgm->set_sck_period = stk600_set_sck_period;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256;
}

View File

@ -34,6 +34,9 @@ void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm);
void stk500v2_dragon_hvsp_initpgm(PROGRAMMER * pgm);
void stk500v2_dragon_isp_initpgm(PROGRAMMER * pgm);
void stk500v2_dragon_pp_initpgm(PROGRAMMER * pgm);
void stk600_initpgm (PROGRAMMER * pgm);
void stk600hvsp_initpgm (PROGRAMMER * pgm);
void stk600pp_initpgm (PROGRAMMER * pgm);
#ifdef __cplusplus
}

View File

@ -23,6 +23,9 @@
#define CMD_OSCCAL 0x05
#define CMD_LOAD_ADDRESS 0x06
#define CMD_FIRMWARE_UPGRADE 0x07
#define CMD_CHECK_TARGET_CONNECTION 0x0D
#define CMD_LOAD_RC_ID_TABLE 0x0E
#define CMD_LOAD_EC_ID_TABLE 0x0F
// *****************[ STK ISP command constants ]******************************
@ -75,6 +78,27 @@
#define CMD_READ_LOCK_HVSP 0x3A
#define CMD_READ_SIGNATURE_HVSP 0x3B
#define CMD_READ_OSCCAL_HVSP 0x3C
// These two are redefined since 0x30/0x31 collide
// with the STK600 bootloader.
#define CMD_ENTER_PROGMODE_HVSP_STK600 0x3D
#define CMD_LEAVE_PROGMODE_HVSP_STK600 0x3E
// *** XPROG command constants ***
#define CMD_XPROG 0x50
#define CMD_XPROG_SETMODE 0x51
// *** AVR32 JTAG Programming command ***
#define CMD_JTAG_AVR32 0x80
#define CMD_ENTER_PROGMODE_JTAG_AVR32 0x81
#define CMD_LEAVE_PROGMODE_JTAG_AVR32 0x82
// *** AVR JTAG Programming command ***
#define CMD_JTAG_AVR 0x90
// *****************[ STK test command constants ]***************************
@ -110,24 +134,136 @@
#define STATUS_CMD_FAILED 0xC0
#define STATUS_CKSUM_ERROR 0xC1
#define STATUS_CMD_UNKNOWN 0xC9
#define STATUS_CMD_ILLEGAL_PARAMETER 0xCA
// Status
#define STATUS_CONN_FAIL_MOSI 0x01
#define STATUS_CONN_FAIL_RST 0x02
#define STATUS_CONN_FAIL_SCK 0x04
#define STATUS_TGT_NOT_DETECTED 0x00
#define STATUS_ISP_READY 0x10
#define STATUS_TGT_REVERSE_INSERTED 0x20
// hw_status
// Bits in status variable
// Bit 0-3: Slave MCU
// Bit 4-7: Master MCU
#define STATUS_AREF_ERROR 0
// Set to '1' if AREF is short circuited
#define STATUS_VTG_ERROR 4
// Set to '1' if VTG is short circuited
#define STATUS_RC_CARD_ERROR 5
// Set to '1' if board id changes when board is powered
#define STATUS_PROGMODE 6
// Set to '1' if board is in programming mode
#define STATUS_POWER_SURGE 7
// Set to '1' if board draws excessive current
// *****************[ STK parameter constants ]***************************
#define PARAM_BUILD_NUMBER_LOW 0x80
#define PARAM_BUILD_NUMBER_HIGH 0x81
#define PARAM_BUILD_NUMBER_LOW 0x80 /* ??? */
#define PARAM_BUILD_NUMBER_HIGH 0x81 /* ??? */
#define PARAM_HW_VER 0x90
#define PARAM_SW_MAJOR 0x91
#define PARAM_SW_MINOR 0x92
#define PARAM_VTARGET 0x94
#define PARAM_VADJUST 0x95
#define PARAM_OSC_PSCALE 0x96
#define PARAM_OSC_CMATCH 0x97
#define PARAM_SCK_DURATION 0x98
#define PARAM_TOPCARD_DETECT 0x9A
#define PARAM_STATUS 0x9C
#define PARAM_DATA 0x9D
#define PARAM_RESET_POLARITY 0x9E
#define PARAM_VADJUST 0x95 /* STK500 only */
#define PARAM_OSC_PSCALE 0x96 /* STK500 only */
#define PARAM_OSC_CMATCH 0x97 /* STK500 only */
#define PARAM_SCK_DURATION 0x98 /* STK500 only */
#define PARAM_TOPCARD_DETECT 0x9A /* STK500 only */
#define PARAM_STATUS 0x9C /* STK500 only */
#define PARAM_DATA 0x9D /* STK500 only */
#define PARAM_RESET_POLARITY 0x9E /* STK500 only, and STK600 FW
* version <= 2.0.3 */
#define PARAM_CONTROLLER_INIT 0x9F
/* STK600 parameters */
#define PARAM_STATUS_TGT_CONN 0xA1
#define PARAM_DISCHARGEDELAY 0xA4
#define PARAM_SOCKETCARD_ID 0xA5
#define PARAM_ROUTINGCARD_ID 0xA6
#define PARAM_EXPCARD_ID 0xA7
#define PARAM_SW_MAJOR_SLAVE1 0xA8
#define PARAM_SW_MINOR_SLAVE1 0xA9
#define PARAM_SW_MAJOR_SLAVE2 0xAA
#define PARAM_SW_MINOR_SLAVE2 0xAB
#define PARAM_BOARD_ID_STATUS 0xAD
#define PARAM_RESET 0xB4
#define PARAM_JTAG_ALLOW_FULL_PAGE_STREAM 0x50
#define PARAM_JTAG_EEPROM_PAGE_SIZE 0x52
#define PARAM_JTAG_DAISY_BITS_BEFORE 0x53
#define PARAM_JTAG_DAISY_BITS_AFTER 0x54
#define PARAM_JTAG_DAISY_UNITS_BEFORE 0x55
#define PARAM_JTAG_DAISY_UNITS_AFTER 0x56
// *** Parameter constants for 2 byte values ***
#define PARAM2_SCK_DURATION 0xC0
#define PARAM2_CLOCK_CONF 0xC1
#define PARAM2_AREF0 0xC2
#define PARAM2_AREF1 0xC3
#define PARAM2_JTAG_FLASH_SIZE_H 0xC5
#define PARAM2_JTAG_FLASH_SIZE_L 0xC6
#define PARAM2_JTAG_FLASH_PAGE_SIZE 0xC7
#define PARAM2_RC_ID_TABLE_REV 0xC8
#define PARAM2_EC_ID_TABLE_REV 0xC9
/* STK600 XPROG section */
// XPROG commands
#define XPRG_CMD_ENTER_PROGMODE 0x01
#define XPRG_CMD_LEAVE_PROGMODE 0x02
#define XPRG_CMD_ERASE 0x03
#define XPRG_CMD_WRITE_MEM 0x04
#define XPRG_CMD_READ_MEM 0x05
#define XPRG_CMD_CRC 0x06
#define XPRG_CMD_SET_PARAM 0x07
// Memory types
#define XPRG_MEM_TYPE_APPL 1
#define XPRG_MEM_TYPE_BOOT 2
#define XPRG_MEM_TYPE_EEPROM 3
#define XPRG_MEM_TYPE_FUSE 4
#define XPRG_MEM_TYPE_LOCKBITS 5
#define XPRG_MEM_TYPE_USERSIG 6
#define XPRG_MEM_TYPE_FACTORY_CALIBRATION 7
// Erase types
#define XPRG_ERASE_CHIP 1
#define XPRG_ERASE_APP 2
#define XPRG_ERASE_BOOT 3
#define XPRG_ERASE_EEPROM 4
#define XPRG_ERASE_APP_PAGE 5
#define XPRG_ERASE_BOOT_PAGE 6
#define XPRG_ERASE_EEPROM_PAGE 7
#define XPRG_ERASE_USERSIG 8
// Write mode flags
#define XPRG_MEM_WRITE_ERASE 0
#define XPRG_MEM_WRITE_WRITE 1
// CRC types
#define XPRG_CRC_APP 1
#define XPRG_CRC_BOOT 2
#define XPRG_CRC_FLASH 3
// Error codes
#define XPRG_ERR_OK 0
#define XPRG_ERR_FAILED 1
#define XPRG_ERR_COLLISION 2
#define XPRG_ERR_TIMEOUT 3
// XPROG parameters of different sizes
// 4-byte address
#define XPRG_PARAM_NVMBASE 0x01
// 2-byte page size
#define XPRG_PARAM_EEPPAGESIZE 0x02
// *****************[ STK answer constants ]***************************
#define ANSWER_CKSUM_ERROR 0xB0

33
term.c
View File

@ -662,25 +662,42 @@ static int cmd_varef(PROGRAMMER * pgm, struct avrpart * p,
int argc, char * argv[])
{
int rc;
unsigned int chan;
double v;
char *endp;
if (argc != 2) {
fprintf(stderr, "Usage: varef <value>\n");
if (argc != 2 && argc != 3) {
fprintf(stderr, "Usage: varef [channel] <value>\n");
return -1;
}
v = strtod(argv[1], &endp);
if (endp == argv[1]) {
fprintf(stderr, "%s (varef): can't parse voltage \"%s\"\n",
progname, argv[1]);
return -1;
if (argc == 2) {
chan = 0;
v = strtod(argv[1], &endp);
if (endp == argv[1]) {
fprintf(stderr, "%s (varef): can't parse voltage \"%s\"\n",
progname, argv[1]);
return -1;
}
} else {
chan = strtoul(argv[1], &endp, 10);
if (endp == argv[1]) {
fprintf(stderr, "%s (varef): can't parse channel \"%s\"\n",
progname, argv[1]);
return -1;
}
v = strtod(argv[2], &endp);
if (endp == argv[2]) {
fprintf(stderr, "%s (varef): can't parse voltage \"%s\"\n",
progname, argv[2]);
return -1;
}
}
if (pgm->set_varef == NULL) {
fprintf(stderr, "%s (varef): the %s programmer cannot set V[aref]\n",
progname, pgm->type);
return -2;
}
if ((rc = pgm->set_varef(pgm, v)) != 0) {
if ((rc = pgm->set_varef(pgm, chan, v)) != 0) {
fprintf(stderr, "%s (varef): failed to set V[aref] (rc = %d)\n",
progname, rc);
return -3;

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding='ISO-8859-1' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--
* Copyright (c) 2008 Joerg Wunsch
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*
* $Id$
-->
<!--
* Extract STK600 routing and socket card information out of
* targetboards.xml.
*
* Run this like:
*
* xsltproc -param what "'RC'" \
* tools/get-stk600-cards.xsl targetboard.xml | sort -u
*
* xsltproc -param what "'SC'" \
* tools/get-stk600-cards.xsl targetboard.xml | sort -u
*
* and copy&paste the results into the respective tables.
-->
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:if test="$what = 'RC'">
<xsl:for-each select="/STK600/ROUTING/CARD">
<xsl:if test="RC_NAME != ''">
<xsl:text> { </xsl:text>
<xsl:value-of select="RC_ID" />
<xsl:text>, &#034;</xsl:text>
<xsl:value-of select="RC_NAME" />
<xsl:text>&#034; },&#010;</xsl:text>
</xsl:if>
</xsl:for-each> <!-- All cards -->
</xsl:if> <!-- Routing cards -->
<xsl:if test="$what = 'SC'">
<xsl:for-each select="/STK600/ROUTING/CARD">
<xsl:if test="SC_NAME != ''">
<xsl:text> { </xsl:text>
<xsl:value-of select="SC_ID" />
<xsl:text>, &#034;</xsl:text>
<xsl:value-of select="SC_NAME" />
<xsl:text>&#034; },&#010;</xsl:text>
</xsl:if>
</xsl:for-each> <!-- All cards -->
</xsl:if> <!-- Socket cards -->
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding='ISO-8859-1' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--
* Copyright (c) 2008 Joerg Wunsch
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*
* $Id$
-->
<!--
* Extract STK600 device support out of
* targetboards.xml.
*
* Run this like:
*
* xsltproc \
* tools/get-stk600-devices.xsl targetboard.xml
*
* and copy&paste the results into the respective table.
-->
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:text>@multitable @columnfractions .15 .15 .6&#010;</xsl:text>
<xsl:text>Routing card @tab Socket card @tab Devices&#010;</xsl:text>
<xsl:for-each select="/STK600/ROUTING/CARD">
<xsl:text>@item @code{</xsl:text>
<xsl:value-of select="RC_NAME" />
<xsl:text>} @tab @code{</xsl:text>
<xsl:value-of select="SC_NAME" />
<xsl:text>} @tab</xsl:text>
<xsl:for-each select="TARGET">
<xsl:text> </xsl:text>
<xsl:value-of select="NAME" />
</xsl:for-each>
<xsl:text>&#010;</xsl:text>
</xsl:for-each> <!-- All cards -->
<xsl:text>@end multitable&#010;</xsl:text>
</xsl:template>
</xsl:stylesheet>

View File

@ -59,6 +59,7 @@ static void usbdev_open(char * port, long baud, union filedescriptor *fd)
struct usb_device *dev;
usb_dev_handle *udev;
char *serno, *cp2;
int i;
size_t x;
/*
@ -187,7 +188,33 @@ static void usbdev_open(char * port, long baud, union filedescriptor *fd)
goto trynext;
}
fd->pfd = udev;
fd->usb.handle = udev;
fd->usb.ep = -1;
/* Try finding out what our read endpoint is. */
for (i = 0; i < dev->config[0].interface[0].altsetting[0].bNumEndpoints; i++)
{
int possible_ep = dev->config[0].interface[0].altsetting[0].
endpoint[i].bEndpointAddress;
if ((possible_ep & USB_ENDPOINT_DIR_MASK) != 0)
{
if (verbose > 1)
{
fprintf(stderr,
"%s: usbdev_open(): using read endpoint 0x%02x\n",
progname, possible_ep);
}
fd->usb.ep = possible_ep;
break;
}
}
if (fd->usb.ep == -1)
{
fprintf(stderr,
"%s: usbdev_open(): cannot find a read endpoint, using 0x%02x\n",
progname, USBDEV_BULK_EP_READ);
fd->usb.ep = USBDEV_BULK_EP_READ;
}
return;
}
trynext:
@ -203,7 +230,7 @@ static void usbdev_open(char * port, long baud, union filedescriptor *fd)
static void usbdev_close(union filedescriptor *fd)
{
usb_dev_handle *udev = (usb_dev_handle *)fd->pfd;
usb_dev_handle *udev = (usb_dev_handle *)fd->usb.handle;
(void)usb_release_interface(udev, usb_interface);
@ -219,7 +246,7 @@ static void usbdev_close(union filedescriptor *fd)
static int usbdev_send(union filedescriptor *fd, unsigned char *bp, size_t mlen)
{
usb_dev_handle *udev = (usb_dev_handle *)fd->pfd;
usb_dev_handle *udev = (usb_dev_handle *)fd->usb.handle;
int rv;
int i = mlen;
unsigned char * p = bp;
@ -276,11 +303,11 @@ static int usbdev_send(union filedescriptor *fd, unsigned char *bp, size_t mlen)
* empty and more data are requested.
*/
static int
usb_fill_buf(usb_dev_handle *udev)
usb_fill_buf(usb_dev_handle *udev, int ep)
{
int rv;
rv = usb_bulk_read(udev, USBDEV_BULK_EP_READ, usbbuf, USBDEV_MAX_XFER, 5000);
rv = usb_bulk_read(udev, ep, usbbuf, USBDEV_MAX_XFER, 5000);
if (rv < 0)
{
if (verbose > 1)
@ -297,7 +324,7 @@ usb_fill_buf(usb_dev_handle *udev)
static int usbdev_recv(union filedescriptor *fd, unsigned char *buf, size_t nbytes)
{
usb_dev_handle *udev = (usb_dev_handle *)fd->pfd;
usb_dev_handle *udev = (usb_dev_handle *)fd->usb.handle;
int i, amnt;
unsigned char * p = buf;
@ -305,7 +332,7 @@ static int usbdev_recv(union filedescriptor *fd, unsigned char *buf, size_t nbyt
{
if (buflen <= bufptr)
{
if (usb_fill_buf(udev) < 0)
if (usb_fill_buf(udev, fd->usb.ep) < 0)
return -1;
}
amnt = buflen - bufptr > nbytes? nbytes: buflen - bufptr;
@ -349,7 +376,7 @@ static int usbdev_recv(union filedescriptor *fd, unsigned char *buf, size_t nbyt
*/
static int usbdev_recv_frame(union filedescriptor *fd, unsigned char *buf, size_t nbytes)
{
usb_dev_handle *udev = (usb_dev_handle *)fd->pfd;
usb_dev_handle *udev = (usb_dev_handle *)fd->usb.handle;
int rv, n;
int i;
unsigned char * p = buf;
@ -357,7 +384,7 @@ static int usbdev_recv_frame(union filedescriptor *fd, unsigned char *buf, size_
n = 0;
do
{
rv = usb_bulk_read(udev, USBDEV_BULK_EP_READ, usbbuf,
rv = usb_bulk_read(udev, fd->usb.ep, usbbuf,
USBDEV_MAX_XFER, 10000);
if (rv < 0)
{
@ -406,11 +433,11 @@ static int usbdev_recv_frame(union filedescriptor *fd, unsigned char *buf, size_
static int usbdev_drain(union filedescriptor *fd, int display)
{
usb_dev_handle *udev = (usb_dev_handle *)fd->pfd;
usb_dev_handle *udev = (usb_dev_handle *)fd->usb.handle;
int rv;
do {
rv = usb_bulk_read(udev, USBDEV_BULK_EP_READ, usbbuf, USBDEV_MAX_XFER, 100);
rv = usb_bulk_read(udev, fd->usb.ep, usbbuf, USBDEV_MAX_XFER, 100);
if (rv > 0 && verbose >= 4)
fprintf(stderr, "%s: usbdev_drain(): flushed %d characters\n",
progname, rv);

View File

@ -29,6 +29,7 @@
#define USB_VENDOR_ATMEL 1003
#define USB_DEVICE_JTAGICEMKII 0x2103
#define USB_DEVICE_AVRISPMKII 0x2104
#define USB_DEVICE_STK600 0x2106
#define USB_DEVICE_AVRDRAGON 0x2107
/*