Add support for the JTAG ICE mkII in ISP mode.
* avrdude.conf.in (jtag2isp): New programmer entry. * config_gram.y: Add K_JTAG_MKII_ISP. * jtagmkII.c: Restructure and export some more functions. * jtagmkII.h: Declare exported functions. * jtagmkII_private.h: Prepare file to be included in stk500v2.c. * lexer.l: Add jtagmkii_isp token. * stk500v2.c: Implement glue to jtagmkII.c. * stk500v2.h: Declare stk500v2_jtagmkII_initpgm(). * avrdude.1: Document the new programmer support. * doc/avrdude.texi: (Ditto.) git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@643 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
7c235970a1
commit
995bd68034
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2006-09-06 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
|
||||
Add support for the JTAG ICE mkII in ISP mode.
|
||||
* avrdude.conf.in (jtag2isp): New programmer entry.
|
||||
* config_gram.y: Add K_JTAG_MKII_ISP.
|
||||
* jtagmkII.c: Restructure and export some more functions.
|
||||
* jtagmkII.h: Declare exported functions.
|
||||
* jtagmkII_private.h: Prepare file to be included in stk500v2.c.
|
||||
* lexer.l: Add jtagmkii_isp token.
|
||||
* stk500v2.c: Implement glue to jtagmkII.c.
|
||||
* stk500v2.h: Declare stk500v2_jtagmkII_initpgm().
|
||||
* avrdude.1: Document the new programmer support.
|
||||
* doc/avrdude.texi: (Ditto.)
|
||||
|
||||
2006-09-01 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
|
||||
* main.c: Add date and time of compilation to the verbose
|
||||
|
|
3
NEWS
3
NEWS
|
@ -23,6 +23,9 @@ Current:
|
|||
* Add high-voltage mode programming for the STK500 (both,
|
||||
parallel, and high-voltage serial programming).
|
||||
|
||||
* Add support for using the JTAG ICE mkII as a generic ISP
|
||||
programmer.
|
||||
|
||||
* Allow for specifying the ISP clock delay as an option for
|
||||
bit-bang programming adapters.
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
.\"
|
||||
.\" $Id$
|
||||
.\"
|
||||
.Dd DATE August 16, 2006
|
||||
.Dd DATE September 6, 2006
|
||||
.Os
|
||||
.Dt AVRDUDE 1
|
||||
.Sh NAME
|
||||
|
@ -57,7 +57,7 @@ microcontrollers.
|
|||
.Nm Avrdude
|
||||
supports Atmel's STK500 programmer,
|
||||
Atmel's AVRISP and AVRISP mkII devices,
|
||||
Atmel's JTAG ICE (both mkI and mkII),
|
||||
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
|
||||
programmer connected directly to a
|
||||
|
@ -111,6 +111,7 @@ supported on a serial port.
|
|||
.Pp
|
||||
Atmel's JTAG ICE (both mkI and mkII) is supported as well to up- or download memory
|
||||
areas from/to an AVR target (no support for on-chip debugging).
|
||||
For the JTAG ICE mkII, both JTAG and ISP mode are supported.
|
||||
.Pp
|
||||
Input files can be provided, and output files can be written in
|
||||
different file formats, such as raw binary files containing the data
|
||||
|
@ -219,7 +220,7 @@ and bit-bang programmers.
|
|||
Override the RS-232 connection baud rate specified in the respective
|
||||
programmer's entry of the configuration file.
|
||||
.It Fl B Ar bitclock
|
||||
Specify the bit clock period for the JTAG interface (JTAG ICE only).
|
||||
Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only).
|
||||
The value is a floating-point number in microseconds.
|
||||
The default value of the JTAG ICE results in about 1 microsecond bit
|
||||
clock period, suitable for target MCUs running at 4 MHz clock and
|
||||
|
@ -629,6 +630,8 @@ microseconds.
|
|||
Note that unlike STK500 settings, this setting will be reverted to
|
||||
its default value (approximately 1 microsecond) when the programming
|
||||
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:
|
||||
Display the current voltage and master oscillator parameters.
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
# id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
|
||||
# desc = <description> ; # quoted string
|
||||
# type = par | stk500 | stk500v2 | stk500pp | stk500hvsp |
|
||||
# avr910 | jtagmki | jtagmkii; # programmer type
|
||||
# avr910 | jtagmki | jtagmkii | jtagmkii_isp; # programmer type
|
||||
# baudrate = <num> ; # baudrate for avr910-programmer
|
||||
# vcc = <num1> [, <num2> ... ] ; # pin number(s)
|
||||
# reset = <num> ; # pin number
|
||||
|
@ -425,6 +425,14 @@ programmer
|
|||
type = jtagmkii;
|
||||
;
|
||||
|
||||
# JTAG ICE mkII in ISP mode
|
||||
programmer
|
||||
id = "jtag2isp";
|
||||
desc = "Atmel JTAG ICE mkII in ISP mode";
|
||||
baudrate = 115200;
|
||||
type = jtagmkii_isp;
|
||||
;
|
||||
|
||||
programmer
|
||||
id = "pavr";
|
||||
desc = "Jason Kyle's pAVR Serial Programmer";
|
||||
|
|
|
@ -95,6 +95,7 @@ static int parse_cmdbits(OPCODE * op);
|
|||
%token K_IO
|
||||
%token K_JTAG_MKI
|
||||
%token K_JTAG_MKII
|
||||
%token K_JTAG_MKII_ISP
|
||||
%token K_LOADPAGE
|
||||
%token K_MAX_WRITE_DELAY
|
||||
%token K_MIN_WRITE_DELAY
|
||||
|
@ -414,6 +415,12 @@ prog_parm :
|
|||
}
|
||||
} |
|
||||
|
||||
K_TYPE TKN_EQUAL K_JTAG_MKII_ISP {
|
||||
{
|
||||
stk500v2_jtagmkII_initpgm(current_prog);
|
||||
}
|
||||
} |
|
||||
|
||||
K_DESC TKN_EQUAL TKN_STRING {
|
||||
strncpy(current_prog->desc, $3->value.string, PGM_DESCLEN);
|
||||
current_prog->desc[PGM_DESCLEN-1] = 0;
|
||||
|
|
|
@ -143,7 +143,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 JTAG ICE (both mkI and mkII), appnote
|
||||
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,
|
||||
and the PPI (parallel port interface). PPI represents a class
|
||||
|
@ -182,6 +182,8 @@ protocol is more sophisticated.
|
|||
(The JTAG ICE mkII protocol can also be run on top of USB.)
|
||||
Only the memory programming functionality of the JTAG ICE is supported
|
||||
by AVRDUDE.
|
||||
For the JTAG ICE mkII, both JTAG and ISP mode are supported.
|
||||
|
||||
|
||||
@menu
|
||||
* History::
|
||||
|
@ -407,7 +409,7 @@ Override the RS-232 connection baud rate specified in the respective
|
|||
programmer's entry of the configuration file.
|
||||
|
||||
@item -B @var{bitclock}
|
||||
Specify the bit clock period for the JTAG interface (JTAG ICE only).
|
||||
Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only).
|
||||
The value is a floating-point number in microseconds.
|
||||
The default value of the JTAG ICE results in about 1 microsecond bit
|
||||
clock period, suitable for target MCUs running at 4 MHz clock and
|
||||
|
@ -487,6 +489,9 @@ Atmel JTAG ICE mkII, running at 115200 Bd
|
|||
@itemx jtag2
|
||||
Same as before.
|
||||
|
||||
@itemx jtag2isp
|
||||
Atmel JTAG ICE mkII in ISP mode.
|
||||
|
||||
@itemx pavr
|
||||
Jason Kyle's pAVR Serial Programmer
|
||||
|
||||
|
@ -1052,6 +1057,8 @@ Set the JTAG ICE bit clock period to @var{period} microseconds.
|
|||
Note that unlike STK500 settings, this setting will be reverted to
|
||||
its default value (approximately 1 microsecond) when the programming
|
||||
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.
|
||||
|
||||
@item parms
|
||||
@emph{STK500 only:}
|
||||
|
|
92
jtagmkII.c
92
jtagmkII.c
|
@ -89,8 +89,6 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
|||
static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char data);
|
||||
static int jtagmkII_set_sck_period(PROGRAMMER * pgm, double v);
|
||||
static int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm,
|
||||
unsigned char * value);
|
||||
static int jtagmkII_setparm(PROGRAMMER * pgm, unsigned char parm,
|
||||
unsigned char * value);
|
||||
static void jtagmkII_print_parms1(PROGRAMMER * pgm, char * p);
|
||||
|
@ -291,7 +289,7 @@ static void jtagmkII_prmsg(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
|||
}
|
||||
|
||||
|
||||
static int jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
||||
int jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
|
@ -493,7 +491,7 @@ fprintf(stderr, "\n");
|
|||
return msglen;
|
||||
}
|
||||
|
||||
static int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg) {
|
||||
int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg) {
|
||||
unsigned short r_seqno;
|
||||
int rv;
|
||||
|
||||
|
@ -531,7 +529,7 @@ static int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg) {
|
|||
}
|
||||
|
||||
|
||||
static int jtagmkII_getsync(PROGRAMMER * pgm) {
|
||||
int jtagmkII_getsync(PROGRAMMER * pgm, int mode) {
|
||||
int tries;
|
||||
#define MAXTRIES 33
|
||||
unsigned char buf[3], *resp, c = 0xff;
|
||||
|
@ -625,14 +623,24 @@ static int jtagmkII_getsync(PROGRAMMER * pgm) {
|
|||
} else if (fwver < FWVER(4, 0)) {
|
||||
device_descriptor_length -= 2;
|
||||
}
|
||||
#undef FWVER
|
||||
if (verbose >= 2)
|
||||
if (verbose >= 2 && mode != EMULATOR_MODE_SPI)
|
||||
fprintf(stderr,
|
||||
"%s: jtagmkII_getsync(): Using a %zu-byte device descriptor\n",
|
||||
progname, device_descriptor_length);
|
||||
if (mode == EMULATOR_MODE_SPI) {
|
||||
device_descriptor_length = 0;
|
||||
if (fwver < FWVER(4, 14)) {
|
||||
fprintf(stderr,
|
||||
"%s: jtagmkII_getsync(): ISP functionality requires firmware "
|
||||
"version >= 4.14\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#undef FWVER
|
||||
|
||||
/* Turn the ICE into JTAG mode */
|
||||
buf[0] = EMULATOR_MODE_JTAG;
|
||||
/* Turn the ICE into JTAG or ISP mode as requested. */
|
||||
buf[0] = mode;
|
||||
if (jtagmkII_setparm(pgm, PAR_EMULATOR_MODE, buf) < 0)
|
||||
return -1;
|
||||
|
||||
|
@ -1058,7 +1066,6 @@ static int jtagmkII_open(PROGRAMMER * pgm, char * port)
|
|||
*/
|
||||
baud = 19200;
|
||||
|
||||
#if defined(HAVE_LIBUSB)
|
||||
/*
|
||||
* If the port name starts with "usb", divert the serial routines
|
||||
* to the USB ones. The serial_open() function for USB overrides
|
||||
|
@ -1066,10 +1073,14 @@ static int jtagmkII_open(PROGRAMMER * pgm, char * port)
|
|||
* search for.
|
||||
*/
|
||||
if (strncmp(port, "usb", 3) == 0) {
|
||||
#if defined(HAVE_LIBUSB)
|
||||
serdev = &usb_serdev;
|
||||
baud = USB_DEVICE_JTAGICEMKII;
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "avrdude was compiled without usb support.\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
strcpy(pgm->port, port);
|
||||
pgm->fd = serial_open(port, baud);
|
||||
|
@ -1079,13 +1090,13 @@ static int jtagmkII_open(PROGRAMMER * pgm, char * port)
|
|||
*/
|
||||
jtagmkII_drain(pgm, 0);
|
||||
|
||||
jtagmkII_getsync(pgm);
|
||||
jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void jtagmkII_close(PROGRAMMER * pgm)
|
||||
void jtagmkII_close(PROGRAMMER * pgm)
|
||||
{
|
||||
int status;
|
||||
unsigned char buf[1], *resp, c;
|
||||
|
@ -1093,33 +1104,36 @@ static void jtagmkII_close(PROGRAMMER * pgm)
|
|||
if (verbose >= 2)
|
||||
fprintf(stderr, "%s: jtagmkII_close()\n", progname);
|
||||
|
||||
buf[0] = CMND_GO;
|
||||
if (verbose >= 2)
|
||||
fprintf(stderr, "%s: jtagmkII_close(): Sending GO command: ",
|
||||
progname);
|
||||
jtagmkII_send(pgm, buf, 1);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
if (status <= 0) {
|
||||
if (device_descriptor_length) {
|
||||
/* When in JTAG mode, restart target. */
|
||||
buf[0] = CMND_GO;
|
||||
if (verbose >= 2)
|
||||
putc('\n', stderr);
|
||||
fprintf(stderr,
|
||||
"%s: jtagmkII_close(): "
|
||||
"timeout/error communicating with programmer (status %d)\n",
|
||||
progname, status);
|
||||
} else {
|
||||
if (verbose >= 3) {
|
||||
putc('\n', stderr);
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else if (verbose == 2)
|
||||
fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status);
|
||||
c = resp[0];
|
||||
free(resp);
|
||||
if (c != RSP_OK) {
|
||||
fprintf(stderr, "%s: jtagmkII_close(): Sending GO command: ",
|
||||
progname);
|
||||
jtagmkII_send(pgm, buf, 1);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
if (status <= 0) {
|
||||
if (verbose >= 2)
|
||||
putc('\n', stderr);
|
||||
fprintf(stderr,
|
||||
"%s: jtagmkII_close(): "
|
||||
"bad response to GO command: 0x%02x\n",
|
||||
progname, c);
|
||||
"timeout/error communicating with programmer (status %d)\n",
|
||||
progname, status);
|
||||
} else {
|
||||
if (verbose >= 3) {
|
||||
putc('\n', stderr);
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else if (verbose == 2)
|
||||
fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status);
|
||||
c = resp[0];
|
||||
free(resp);
|
||||
if (c != RSP_OK) {
|
||||
fprintf(stderr,
|
||||
"%s: jtagmkII_close(): "
|
||||
"bad response to GO command: 0x%02x\n",
|
||||
progname, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1624,8 +1638,8 @@ static int jtagmkII_set_sck_period(PROGRAMMER * pgm, double v)
|
|||
* bytes by now, we always copy out 4 bytes to *value, so the caller
|
||||
* must have allocated sufficient space.
|
||||
*/
|
||||
static int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm,
|
||||
unsigned char * value)
|
||||
int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm,
|
||||
unsigned char * value)
|
||||
{
|
||||
int status;
|
||||
unsigned char buf[2], *resp, c;
|
||||
|
|
10
jtagmkII.h
10
jtagmkII.h
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
* Copyright (C) 2002-2004, 2006 Brian S. Dean <bsd@bsdhome.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -22,6 +22,14 @@
|
|||
#ifndef jtagmkII_h
|
||||
#define jtagmkII_h
|
||||
|
||||
int jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len);
|
||||
int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg);
|
||||
int jtagmkII_open(PROGRAMMER * pgm, char * port);
|
||||
void jtagmkII_close(PROGRAMMER * pgm);
|
||||
int jtagmkII_getsync(PROGRAMMER * pgm, int mode);
|
||||
int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm,
|
||||
unsigned char * value);
|
||||
|
||||
void jtagmkII_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2005 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2005, 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -26,6 +26,7 @@
|
|||
* Taken from Appnote AVR067
|
||||
*/
|
||||
|
||||
#if !defined(JTAGMKII_PRIVATE_EXPORTED)
|
||||
/*
|
||||
* Communication with the JTAG ICE works in frames. The protocol
|
||||
* somewhat resembles the STK500v2 protocol, yet it is sufficiently
|
||||
|
@ -71,6 +72,8 @@
|
|||
*/
|
||||
#define MAX_MESSAGE 100000
|
||||
|
||||
#endif /* JTAGMKII_PRIVATE_EXPORTED */
|
||||
|
||||
/* ICE command codes */
|
||||
#define CMND_CHIP_ERASE 0x13
|
||||
#define CMND_CLEAR_EVENTS 0x22
|
||||
|
@ -83,6 +86,7 @@
|
|||
#define CMND_GET_SIGN_ON 0x01
|
||||
#define CMND_GET_SYNC 0x0f
|
||||
#define CMND_GO 0x08
|
||||
#define CMND_ISP_PACKET 0x2F
|
||||
#define CMND_LEAVE_PROGMODE 0x15
|
||||
#define CMND_READ_MEMORY 0x05
|
||||
#define CMND_READ_PC 0x07
|
||||
|
@ -232,6 +236,7 @@
|
|||
# define PAGEPROG_NOT_ALLOWED 0x00
|
||||
# define PAGEPROG_ALLOWED 0x01
|
||||
|
||||
#if !defined(JTAGMKII_PRIVATE_EXPORTED)
|
||||
/*
|
||||
* In appnote AVR067, struct device_descriptor is written with
|
||||
* int/long field types. We cannot use them directly, as they were
|
||||
|
@ -288,3 +293,4 @@ struct device_descriptor
|
|||
/* new as of early 2005, firmware 4.x */
|
||||
unsigned char EECRAddress[2]; /* EECR memory-mapped IO address */
|
||||
};
|
||||
#endif /* JTAGMKII_PRIVATE_EXPORTED */
|
||||
|
|
1
lexer.l
1
lexer.l
|
@ -144,6 +144,7 @@ id { yylval=NULL; return K_ID; }
|
|||
idr { yylval=NULL; return K_IDR; }
|
||||
jtagmki { yylval=NULL; return K_JTAG_MKI; }
|
||||
jtagmkii { yylval=NULL; return K_JTAG_MKII; }
|
||||
jtagmkii_isp { yylval=NULL; return K_JTAG_MKII_ISP; }
|
||||
max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; }
|
||||
memory { yylval=NULL; return K_MEMORY; }
|
||||
min_write_delay { yylval=NULL; return K_MIN_WRITE_DELAY; }
|
||||
|
|
293
stk500v2.c
293
stk500v2.c
|
@ -54,6 +54,17 @@
|
|||
#include "serial.h"
|
||||
#include "usbdevs.h"
|
||||
|
||||
/*
|
||||
* We need to import enough from the JTAG ICE mkII definitions to be
|
||||
* able to talk to the ICE, query some parameters etc. The macro
|
||||
* JTAGMKII_PRIVATE_EXPORTED limits the amount of definitions that
|
||||
* jtagmkII_private.h will export, so to avoid conflicts with those
|
||||
* names that are identical to the STK500v2 ones.
|
||||
*/
|
||||
#include "jtagmkII.h" // public interfaces from jtagmkII.c
|
||||
#define JTAGMKII_PRIVATE_EXPORTED
|
||||
#include "jtagmkII_private.h"
|
||||
|
||||
#define STK500V2_XTAL 7372800U
|
||||
|
||||
#if 0
|
||||
|
@ -91,7 +102,6 @@ static unsigned long eeprom_pageaddr;
|
|||
static unsigned int eeprom_pagesize;
|
||||
|
||||
static unsigned char command_sequence = 1;
|
||||
static int is_mk2; /* Is the device an AVRISP mkII? */
|
||||
|
||||
static enum
|
||||
{
|
||||
|
@ -99,6 +109,7 @@ static enum
|
|||
PGMTYPE_STK500,
|
||||
PGMTYPE_AVRISP,
|
||||
PGMTYPE_AVRISP_MKII,
|
||||
PGMTYPE_JTAGICE_MKII,
|
||||
}
|
||||
pgmtype;
|
||||
|
||||
|
@ -108,6 +119,36 @@ static const char *pgmname[] =
|
|||
"STK500",
|
||||
"AVRISP",
|
||||
"AVRISP mkII",
|
||||
"JTAG ICE mkII",
|
||||
};
|
||||
|
||||
struct jtagispentry
|
||||
{
|
||||
unsigned char cmd;
|
||||
unsigned short size;
|
||||
#define SZ_READ_FLASH_EE USHRT_MAX
|
||||
#define SZ_SPI_MULTI (USHRT_MAX - 1)
|
||||
};
|
||||
|
||||
static struct jtagispentry jtagispcmds[] = {
|
||||
{ CMD_SET_PARAMETER, 2 },
|
||||
{ CMD_GET_PARAMETER, 3 },
|
||||
{ CMD_OSCCAL, 2 },
|
||||
{ CMD_LOAD_ADDRESS, 2 },
|
||||
{ CMD_ENTER_PROGMODE_ISP, 2 },
|
||||
{ CMD_LEAVE_PROGMODE_ISP, 2 },
|
||||
{ CMD_CHIP_ERASE_ISP, 2 },
|
||||
{ CMD_PROGRAM_FLASH_ISP, 2 },
|
||||
{ CMD_READ_FLASH_ISP, SZ_READ_FLASH_EE },
|
||||
{ CMD_PROGRAM_EEPROM_ISP, 2 },
|
||||
{ CMD_READ_EEPROM_ISP, SZ_READ_FLASH_EE },
|
||||
{ CMD_PROGRAM_FUSE_ISP, 3 },
|
||||
{ CMD_READ_FUSE_ISP, 4 },
|
||||
{ CMD_PROGRAM_LOCK_ISP, 3 },
|
||||
{ CMD_READ_LOCK_ISP, 4 },
|
||||
{ CMD_READ_SIGNATURE_ISP, 4 },
|
||||
{ CMD_READ_OSCCAL_ISP, 4 },
|
||||
{ CMD_SPI_MULTI, SZ_SPI_MULTI }
|
||||
};
|
||||
|
||||
static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value);
|
||||
|
@ -118,9 +159,17 @@ static int stk500v2_is_page_empty(unsigned int address, int page_size,
|
|||
|
||||
static unsigned int stk500v2_mode_for_pagesize(unsigned int pagesize);
|
||||
|
||||
#if defined(HAVE_LIBUSB)
|
||||
static int stk500v2_set_sck_period_mk2(PROGRAMMER * pgm, double v);
|
||||
#endif
|
||||
|
||||
static unsigned short
|
||||
b2_to_u16(unsigned char *b)
|
||||
{
|
||||
unsigned short l;
|
||||
l = b[0];
|
||||
l += (unsigned)b[1] << 8;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static int stk500v2_send_mk2(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
||||
{
|
||||
|
@ -132,13 +181,74 @@ static int stk500v2_send_mk2(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned short get_jtagisp_return_size(unsigned char cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof jtagispcmds / sizeof jtagispcmds[0]; i++)
|
||||
if (jtagispcmds[i].cmd == cmd)
|
||||
return jtagispcmds[i].size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the data as a JTAG ICE mkII encapsulated ISP packet.
|
||||
* Unlike what AVR067 says, the packet gets a length of our
|
||||
* response buffer prepended, and replies with RSP_SPI_DATA
|
||||
* if successful.
|
||||
*/
|
||||
static int stk500v2_jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
||||
{
|
||||
unsigned char *cmdbuf;
|
||||
int rv;
|
||||
unsigned short sz;
|
||||
|
||||
sz = get_jtagisp_return_size(data[0]);
|
||||
if (sz == 0) {
|
||||
fprintf(stderr, "%s: unsupported encapsulated ISP command: %#x\n",
|
||||
progname, data[0]);
|
||||
return -1;
|
||||
}
|
||||
if (sz == SZ_READ_FLASH_EE) {
|
||||
/*
|
||||
* For CMND_READ_FLASH_ISP and CMND_READ_EEPROM_ISP, extract the
|
||||
* size of the return data from the request. Note that the
|
||||
* request itself has the size in big endian format, while we are
|
||||
* supposed to deliver it in little endian.
|
||||
*/
|
||||
sz = 3 + (data[1] << 8) + data[2];
|
||||
} else if (sz == SZ_SPI_MULTI) {
|
||||
/*
|
||||
* CMND_SPI_MULTI has the Rx size encoded in its 3rd byte.
|
||||
*/
|
||||
sz = 3 + data[2];
|
||||
}
|
||||
|
||||
if ((cmdbuf = malloc(len + 3)) == NULL) {
|
||||
fprintf(stderr, "%s: out of memory for command packet\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
cmdbuf[0] = CMND_ISP_PACKET;
|
||||
cmdbuf[1] = sz & 0xff;
|
||||
cmdbuf[2] = (sz >> 8) & 0xff;
|
||||
memcpy(cmdbuf + 3, data, len);
|
||||
rv = jtagmkII_send(pgm, cmdbuf, len + 3);
|
||||
free(cmdbuf);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
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 (is_mk2)
|
||||
if (pgmtype == PGMTYPE_AVRISP_MKII)
|
||||
return stk500v2_send_mk2(pgm, data, len);
|
||||
else if (pgmtype == PGMTYPE_JTAGICE_MKII)
|
||||
return stk500v2_jtagmkII_send(pgm, data, len);
|
||||
|
||||
buf[0] = MESSAGE_START;
|
||||
buf[1] = command_sequence;
|
||||
|
@ -184,6 +294,44 @@ static int stk500v2_recv_mk2(PROGRAMMER * pgm, unsigned char msg[],
|
|||
return rv;
|
||||
}
|
||||
|
||||
static int stk500v2_jtagmkII_recv(PROGRAMMER * pgm, unsigned char msg[],
|
||||
size_t maxsize)
|
||||
{
|
||||
int rv;
|
||||
unsigned char *jtagmsg;
|
||||
|
||||
rv = jtagmkII_recv(pgm, &jtagmsg);
|
||||
if (rv <= 0) {
|
||||
fprintf(stderr, "%s: stk500v2_jtagmkII_recv(): error in jtagmkII_recv()\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
if (rv > maxsize) {
|
||||
fprintf(stderr,
|
||||
"%s: stk500v2_jtagmkII_recv(): got %u bytes, have only room for %u bytes\n",
|
||||
progname, (unsigned)rv, maxsize);
|
||||
rv = maxsize;
|
||||
}
|
||||
switch (jtagmsg[0]) {
|
||||
case RSP_SPI_DATA:
|
||||
break;
|
||||
case RSP_FAILED:
|
||||
fprintf(stderr, "%s: stk500v2_jtagmkII_recv(): failed\n",
|
||||
progname);
|
||||
return -1;
|
||||
case RSP_ILLEGAL_MCU_STATE:
|
||||
fprintf(stderr, "%s: stk500v2_jtagmkII_recv(): illegal MCU state\n",
|
||||
progname);
|
||||
return -1;
|
||||
default:
|
||||
fprintf(stderr, "%s: stk500v2_jtagmkII_recv(): unknown status %d\n",
|
||||
progname, jtagmsg[0]);
|
||||
return -1;
|
||||
}
|
||||
memcpy(msg, jtagmsg + 1, rv - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) {
|
||||
enum states { sINIT, sSTART, sSEQNUM, sSIZE1, sSIZE2, sTOKEN, sDATA, sCSUM, sDONE } state = sSTART;
|
||||
int msglen = 0;
|
||||
|
@ -195,8 +343,10 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize)
|
|||
struct timeval tv;
|
||||
double tstart, tnow;
|
||||
|
||||
if (is_mk2)
|
||||
if (pgmtype == PGMTYPE_AVRISP_MKII)
|
||||
return stk500v2_recv_mk2(pgm, msg, maxsize);
|
||||
else if (pgmtype == PGMTYPE_JTAGICE_MKII)
|
||||
return stk500v2_jtagmkII_recv(pgm, msg, maxsize);
|
||||
|
||||
DEBUG("STK500V2: stk500v2_recv(): ");
|
||||
|
||||
|
@ -301,6 +451,9 @@ static int stk500v2_getsync(PROGRAMMER * pgm) {
|
|||
|
||||
DEBUG("STK500V2: stk500v2_getsync()\n");
|
||||
|
||||
if (pgmtype == PGMTYPE_JTAGICE_MKII)
|
||||
return 0;
|
||||
|
||||
retry:
|
||||
tries++;
|
||||
|
||||
|
@ -702,7 +855,6 @@ static void stk500v2_disable(PROGRAMMER * pgm)
|
|||
if (buf[1] != STATUS_CMD_OK) {
|
||||
fprintf(stderr, "%s: stk500v2_disable(): failed to leave programming mode, got 0x%02x\n",
|
||||
progname,buf[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -769,6 +921,8 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port)
|
|||
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
|
||||
|
@ -779,7 +933,7 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port)
|
|||
#if defined(HAVE_LIBUSB)
|
||||
serdev = &usb_serdev_frame;
|
||||
baud = USB_DEVICE_AVRISPMKII;
|
||||
is_mk2 = 1;
|
||||
pgmtype = PGMTYPE_AVRISP_MKII;
|
||||
pgm->set_sck_period = stk500v2_set_sck_period_mk2;
|
||||
#else
|
||||
fprintf(stderr, "avrdude was compiled without usb support.\n");
|
||||
|
@ -795,8 +949,6 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port)
|
|||
*/
|
||||
stk500v2_drain(pgm, 0);
|
||||
|
||||
pgmtype = PGMTYPE_UNKNOWN;
|
||||
|
||||
stk500v2_getsync(pgm);
|
||||
|
||||
stk500v2_drain(pgm, 0);
|
||||
|
@ -1707,7 +1859,6 @@ double avrispmkIIfreqs[] = {
|
|||
65.0, 61.9, 59.0, 56.3, 53.6, 51.1
|
||||
};
|
||||
|
||||
#if defined(HAVE_LIBUSB)
|
||||
static int stk500v2_set_sck_period_mk2(PROGRAMMER * pgm, double v)
|
||||
{
|
||||
int i;
|
||||
|
@ -1722,7 +1873,6 @@ static int stk500v2_set_sck_period_mk2(PROGRAMMER * pgm, double v)
|
|||
|
||||
return stk500v2_setparm(pgm, PARAM_SCK_DURATION, i);
|
||||
}
|
||||
#endif /* HAVE_LIBUSB */
|
||||
|
||||
/*
|
||||
* Return the "mode" value for the parallel and HVSP modes that
|
||||
|
@ -1837,10 +1987,6 @@ static void stk500v2_display(PROGRAMMER * pgm, char * p)
|
|||
unsigned char maj, min, hdw, topcard;
|
||||
const char *topcard_name, *pgmname;
|
||||
|
||||
stk500v2_getparm(pgm, PARAM_HW_VER, &hdw);
|
||||
stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
|
||||
stk500v2_getparm(pgm, PARAM_SW_MINOR, &min);
|
||||
|
||||
switch (pgmtype) {
|
||||
case PGMTYPE_UNKNOWN: pgmname = "Unknown"; break;
|
||||
case PGMTYPE_STK500: pgmname = "STK500"; break;
|
||||
|
@ -1848,9 +1994,14 @@ static void stk500v2_display(PROGRAMMER * pgm, char * p)
|
|||
case PGMTYPE_AVRISP_MKII: pgmname = "AVRISP mkII"; break;
|
||||
default: pgmname = "None";
|
||||
}
|
||||
fprintf(stderr, "%sProgrammer Model: %s\n", p, pgmname);
|
||||
fprintf(stderr, "%sHardware Version: %d\n", p, hdw);
|
||||
fprintf(stderr, "%sFirmware Version: %d.%02d\n", p, maj, min);
|
||||
if (pgmtype != PGMTYPE_JTAGICE_MKII) {
|
||||
fprintf(stderr, "%sProgrammer Model: %s\n", p, pgmname);
|
||||
stk500v2_getparm(pgm, PARAM_HW_VER, &hdw);
|
||||
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);
|
||||
}
|
||||
|
||||
if (pgmtype == PGMTYPE_STK500) {
|
||||
stk500v2_getparm(pgm, PARAM_TOPCARD_DETECT, &topcard);
|
||||
|
@ -1874,10 +2025,17 @@ static void stk500v2_display(PROGRAMMER * pgm, char * p)
|
|||
static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p)
|
||||
{
|
||||
unsigned char vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
|
||||
unsigned char vtarget_jtag[4];
|
||||
|
||||
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
|
||||
if (pgmtype == PGMTYPE_JTAGICE_MKII) {
|
||||
jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget_jtag);
|
||||
fprintf(stderr, "%sVtarget : %.1f V\n", p,
|
||||
b2_to_u16(vtarget_jtag) / 1000.0);
|
||||
} else {
|
||||
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
|
||||
fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
||||
}
|
||||
stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
|
||||
fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
||||
|
||||
if (pgmtype == PGMTYPE_STK500) {
|
||||
stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust);
|
||||
|
@ -1913,7 +2071,7 @@ static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p)
|
|||
fprintf(stderr, "%.3f %s\n", f, unit);
|
||||
}
|
||||
}
|
||||
if (is_mk2)
|
||||
if (pgmtype == PGMTYPE_AVRISP_MKII || pgmtype == PGMTYPE_JTAGICE_MKII)
|
||||
fprintf(stderr, "%sSCK period : %.2f us\n", p,
|
||||
(float) 1000000 / avrispmkIIfreqs[sck_duration]);
|
||||
else
|
||||
|
@ -1930,6 +2088,72 @@ static void stk500v2_print_parms(PROGRAMMER * pgm)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Wrapper functions for the JTAG ICE mkII in ISP mode. This mode
|
||||
* uses the normal JTAG ICE mkII packet stream to communicate with the
|
||||
* ICE, but then encapsulates AVRISP mkII commands using
|
||||
* CMND_ISP_PACKET.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Open a JTAG ICE mkII in ISP mode.
|
||||
*/
|
||||
static int stk500v2_jtagmkII_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
long baud;
|
||||
|
||||
if (verbose >= 2)
|
||||
fprintf(stderr, "%s: stk500v2_jtagmkII_open()\n", progname);
|
||||
|
||||
/*
|
||||
* The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon
|
||||
* attaching. If the config file or command-line parameters specify
|
||||
* a higher baud rate, we switch to it later on, after establishing
|
||||
* the connection with the ICE.
|
||||
*/
|
||||
baud = 19200;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
baud = USB_DEVICE_JTAGICEMKII;
|
||||
#else
|
||||
fprintf(stderr, "avrdude was compiled without usb support.\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
strcpy(pgm->port, port);
|
||||
pgm->fd = serial_open(port, baud);
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
*/
|
||||
stk500v2_drain(pgm, 0);
|
||||
|
||||
if (jtagmkII_getsync(pgm, EMULATOR_MODE_SPI) != 0) {
|
||||
fprintf(stderr, "%s: failed to sync with the JTAG ICE mkII in ISP mode\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pgmtype = PGMTYPE_JTAGICE_MKII;
|
||||
|
||||
if (pgm->bitclock != 0.0) {
|
||||
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void stk500v2_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
strcpy(pgm->type, "STK500V2");
|
||||
|
@ -2023,3 +2247,30 @@ void stk500hvsp_initpgm(PROGRAMMER * pgm)
|
|||
pgm->set_sck_period = stk500v2_set_sck_period;
|
||||
pgm->page_size = 256;
|
||||
}
|
||||
|
||||
void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
strcpy(pgm->type, "JTAGMKII_ISP");
|
||||
|
||||
/*
|
||||
* 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 = stk500v2_jtagmkII_open;
|
||||
pgm->close = jtagmkII_close;
|
||||
|
||||
/*
|
||||
* optional functions
|
||||
*/
|
||||
pgm->paged_write = stk500v2_paged_write;
|
||||
pgm->paged_load = stk500v2_paged_load;
|
||||
pgm->print_parms = stk500v2_print_parms;
|
||||
pgm->set_sck_period = stk500v2_set_sck_period_mk2;
|
||||
pgm->page_size = 256;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
void stk500v2_initpgm (PROGRAMMER * pgm);
|
||||
void stk500hvsp_initpgm (PROGRAMMER * pgm);
|
||||
void stk500pp_initpgm (PROGRAMMER * pgm);
|
||||
void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue