* pgm_type.c: Add "jtagice3_isp" programmer hook
* avrdude.conf.in: Add "jtag3isp" programmer * jtag3.c: jtag3_setparm() is now public * jtag3.h: (Dito) * stk500v2_private.h: Command 0x1D is CMD_SPI_MULTI only for STK500v2, AVRISPmkII, and JTAGICEmkII; for JTAGICE3, it's CMD_SET_SCK now; also add CMD_GET_SCK * avrpart.c (avr_get_output_index): New function * avrpart.h: (Dito) * stk500v2.c: Implement the pasthrough programmer glue logic for JTAGICE3 in ISP mode * stk500v2.h: (Dito) * avrdude.1: Document the JTAGICE3 support. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1119 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
1acbb2fb64
commit
2c540d02b6
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
||||||
|
2012-12-03 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||||
|
|
||||||
|
* pgm_type.c: Add "jtagice3_isp" programmer hook
|
||||||
|
* avrdude.conf.in: Add "jtag3isp" programmer
|
||||||
|
* jtag3.c: jtag3_setparm() is now public
|
||||||
|
* jtag3.h: (Dito)
|
||||||
|
* stk500v2_private.h: Command 0x1D is CMD_SPI_MULTI only
|
||||||
|
for STK500v2, AVRISPmkII, and JTAGICEmkII; for JTAGICE3,
|
||||||
|
it's CMD_SET_SCK now; also add CMD_GET_SCK
|
||||||
|
* avrpart.c (avr_get_output_index): New function
|
||||||
|
* avrpart.h: (Dito)
|
||||||
|
* stk500v2.c: Implement the pasthrough programmer glue logic
|
||||||
|
for JTAGICE3 in ISP mode
|
||||||
|
* stk500v2.h: (Dito)
|
||||||
|
* avrdude.1: Document the JTAGICE3 support.
|
||||||
|
|
||||||
2012-11-30 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
2012-11-30 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||||
|
|
||||||
* jtag3.c (jtag3_read_byte, jtag3_write_byte): Remove the
|
* jtag3.c (jtag3_read_byte, jtag3_write_byte): Remove the
|
||||||
|
|
2
NEWS
2
NEWS
|
@ -35,7 +35,7 @@ Current:
|
||||||
X3(1), sck = DSR X3(2), mosi = DCD X3(3), reset = RI X3(4))
|
X3(1), sck = DSR X3(2), mosi = DCD X3(3), reset = RI X3(4))
|
||||||
+ diecimila (alias for arduino-ft232r)
|
+ diecimila (alias for arduino-ft232r)
|
||||||
|
|
||||||
- Atmel JTAGICE3 (megaAVR/JTAG, Xmega/JTAG/PDI only so far)
|
- Atmel JTAGICE3
|
||||||
|
|
||||||
* Bugfixes
|
* Bugfixes
|
||||||
- bug #34027: avrdude AT90S1200 Problem
|
- bug #34027: avrdude AT90S1200 Problem
|
||||||
|
|
17
avrdude.1
17
avrdude.1
|
@ -18,7 +18,7 @@
|
||||||
.\"
|
.\"
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.Dd DATE February 2, 2012
|
.Dd DATE December 3, 2012
|
||||||
.Os
|
.Os
|
||||||
.Dt AVRDUDE 1
|
.Dt AVRDUDE 1
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -59,7 +59,7 @@ microcontrollers.
|
||||||
supports Atmel's STK500 programmer,
|
supports Atmel's STK500 programmer,
|
||||||
Atmel's AVRISP and AVRISP mkII devices,
|
Atmel's AVRISP and AVRISP mkII devices,
|
||||||
Atmel's STK600,
|
Atmel's STK600,
|
||||||
Atmel's JTAG ICE (both mkI and mkII, the latter also in ISP mode),
|
Atmel's JTAG ICE (mkI, mkII and 3, the latter two also in ISP mode),
|
||||||
programmers complying to AppNote AVR910 and AVR109 (including the Butterfly),
|
programmers complying to AppNote AVR910 and AVR109 (including the Butterfly),
|
||||||
as well as a simple hard-wired
|
as well as a simple hard-wired
|
||||||
programmer connected directly to a
|
programmer connected directly to a
|
||||||
|
@ -129,13 +129,15 @@ AVR910, and the bootloader described in Atmel's application note
|
||||||
AVR109 (which is also used by the AVR Butterfly evaluation board), are
|
AVR109 (which is also used by the AVR Butterfly evaluation board), are
|
||||||
supported on a serial port.
|
supported on a serial port.
|
||||||
.Pp
|
.Pp
|
||||||
Atmel's JTAG ICE (both mkI and mkII) is supported as well to up- or download memory
|
Atmel's JTAG ICE (mkI, mkII, and 3) is supported as well to up- or download memory
|
||||||
areas from/to an AVR target (no support for on-chip debugging).
|
areas from/to an AVR target (no support for on-chip debugging).
|
||||||
For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported, provided
|
For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported, provided
|
||||||
it has a firmware revision of at least 4.14 (decimal).
|
it has a firmware revision of at least 4.14 (decimal).
|
||||||
|
JTAGICE3 also supports all of JTAG, debugWIRE, and ISP mode.
|
||||||
See below for the limitations of debugWire.
|
See below for the limitations of debugWire.
|
||||||
For ATxmega devices, the JTAG ICE mkII is supported in PDI mode, provided it
|
For ATxmega devices, the JTAG ICE mkII is supported in PDI mode, provided it
|
||||||
has a revision 1 hardware and firmware version of at least 5.37 (decimal).
|
has a revision 1 hardware and firmware version of at least 5.37 (decimal).
|
||||||
|
For ATxmega devices, the JTAGICE3 is supported in PDI mode.
|
||||||
.Pp
|
.Pp
|
||||||
The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP, debugWire).
|
The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP, debugWire).
|
||||||
When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a
|
When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a
|
||||||
|
@ -432,7 +434,7 @@ language notation (i. e., hexadecimal values are prefixed by
|
||||||
.Ql 0x
|
.Ql 0x
|
||||||
).
|
).
|
||||||
.Pp
|
.Pp
|
||||||
For the JTAG ICE mkII, if
|
For the JTAG ICE mkII and JTAGICE3, if
|
||||||
.Nm
|
.Nm
|
||||||
has been configured with libusb support,
|
has been configured with libusb support,
|
||||||
.Ar port
|
.Ar port
|
||||||
|
@ -440,7 +442,7 @@ can alternatively be specified as
|
||||||
.Pa usb Ns Op \&: Ns Ar serialno .
|
.Pa usb Ns Op \&: Ns Ar serialno .
|
||||||
This will cause
|
This will cause
|
||||||
.Nm
|
.Nm
|
||||||
to search a JTAG ICE mkII on USB.
|
to search the programmer on USB.
|
||||||
If
|
If
|
||||||
.Ar serialno
|
.Ar serialno
|
||||||
is also specified, it will be matched against the serial number read
|
is also specified, it will be matched against the serial number read
|
||||||
|
@ -770,7 +772,7 @@ microseconds.
|
||||||
Note that unlike STK500 settings, this setting will be reverted to
|
Note that unlike STK500 settings, this setting will be reverted to
|
||||||
its default value (approximately 1 microsecond) when the programming
|
its default value (approximately 1 microsecond) when the programming
|
||||||
software signs off from the JTAG ICE.
|
software signs off from the JTAG ICE.
|
||||||
This parameter can also be used on the JTAG ICE mkII to specify the
|
This parameter can also be used on the JTAG ICE mkII and JTAGICE3 to specify the
|
||||||
ISP clock period when operating the ICE in ISP mode.
|
ISP clock period when operating the ICE in ISP mode.
|
||||||
.It Ar parms
|
.It Ar parms
|
||||||
.Em STK500 and STK600 programmer only:
|
.Em STK500 and STK600 programmer only:
|
||||||
|
@ -829,8 +831,9 @@ entered.
|
||||||
.Ss Programmers accepting extended parameters
|
.Ss Programmers accepting extended parameters
|
||||||
.Bl -tag -offset indent -width indent
|
.Bl -tag -offset indent -width indent
|
||||||
.It Ar JTAG ICE mkII
|
.It Ar JTAG ICE mkII
|
||||||
|
.It Ar JTAGICE3
|
||||||
.It Ar AVR Dragon
|
.It Ar AVR Dragon
|
||||||
When using the JTAG ICE mkII or AVR Dragon in JTAG mode, the
|
When using the JTAG ICE mkII, JTAGICE3 or AVR Dragon in JTAG mode, the
|
||||||
following extended parameter is accepted:
|
following extended parameter is accepted:
|
||||||
.Bl -tag -offset indent -width indent
|
.Bl -tag -offset indent -width indent
|
||||||
.It Ar jtagchain=UB,UA,BB,BA
|
.It Ar jtagchain=UB,UA,BB,BA
|
||||||
|
|
|
@ -912,6 +912,13 @@ programmer
|
||||||
connection_type = usb;
|
connection_type = usb;
|
||||||
;
|
;
|
||||||
|
|
||||||
|
programmer
|
||||||
|
id = "jtag3isp";
|
||||||
|
desc = "Atmel AVR JTAGICE3 in ISP mode";
|
||||||
|
type = "jtagice3_isp";
|
||||||
|
connection_type = usb;
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
programmer
|
programmer
|
||||||
id = "pavr";
|
id = "pavr";
|
||||||
|
|
21
avrpart.c
21
avrpart.c
|
@ -185,6 +185,27 @@ int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* avr_get_output_index()
|
||||||
|
*
|
||||||
|
* Calculate the byte number of the output data based on the
|
||||||
|
* opcode data.
|
||||||
|
*/
|
||||||
|
int avr_get_output_index(OPCODE * op)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i=0; i<32; i++) {
|
||||||
|
if (op->bit[i].type == AVR_CMDBIT_OUTPUT) {
|
||||||
|
j = 3 - i / 8;
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char * avr_op_str(int op)
|
static char * avr_op_str(int op)
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
|
|
@ -203,6 +203,7 @@ int avr_set_bits(OPCODE * op, unsigned char * cmd);
|
||||||
int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr);
|
int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr);
|
||||||
int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data);
|
int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data);
|
||||||
int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data);
|
int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data);
|
||||||
|
int avr_get_output_index(OPCODE * op);
|
||||||
|
|
||||||
/* Functions for AVRMEM structures */
|
/* Functions for AVRMEM structures */
|
||||||
AVRMEM * avr_new_memtype(void);
|
AVRMEM * avr_new_memtype(void);
|
||||||
|
|
7
jtag3.c
7
jtag3.c
|
@ -106,9 +106,6 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
unsigned long addr, unsigned char data);
|
unsigned long addr, unsigned char data);
|
||||||
static int jtag3_reset(PROGRAMMER * pgm, unsigned char flags);
|
static int jtag3_reset(PROGRAMMER * pgm, unsigned char flags);
|
||||||
static int jtag3_set_sck_period(PROGRAMMER * pgm, double v);
|
static int jtag3_set_sck_period(PROGRAMMER * pgm, double v);
|
||||||
static int jtag3_setparm(PROGRAMMER * pgm, unsigned char scope,
|
|
||||||
unsigned char section, unsigned char parm,
|
|
||||||
unsigned char *value, unsigned char length);
|
|
||||||
static void jtag3_print_parms1(PROGRAMMER * pgm, const char * p);
|
static void jtag3_print_parms1(PROGRAMMER * pgm, const char * p);
|
||||||
static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
|
@ -1554,7 +1551,7 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
/* should not happen */
|
/* should not happen */
|
||||||
fprintf(stderr, "address out of range for signature memory: %u\n", addr);
|
fprintf(stderr, "address out of range for signature memory: %lu\n", addr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1773,7 +1770,7 @@ int jtag3_getparm(PROGRAMMER * pgm, unsigned char scope,
|
||||||
/*
|
/*
|
||||||
* Write an emulator parameter.
|
* Write an emulator parameter.
|
||||||
*/
|
*/
|
||||||
static int jtag3_setparm(PROGRAMMER * pgm, unsigned char scope,
|
int jtag3_setparm(PROGRAMMER * pgm, unsigned char scope,
|
||||||
unsigned char section, unsigned char parm,
|
unsigned char section, unsigned char parm,
|
||||||
unsigned char *value, unsigned char length)
|
unsigned char *value, unsigned char length)
|
||||||
{
|
{
|
||||||
|
|
3
jtag3.h
3
jtag3.h
|
@ -32,6 +32,9 @@ int jtag3_getsync(PROGRAMMER * pgm, int mode);
|
||||||
int jtag3_getparm(PROGRAMMER * pgm, unsigned char scope,
|
int jtag3_getparm(PROGRAMMER * pgm, unsigned char scope,
|
||||||
unsigned char section, unsigned char parm,
|
unsigned char section, unsigned char parm,
|
||||||
unsigned char *value, unsigned char length);
|
unsigned char *value, unsigned char length);
|
||||||
|
int jtag3_setparm(PROGRAMMER * pgm, unsigned char scope,
|
||||||
|
unsigned char section, unsigned char parm,
|
||||||
|
unsigned char *value, unsigned char length);
|
||||||
extern const char jtag3_desc[];
|
extern const char jtag3_desc[];
|
||||||
extern const char jtag3_dw_desc[];
|
extern const char jtag3_dw_desc[];
|
||||||
extern const char jtag3_pdi_desc[];
|
extern const char jtag3_pdi_desc[];
|
||||||
|
|
|
@ -73,6 +73,7 @@ const PROGRAMMER_TYPE const programmers_types[] = {
|
||||||
{"jtagice3", jtag3_initpgm, jtag3_desc},
|
{"jtagice3", jtag3_initpgm, jtag3_desc},
|
||||||
{"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc},
|
{"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc},
|
||||||
{"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc},
|
{"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc},
|
||||||
|
{"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc},
|
||||||
{"par", par_initpgm, par_desc},
|
{"par", par_initpgm, par_desc},
|
||||||
{"pickit2", pickit2_initpgm, pickit2_desc},
|
{"pickit2", pickit2_initpgm, pickit2_desc},
|
||||||
{"serbb", serbb_initpgm, serbb_desc},
|
{"serbb", serbb_initpgm, serbb_desc},
|
||||||
|
|
642
stk500v2.c
642
stk500v2.c
|
@ -67,6 +67,10 @@
|
||||||
#define JTAGMKII_PRIVATE_EXPORTED
|
#define JTAGMKII_PRIVATE_EXPORTED
|
||||||
#include "jtagmkII_private.h"
|
#include "jtagmkII_private.h"
|
||||||
|
|
||||||
|
#include "jtag3.h" // public interfaces from jtagmkII.c
|
||||||
|
#define JTAG3_PRIVATE_EXPORTED
|
||||||
|
#include "jtag3_private.h"
|
||||||
|
|
||||||
#define STK500V2_XTAL 7372800U
|
#define STK500V2_XTAL 7372800U
|
||||||
|
|
||||||
// Timeout (in seconds) for waiting for serial response
|
// Timeout (in seconds) for waiting for serial response
|
||||||
|
@ -113,6 +117,7 @@ static const char *pgmname[] =
|
||||||
"AVRISP mkII",
|
"AVRISP mkII",
|
||||||
"JTAG ICE mkII",
|
"JTAG ICE mkII",
|
||||||
"STK600",
|
"STK600",
|
||||||
|
"JTAGICE3",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct jtagispentry
|
struct jtagispentry
|
||||||
|
@ -267,6 +272,12 @@ static int stk500v2_getparm2(PROGRAMMER * pgm, unsigned char parm, unsigned int
|
||||||
static int stk500v2_setparm2(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 int stk500v2_setparm_real(PROGRAMMER * pgm, unsigned char parm, unsigned char value);
|
||||||
static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p);
|
static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p);
|
||||||
|
static int stk500v2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
|
unsigned int page_size,
|
||||||
|
unsigned int addr, unsigned int n_bytes);
|
||||||
|
static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
|
unsigned int page_size,
|
||||||
|
unsigned int addr, unsigned int n_bytes);
|
||||||
|
|
||||||
static unsigned int stk500v2_mode_for_pagesize(unsigned int pagesize);
|
static unsigned int stk500v2_mode_for_pagesize(unsigned int pagesize);
|
||||||
|
|
||||||
|
@ -315,6 +326,30 @@ static void stk500v2_jtagmkII_setup(PROGRAMMER * pgm)
|
||||||
PDATA(pgm)->chained_pdata = theircookie;
|
PDATA(pgm)->chained_pdata = theircookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stk500v2_jtag3_setup(PROGRAMMER * pgm)
|
||||||
|
{
|
||||||
|
void *mycookie, *theircookie;
|
||||||
|
|
||||||
|
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500v2_setup(): Out of memory allocating private data\n",
|
||||||
|
progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memset(pgm->cookie, 0, sizeof(struct pdata));
|
||||||
|
PDATA(pgm)->command_sequence = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, have the JTAGICE3 backend allocate its own private
|
||||||
|
* data. Store our own cookie in a safe place for the time being.
|
||||||
|
*/
|
||||||
|
mycookie = pgm->cookie;
|
||||||
|
jtag3_setup(pgm);
|
||||||
|
theircookie = pgm->cookie;
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
PDATA(pgm)->chained_pdata = theircookie;
|
||||||
|
}
|
||||||
|
|
||||||
void stk500v2_teardown(PROGRAMMER * pgm)
|
void stk500v2_teardown(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
free(pgm->cookie);
|
free(pgm->cookie);
|
||||||
|
@ -331,6 +366,17 @@ static void stk500v2_jtagmkII_teardown(PROGRAMMER * pgm)
|
||||||
free(mycookie);
|
free(mycookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stk500v2_jtag3_teardown(PROGRAMMER * pgm)
|
||||||
|
{
|
||||||
|
void *mycookie;
|
||||||
|
|
||||||
|
mycookie = pgm->cookie;
|
||||||
|
pgm->cookie = PDATA(pgm)->chained_pdata;
|
||||||
|
jtag3_teardown(pgm);
|
||||||
|
|
||||||
|
free(mycookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned short
|
static unsigned short
|
||||||
b2_to_u16(unsigned char *b)
|
b2_to_u16(unsigned char *b)
|
||||||
|
@ -415,6 +461,31 @@ static int stk500v2_jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send the data as a JTAGICE3 encapsulated ISP packet.
|
||||||
|
*/
|
||||||
|
static int stk500v2_jtag3_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
||||||
|
{
|
||||||
|
unsigned char *cmdbuf;
|
||||||
|
int rv;
|
||||||
|
void *mycookie;
|
||||||
|
|
||||||
|
if ((cmdbuf = malloc(len + 1)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: out of memory for command packet\n",
|
||||||
|
progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
mycookie = pgm->cookie;
|
||||||
|
pgm->cookie = PDATA(pgm)->chained_pdata;
|
||||||
|
cmdbuf[0] = SCOPE_AVR_ISP;
|
||||||
|
memcpy(cmdbuf + 1, data, len);
|
||||||
|
rv = jtag3_send(pgm, cmdbuf, len + 1);
|
||||||
|
free(cmdbuf);
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
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
|
unsigned char buf[275 + 6]; // max MESSAGE_BODY of 275 bytes, 6 bytes overhead
|
||||||
|
@ -425,6 +496,8 @@ static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
||||||
return stk500v2_send_mk2(pgm, data, len);
|
return stk500v2_send_mk2(pgm, data, len);
|
||||||
else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII)
|
else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII)
|
||||||
return stk500v2_jtagmkII_send(pgm, data, len);
|
return stk500v2_jtagmkII_send(pgm, data, len);
|
||||||
|
else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3)
|
||||||
|
return stk500v2_jtag3_send(pgm, data, len);
|
||||||
|
|
||||||
buf[0] = MESSAGE_START;
|
buf[0] = MESSAGE_START;
|
||||||
buf[1] = PDATA(pgm)->command_sequence;
|
buf[1] = PDATA(pgm)->command_sequence;
|
||||||
|
@ -512,6 +585,40 @@ static int stk500v2_jtagmkII_recv(PROGRAMMER * pgm, unsigned char msg[],
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int stk500v2_jtag3_recv(PROGRAMMER * pgm, unsigned char msg[],
|
||||||
|
size_t maxsize)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
unsigned char *jtagmsg;
|
||||||
|
void *mycookie;
|
||||||
|
|
||||||
|
mycookie = pgm->cookie;
|
||||||
|
pgm->cookie = PDATA(pgm)->chained_pdata;
|
||||||
|
rv = jtag3_recv(pgm, &jtagmsg);
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
if (rv <= 0) {
|
||||||
|
fprintf(stderr, "%s: stk500v2_jtag3_recv(): error in jtagmkII_recv()\n",
|
||||||
|
progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (rv - 1 > maxsize) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500v2_jtag3_recv(): got %u bytes, have only room for %u bytes\n",
|
||||||
|
progname, (unsigned)rv - 1, (unsigned)maxsize);
|
||||||
|
rv = maxsize;
|
||||||
|
}
|
||||||
|
if (jtagmsg[0] != SCOPE_AVR_ISP) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500v2_jtag3_recv(): message is not AVR ISP: 0x%02x\n",
|
||||||
|
progname, jtagmsg[0]);
|
||||||
|
free(jtagmsg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(msg, jtagmsg + 1, rv - 1);
|
||||||
|
free(jtagmsg);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) {
|
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;
|
enum states { sINIT, sSTART, sSEQNUM, sSIZE1, sSIZE2, sTOKEN, sDATA, sCSUM, sDONE } state = sSTART;
|
||||||
unsigned int msglen = 0;
|
unsigned int msglen = 0;
|
||||||
|
@ -528,6 +635,8 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize)
|
||||||
return stk500v2_recv_mk2(pgm, msg, maxsize);
|
return stk500v2_recv_mk2(pgm, msg, maxsize);
|
||||||
else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII)
|
else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII)
|
||||||
return stk500v2_jtagmkII_recv(pgm, msg, maxsize);
|
return stk500v2_jtagmkII_recv(pgm, msg, maxsize);
|
||||||
|
else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3)
|
||||||
|
return stk500v2_jtag3_recv(pgm, msg, maxsize);
|
||||||
|
|
||||||
DEBUG("STK500V2: stk500v2_recv(): ");
|
DEBUG("STK500V2: stk500v2_recv(): ");
|
||||||
|
|
||||||
|
@ -632,7 +741,8 @@ int stk500v2_getsync(PROGRAMMER * pgm) {
|
||||||
|
|
||||||
DEBUG("STK500V2: stk500v2_getsync()\n");
|
DEBUG("STK500V2: stk500v2_getsync()\n");
|
||||||
|
|
||||||
if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII)
|
if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII ||
|
||||||
|
PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
|
@ -796,6 +906,10 @@ retry:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: stk500v2_command(): command failed\n",
|
"%s: stk500v2_command(): command failed\n",
|
||||||
progname);
|
progname);
|
||||||
|
} else if (buf[1] == STATUS_CMD_UNKNOWN) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500v2_command(): unknown command\n",
|
||||||
|
progname);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "%s: stk500v2_command(): unknown status 0x%02x\n",
|
fprintf(stderr, "%s: stk500v2_command(): unknown status 0x%02x\n",
|
||||||
progname, buf[1]);
|
progname, buf[1]);
|
||||||
|
@ -856,6 +970,17 @@ static int stk500v2_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int stk500v2_jtag3_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||||
|
unsigned char res[4])
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500v2_jtag3_cmd(): Not available in JTAGICE3\n",
|
||||||
|
progname);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* issue the 'chip erase' command to the AVR device
|
* issue the 'chip erase' command to the AVR device
|
||||||
*/
|
*/
|
||||||
|
@ -1080,7 +1205,6 @@ static int stk500hvsp_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize the AVR device and prepare it to accept commands
|
* initialize the AVR device and prepare it to accept commands
|
||||||
*/
|
*/
|
||||||
|
@ -1127,6 +1251,97 @@ static int stk500v2_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize the AVR device and prepare it to accept commands
|
||||||
|
*/
|
||||||
|
static int stk500v2_jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
|
{
|
||||||
|
unsigned char parm[4], *resp;
|
||||||
|
LNODEID ln;
|
||||||
|
AVRMEM * m;
|
||||||
|
void *mycookie;
|
||||||
|
|
||||||
|
if ((p->flags & AVRPART_HAS_PDI) ||
|
||||||
|
(p->flags & AVRPART_HAS_TPI)) {
|
||||||
|
fprintf(stderr, "%s: jtag3_initialize(): part %s has no ISP interface\n",
|
||||||
|
progname, p->desc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mycookie = pgm->cookie;
|
||||||
|
pgm->cookie = PDATA(pgm)->chained_pdata;
|
||||||
|
|
||||||
|
if (p->flags & AVRPART_HAS_DW)
|
||||||
|
parm[0] = PARM3_ARCH_TINY;
|
||||||
|
else
|
||||||
|
parm[0] = PARM3_ARCH_MEGA;
|
||||||
|
if (jtag3_setparm(pgm, SCOPE_AVR, 0, PARM3_ARCH, parm, 1) < 0) {
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
parm[0] = PARM3_SESS_PROGRAMMING;
|
||||||
|
if (jtag3_setparm(pgm, SCOPE_AVR, 0, PARM3_SESS_PURPOSE, parm, 1) < 0) {
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
parm[0] = PARM3_CONN_ISP;
|
||||||
|
if (jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CONNECTION, parm, 1) < 0) {
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
parm[0] = SCOPE_AVR_ISP;
|
||||||
|
parm[1] = 0x1e;
|
||||||
|
jtag3_send(pgm, parm, 2);
|
||||||
|
|
||||||
|
if (jtag3_recv(pgm, &resp) > 0)
|
||||||
|
free(resp);
|
||||||
|
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Examine the avrpart's memory definitions, and initialize the page
|
||||||
|
* caches. For devices/memory that are not page oriented, treat
|
||||||
|
* them as page size 1 for EEPROM, and 2 for flash.
|
||||||
|
*/
|
||||||
|
PDATA(pgm)->flash_pagesize = 2;
|
||||||
|
PDATA(pgm)->eeprom_pagesize = 1;
|
||||||
|
for (ln = lfirst(p->mem); ln; ln = lnext(ln)) {
|
||||||
|
m = ldata(ln);
|
||||||
|
if (strcmp(m->desc, "flash") == 0) {
|
||||||
|
if (m->page_size > 0) {
|
||||||
|
if (m->page_size > 256)
|
||||||
|
PDATA(pgm)->flash_pagesize = 256;
|
||||||
|
else
|
||||||
|
PDATA(pgm)->flash_pagesize = m->page_size;
|
||||||
|
}
|
||||||
|
} else if (strcmp(m->desc, "eeprom") == 0) {
|
||||||
|
if (m->page_size > 0)
|
||||||
|
PDATA(pgm)->eeprom_pagesize = m->page_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(PDATA(pgm)->flash_pagecache);
|
||||||
|
free(PDATA(pgm)->eeprom_pagecache);
|
||||||
|
if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: stk500hv_initialize(): Out of memory\n",
|
||||||
|
progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) {
|
||||||
|
fprintf(stderr, "%s: stk500hv_initialize(): Out of memory\n",
|
||||||
|
progname);
|
||||||
|
free(PDATA(pgm)->flash_pagecache);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
PDATA(pgm)->flash_pageaddr = PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
|
||||||
|
|
||||||
|
return pgm->program_enable(pgm, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize the AVR device and prepare it to accept commands, generic HV mode
|
* initialize the AVR device and prepare it to accept commands, generic HV mode
|
||||||
*/
|
*/
|
||||||
|
@ -1154,7 +1369,7 @@ static int stk500hv_initialize(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode)
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: stk500pp_initalize(): "
|
"%s: stk500hv_initalize(): "
|
||||||
"failed to set control stack\n",
|
"failed to set control stack\n",
|
||||||
progname);
|
progname);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1184,12 +1399,12 @@ static int stk500hv_initialize(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode)
|
||||||
free(PDATA(pgm)->flash_pagecache);
|
free(PDATA(pgm)->flash_pagecache);
|
||||||
free(PDATA(pgm)->eeprom_pagecache);
|
free(PDATA(pgm)->eeprom_pagecache);
|
||||||
if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) {
|
if ((PDATA(pgm)->flash_pagecache = malloc(PDATA(pgm)->flash_pagesize)) == NULL) {
|
||||||
fprintf(stderr, "%s: stk500pp_initialize(): Out of memory\n",
|
fprintf(stderr, "%s: stk500hv_initialize(): Out of memory\n",
|
||||||
progname);
|
progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) {
|
if ((PDATA(pgm)->eeprom_pagecache = malloc(PDATA(pgm)->eeprom_pagesize)) == NULL) {
|
||||||
fprintf(stderr, "%s: stk500pp_initialize(): Out of memory\n",
|
fprintf(stderr, "%s: stk500hv_initialize(): Out of memory\n",
|
||||||
progname);
|
progname);
|
||||||
free(PDATA(pgm)->flash_pagecache);
|
free(PDATA(pgm)->flash_pagecache);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1215,6 +1430,31 @@ static int stk500hvsp_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
return stk500hv_initialize(pgm, p, HVSPMODE);
|
return stk500hv_initialize(pgm, p, HVSPMODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stk500v2_jtag3_disable(PROGRAMMER * pgm)
|
||||||
|
{
|
||||||
|
unsigned char buf[16];
|
||||||
|
int result;
|
||||||
|
|
||||||
|
free(PDATA(pgm)->flash_pagecache);
|
||||||
|
PDATA(pgm)->flash_pagecache = NULL;
|
||||||
|
free(PDATA(pgm)->eeprom_pagecache);
|
||||||
|
PDATA(pgm)->eeprom_pagecache = NULL;
|
||||||
|
|
||||||
|
buf[0] = CMD_LEAVE_PROGMODE_ISP;
|
||||||
|
buf[1] = 1; // preDelay;
|
||||||
|
buf[2] = 1; // postDelay;
|
||||||
|
|
||||||
|
result = stk500v2_command(pgm, buf, 3, sizeof(buf));
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500v2_disable(): failed to leave programming mode\n",
|
||||||
|
progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static void stk500v2_disable(PROGRAMMER * pgm)
|
static void stk500v2_disable(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
unsigned char buf[16];
|
unsigned char buf[16];
|
||||||
|
@ -1577,6 +1817,112 @@ static int stk500hvsp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
return stk500hv_read_byte(pgm, p, mem, addr, value, HVSPMODE);
|
return stk500hv_read_byte(pgm, p, mem, addr, value, HVSPMODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a single byte, ISP mode
|
||||||
|
*
|
||||||
|
* By now, only used on the JTAGICE3 which does not implement the
|
||||||
|
* CMD_SPI_MULTI SPI passthrough command.
|
||||||
|
*/
|
||||||
|
static int stk500isp_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
|
unsigned long addr, unsigned char * value)
|
||||||
|
{
|
||||||
|
int result, pollidx;
|
||||||
|
unsigned char buf[6];
|
||||||
|
unsigned long paddr = 0UL, *paddr_ptr = NULL;
|
||||||
|
unsigned int pagesize = 0;
|
||||||
|
unsigned char *cache_ptr = NULL;
|
||||||
|
OPCODE *op;
|
||||||
|
|
||||||
|
if (verbose >= 2)
|
||||||
|
fprintf(stderr, "%s: stk500isp_read_byte(.., %s, 0x%lx, ...)\n",
|
||||||
|
progname, mem->desc, addr);
|
||||||
|
|
||||||
|
if (strcmp(mem->desc, "flash") == 0 ||
|
||||||
|
strcmp(mem->desc, "eeprom") == 0) {
|
||||||
|
// use paged access, and cache result
|
||||||
|
if (strcmp(mem->desc, "flash") == 0) {
|
||||||
|
pagesize = PDATA(pgm)->flash_pagesize;
|
||||||
|
paddr = addr & ~(pagesize - 1);
|
||||||
|
paddr_ptr = &PDATA(pgm)->flash_pageaddr;
|
||||||
|
cache_ptr = PDATA(pgm)->flash_pagecache;
|
||||||
|
} else {
|
||||||
|
pagesize = mem->page_size;
|
||||||
|
if (pagesize == 0)
|
||||||
|
pagesize = 1;
|
||||||
|
paddr = addr & ~(pagesize - 1);
|
||||||
|
paddr_ptr = &PDATA(pgm)->eeprom_pageaddr;
|
||||||
|
cache_ptr = PDATA(pgm)->eeprom_pagecache;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paddr == *paddr_ptr) {
|
||||||
|
*value = cache_ptr[addr & (pagesize - 1)];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stk500v2_paged_load(pgm, p, mem, pagesize, paddr, pagesize) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*paddr_ptr = paddr;
|
||||||
|
memcpy(cache_ptr, &mem->buf[paddr], pagesize);
|
||||||
|
*value = cache_ptr[addr & (pagesize - 1)];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(mem->desc, "lfuse") == 0 ||
|
||||||
|
strcmp(mem->desc, "fuse") == 0) {
|
||||||
|
buf[0] = CMD_READ_FUSE_ISP;
|
||||||
|
addr = 0;
|
||||||
|
} else if (strcmp(mem->desc, "hfuse") == 0) {
|
||||||
|
buf[0] = CMD_READ_FUSE_ISP;
|
||||||
|
addr = 1;
|
||||||
|
} else if (strcmp(mem->desc, "efuse") == 0) {
|
||||||
|
buf[0] = CMD_READ_FUSE_ISP;
|
||||||
|
addr = 2;
|
||||||
|
} else if (strcmp(mem->desc, "lock") == 0) {
|
||||||
|
buf[0] = CMD_READ_LOCK_ISP;
|
||||||
|
} else if (strcmp(mem->desc, "calibration") == 0) {
|
||||||
|
buf[0] = CMD_READ_OSCCAL_ISP;
|
||||||
|
} else if (strcmp(mem->desc, "signature") == 0) {
|
||||||
|
buf[0] = CMD_READ_SIGNATURE_ISP;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buf + 1, 0, 5);
|
||||||
|
if ((op = mem->op[AVR_OP_READ]) == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500isp_read_byte(): invalid operation AVR_OP_READ on %s memory\n",
|
||||||
|
progname, mem->desc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
avr_set_bits(op, buf + 2);
|
||||||
|
if ((pollidx = avr_get_output_index(op)) == -1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500isp_read_byte(): cannot determine pollidx to read %s memory\n",
|
||||||
|
progname, mem->desc);
|
||||||
|
pollidx = 3;
|
||||||
|
}
|
||||||
|
buf[1] = pollidx + 1;
|
||||||
|
avr_set_addr(op, buf + 2, addr);
|
||||||
|
|
||||||
|
if (verbose >= 2)
|
||||||
|
fprintf(stderr, "%s: stk500isp_read_byte(): Sending read memory command: ",
|
||||||
|
progname);
|
||||||
|
|
||||||
|
result = stk500v2_command(pgm, buf, 6, sizeof(buf));
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500isp_read_byte(): "
|
||||||
|
"timeout/error communicating with programmer\n",
|
||||||
|
progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = buf[2];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write one byte, generic HV mode
|
* Write one byte, generic HV mode
|
||||||
*/
|
*/
|
||||||
|
@ -1738,6 +2084,122 @@ static int stk500hvsp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write one byte, ISP mode
|
||||||
|
*/
|
||||||
|
static int stk500isp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
|
unsigned long addr, unsigned char data)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
unsigned char buf[5];
|
||||||
|
unsigned long paddr = 0UL, *paddr_ptr = NULL;
|
||||||
|
unsigned int pagesize = 0;
|
||||||
|
unsigned char *cache_ptr = NULL;
|
||||||
|
OPCODE *op;
|
||||||
|
|
||||||
|
if (verbose >= 2)
|
||||||
|
fprintf(stderr, "%s: stk500isp_write_byte(.., %s, 0x%lx, ...)\n",
|
||||||
|
progname, mem->desc, addr);
|
||||||
|
|
||||||
|
if (strcmp(mem->desc, "flash") == 0 ||
|
||||||
|
strcmp(mem->desc, "eeprom") == 0) {
|
||||||
|
if (strcmp(mem->desc, "flash") == 0) {
|
||||||
|
pagesize = PDATA(pgm)->flash_pagesize;
|
||||||
|
paddr = addr & ~(pagesize - 1);
|
||||||
|
paddr_ptr = &PDATA(pgm)->flash_pageaddr;
|
||||||
|
cache_ptr = PDATA(pgm)->flash_pagecache;
|
||||||
|
} else {
|
||||||
|
pagesize = mem->page_size;
|
||||||
|
if (pagesize == 0)
|
||||||
|
pagesize = 1;
|
||||||
|
paddr = addr & ~(pagesize - 1);
|
||||||
|
paddr_ptr = &PDATA(pgm)->eeprom_pageaddr;
|
||||||
|
cache_ptr = PDATA(pgm)->eeprom_pagecache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use paged writes for flash and EEPROM. As both, flash and
|
||||||
|
* EEPROM cells can only be programmed from `1' to `0' bits (even
|
||||||
|
* EEPROM does not support auto-erase in parallel mode), we just
|
||||||
|
* pre-fill the page cache with 0xff, so all those cells that are
|
||||||
|
* outside our current address will remain unaffected.
|
||||||
|
*/
|
||||||
|
memset(cache_ptr, 0xff, pagesize);
|
||||||
|
cache_ptr[addr & (pagesize - 1)] = data;
|
||||||
|
|
||||||
|
memcpy(mem->buf + paddr, cache_ptr, pagesize);
|
||||||
|
stk500v2_paged_write(pgm, p, mem, pagesize, addr, pagesize);
|
||||||
|
|
||||||
|
/* Invalidate the page cache. */
|
||||||
|
*paddr_ptr = (unsigned long)-1L;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof buf);
|
||||||
|
if (strcmp(mem->desc, "lfuse") == 0 ||
|
||||||
|
strcmp(mem->desc, "fuse") == 0) {
|
||||||
|
buf[0] = CMD_PROGRAM_FUSE_ISP;
|
||||||
|
addr = 0;
|
||||||
|
} else if (strcmp(mem->desc, "hfuse") == 0) {
|
||||||
|
buf[0] = CMD_PROGRAM_FUSE_ISP;
|
||||||
|
addr = 1;
|
||||||
|
} else if (strcmp(mem->desc, "efuse") == 0) {
|
||||||
|
buf[0] = CMD_PROGRAM_FUSE_ISP;
|
||||||
|
addr = 2;
|
||||||
|
} else if (strcmp(mem->desc, "lock") == 0) {
|
||||||
|
buf[0] = CMD_PROGRAM_LOCK_ISP;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500isp_write_byte(): "
|
||||||
|
"unsupported memory type: %s\n",
|
||||||
|
progname, mem->desc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((op = mem->op[AVR_OP_WRITE]) == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500isp_write_byte(): "
|
||||||
|
"no AVR_OP_WRITE for %s memory\n",
|
||||||
|
progname, mem->desc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
avr_set_bits(op, buf + 1);
|
||||||
|
avr_set_addr(op, buf + 1, addr);
|
||||||
|
avr_set_input(op, buf + 1, data);
|
||||||
|
|
||||||
|
if (verbose >= 2)
|
||||||
|
fprintf(stderr, "%s: stk500isp_write_byte(): Sending write memory command: ",
|
||||||
|
progname);
|
||||||
|
|
||||||
|
result = stk500v2_command(pgm, buf, 5, sizeof(buf));
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: stk500isp_write_byte(): "
|
||||||
|
"timeout/error communicating with programmer\n",
|
||||||
|
progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf[0] == CMD_PROGRAM_FUSE_ISP) {
|
||||||
|
/*
|
||||||
|
* The JTAGICE3 needs one leave progmode / enter progmode cycle
|
||||||
|
* after writing fuses, before being able to read them back.
|
||||||
|
*/
|
||||||
|
buf[0] = CMD_LEAVE_PROGMODE_ISP;
|
||||||
|
buf[1] = 1; // preDelay;
|
||||||
|
buf[2] = 1; // postDelay;
|
||||||
|
|
||||||
|
stk500v2_command(pgm, buf, 3, sizeof(buf));
|
||||||
|
|
||||||
|
pgm->program_enable(pgm, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
|
@ -2495,6 +2957,28 @@ static int stk600_set_sck_period(PROGRAMMER * pgm, double v)
|
||||||
return stk500v2_setparm2(pgm, PARAM2_SCK_DURATION, sck);
|
return stk500v2_setparm2(pgm, PARAM2_SCK_DURATION, sck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int stk500v2_jtag3_set_sck_period(PROGRAMMER * pgm, double v)
|
||||||
|
{
|
||||||
|
unsigned char value[3];
|
||||||
|
unsigned int sck;
|
||||||
|
|
||||||
|
if (v < 1E-6)
|
||||||
|
sck = 0x400;
|
||||||
|
else if (v > 1E-3)
|
||||||
|
sck = 1;
|
||||||
|
else
|
||||||
|
sck = 1.0 / (1000.0 * v);
|
||||||
|
|
||||||
|
value[0] = CMD_SET_SCK;
|
||||||
|
value[1] = sck & 0xff;
|
||||||
|
value[2] = (sck >> 8) & 0xff;
|
||||||
|
|
||||||
|
if (stk500v2_jtag3_send(pgm, value, 3) < 0)
|
||||||
|
return -1;
|
||||||
|
if (stk500v2_jtag3_recv(pgm, value, 3) < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value)
|
static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value)
|
||||||
{
|
{
|
||||||
|
@ -2616,7 +3100,8 @@ static void stk500v2_display(PROGRAMMER * pgm, const char * p)
|
||||||
case PGMTYPE_STK600: pgmname = "STK600"; break;
|
case PGMTYPE_STK600: pgmname = "STK600"; break;
|
||||||
default: pgmname = "None";
|
default: pgmname = "None";
|
||||||
}
|
}
|
||||||
if (PDATA(pgm)->pgmtype != PGMTYPE_JTAGICE_MKII) {
|
if (PDATA(pgm)->pgmtype != PGMTYPE_JTAGICE_MKII &&
|
||||||
|
PDATA(pgm)->pgmtype != PGMTYPE_JTAGICE3) {
|
||||||
fprintf(stderr, "%sProgrammer Model: %s\n", p, pgmname);
|
fprintf(stderr, "%sProgrammer Model: %s\n", p, pgmname);
|
||||||
stk500v2_getparm(pgm, PARAM_HW_VER, &hdw);
|
stk500v2_getparm(pgm, PARAM_HW_VER, &hdw);
|
||||||
stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
|
stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
|
||||||
|
@ -2698,6 +3183,14 @@ static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p)
|
||||||
pgm->cookie = mycookie;
|
pgm->cookie = mycookie;
|
||||||
fprintf(stderr, "%sVtarget : %.1f V\n", p,
|
fprintf(stderr, "%sVtarget : %.1f V\n", p,
|
||||||
b2_to_u16(vtarget_jtag) / 1000.0);
|
b2_to_u16(vtarget_jtag) / 1000.0);
|
||||||
|
} else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE3) {
|
||||||
|
mycookie = pgm->cookie;
|
||||||
|
pgm->cookie = PDATA(pgm)->chained_pdata;
|
||||||
|
jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, vtarget_jtag, 2);
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
fprintf(stderr, "%sVtarget : %.1f V\n", p,
|
||||||
|
b2_to_u16(vtarget_jtag) / 1000.0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
|
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
|
||||||
fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
||||||
|
@ -2741,6 +3234,20 @@ static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p)
|
||||||
(float) 1000000 / avrispmkIIfreqs[sck_duration]);
|
(float) 1000000 / avrispmkIIfreqs[sck_duration]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PGMTYPE_JTAGICE3:
|
||||||
|
{
|
||||||
|
unsigned char cmd[4];
|
||||||
|
|
||||||
|
cmd[0] = CMD_GET_SCK;
|
||||||
|
if (stk500v2_jtag3_send(pgm, cmd, 1) >= 0 &&
|
||||||
|
stk500v2_jtag3_recv(pgm, cmd, 4) >= 2) {
|
||||||
|
unsigned int sck = cmd[1] | (cmd[2] << 8);
|
||||||
|
fprintf(stderr, "%sSCK period : %.2f us\n", p,
|
||||||
|
(float)(1E6 / (1000.0 * sck)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case PGMTYPE_STK600:
|
case PGMTYPE_STK600:
|
||||||
stk500v2_getparm2(pgm, PARAM2_AREF0, &varef);
|
stk500v2_getparm2(pgm, PARAM2_AREF0, &varef);
|
||||||
fprintf(stderr, "%sVaref 0 : %.2f V\n", p, varef / 100.0);
|
fprintf(stderr, "%sVaref 0 : %.2f V\n", p, varef / 100.0);
|
||||||
|
@ -2887,6 +3394,23 @@ static void stk500v2_jtagmkII_close(PROGRAMMER * pgm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Close JTAGICE3.
|
||||||
|
*/
|
||||||
|
static void stk500v2_jtag3_close(PROGRAMMER * pgm)
|
||||||
|
{
|
||||||
|
void *mycookie;
|
||||||
|
|
||||||
|
if (verbose >= 2)
|
||||||
|
fprintf(stderr, "%s: stk500v2_jtag3_close()\n", progname);
|
||||||
|
|
||||||
|
mycookie = pgm->cookie;
|
||||||
|
pgm->cookie = PDATA(pgm)->chained_pdata;
|
||||||
|
jtag3_close(pgm);
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper functions for the AVR Dragon in ISP mode. This mode
|
* Wrapper functions for the AVR Dragon in ISP mode. This mode
|
||||||
* uses the normal JTAG ICE mkII packet stream to communicate with the
|
* uses the normal JTAG ICE mkII packet stream to communicate with the
|
||||||
|
@ -3040,6 +3564,77 @@ static int stk500v2_dragon_hv_open(PROGRAMMER * pgm, char * port)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper functions for the JTAGICE3 in ISP mode. This mode
|
||||||
|
* uses the normal JTAGICE3 packet stream to communicate with the
|
||||||
|
* ICE, but then encapsulates AVRISP mkII commands using
|
||||||
|
* scope AVRISP.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open a JTAGICE3 in ISP mode.
|
||||||
|
*/
|
||||||
|
static int stk500v2_jtag3_open(PROGRAMMER * pgm, char * port)
|
||||||
|
{
|
||||||
|
long baud;
|
||||||
|
void *mycookie;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (verbose >= 2)
|
||||||
|
fprintf(stderr, "%s: stk500v2_jtag3_open()\n", progname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_JTAGICE3;
|
||||||
|
pgm->fd.usb.max_xfer = USBDEV_MAX_XFER_3;
|
||||||
|
pgm->fd.usb.rep = USBDEV_BULK_EP_READ_3;
|
||||||
|
pgm->fd.usb.wep = USBDEV_BULK_EP_WRITE_3;
|
||||||
|
pgm->fd.usb.eep = USBDEV_EVT_EP_READ_3;
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "avrdude was compiled without usb support.\n");
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(pgm->port, port);
|
||||||
|
if (serial_open(port, baud, &pgm->fd)==-1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* drain any extraneous input
|
||||||
|
*/
|
||||||
|
stk500v2_drain(pgm, 0);
|
||||||
|
|
||||||
|
mycookie = pgm->cookie;
|
||||||
|
pgm->cookie = PDATA(pgm)->chained_pdata;
|
||||||
|
if ((rv = jtag3_getsync(pgm, 42)) != 0) {
|
||||||
|
if (rv != JTAGII_GETSYNC_FAIL_GRACEFUL)
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: failed to sync with the JTAGICE3 in ISP mode\n",
|
||||||
|
progname);
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pgm->cookie = mycookie;
|
||||||
|
|
||||||
|
PDATA(pgm)->pgmtype = PGMTYPE_JTAGICE3;
|
||||||
|
|
||||||
|
if (pgm->bitclock != 0.0) {
|
||||||
|
if (pgm->set_sck_period(pgm, pgm->bitclock) != 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XPROG wrapper
|
* XPROG wrapper
|
||||||
*/
|
*/
|
||||||
|
@ -4080,3 +4675,38 @@ void stk600hvsp_initpgm(PROGRAMMER * pgm)
|
||||||
pgm->page_size = 256;
|
pgm->page_size = 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char stk500v2_jtag3_desc[] = "Atmel JTAGICE3 in ISP mode";
|
||||||
|
|
||||||
|
void stk500v2_jtag3_initpgm(PROGRAMMER * pgm)
|
||||||
|
{
|
||||||
|
strcpy(pgm->type, "JTAG3_ISP");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mandatory functions
|
||||||
|
*/
|
||||||
|
pgm->initialize = stk500v2_jtag3_initialize;
|
||||||
|
pgm->display = stk500v2_display;
|
||||||
|
pgm->enable = stk500v2_enable;
|
||||||
|
pgm->disable = stk500v2_jtag3_disable;
|
||||||
|
pgm->program_enable = stk500v2_program_enable;
|
||||||
|
pgm->chip_erase = stk500v2_chip_erase;
|
||||||
|
pgm->cmd = stk500v2_jtag3_cmd;
|
||||||
|
pgm->open = stk500v2_jtag3_open;
|
||||||
|
pgm->close = stk500v2_jtag3_close;
|
||||||
|
pgm->read_byte = stk500isp_read_byte;
|
||||||
|
pgm->write_byte = stk500isp_write_byte;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* optional functions
|
||||||
|
*/
|
||||||
|
pgm->paged_write = stk500v2_paged_write;
|
||||||
|
pgm->paged_load = stk500v2_paged_load;
|
||||||
|
pgm->page_erase = stk500v2_page_erase;
|
||||||
|
pgm->print_parms = stk500v2_print_parms;
|
||||||
|
pgm->set_sck_period = stk500v2_jtag3_set_sck_period;
|
||||||
|
pgm->perform_osccal = stk500v2_perform_osccal;
|
||||||
|
pgm->setup = stk500v2_jtag3_setup;
|
||||||
|
pgm->teardown = stk500v2_jtag3_teardown;
|
||||||
|
pgm->page_size = 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ extern const char stk500v2_jtagmkII_desc[];
|
||||||
extern const char stk500v2_dragon_hvsp_desc[];
|
extern const char stk500v2_dragon_hvsp_desc[];
|
||||||
extern const char stk500v2_dragon_isp_desc[];
|
extern const char stk500v2_dragon_isp_desc[];
|
||||||
extern const char stk500v2_dragon_pp_desc[];
|
extern const char stk500v2_dragon_pp_desc[];
|
||||||
|
extern const char stk500v2_jtag3_desc[];
|
||||||
extern const char stk600_desc[];
|
extern const char stk600_desc[];
|
||||||
extern const char stk600hvsp_desc[];
|
extern const char stk600hvsp_desc[];
|
||||||
extern const char stk600pp_desc[];
|
extern const char stk600pp_desc[];
|
||||||
|
@ -40,6 +41,7 @@ void stk500v2_initpgm (PROGRAMMER * pgm);
|
||||||
void stk500hvsp_initpgm (PROGRAMMER * pgm);
|
void stk500hvsp_initpgm (PROGRAMMER * pgm);
|
||||||
void stk500pp_initpgm (PROGRAMMER * pgm);
|
void stk500pp_initpgm (PROGRAMMER * pgm);
|
||||||
void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm);
|
void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm);
|
||||||
|
void stk500v2_jtag3_initpgm(PROGRAMMER * pgm);
|
||||||
void stk500v2_dragon_hvsp_initpgm(PROGRAMMER * pgm);
|
void stk500v2_dragon_hvsp_initpgm(PROGRAMMER * pgm);
|
||||||
void stk500v2_dragon_isp_initpgm(PROGRAMMER * pgm);
|
void stk500v2_dragon_isp_initpgm(PROGRAMMER * pgm);
|
||||||
void stk500v2_dragon_pp_initpgm(PROGRAMMER * pgm);
|
void stk500v2_dragon_pp_initpgm(PROGRAMMER * pgm);
|
||||||
|
|
|
@ -45,7 +45,10 @@
|
||||||
#define CMD_READ_LOCK_ISP 0x1A
|
#define CMD_READ_LOCK_ISP 0x1A
|
||||||
#define CMD_READ_SIGNATURE_ISP 0x1B
|
#define CMD_READ_SIGNATURE_ISP 0x1B
|
||||||
#define CMD_READ_OSCCAL_ISP 0x1C
|
#define CMD_READ_OSCCAL_ISP 0x1C
|
||||||
#define CMD_SPI_MULTI 0x1D
|
#define CMD_SPI_MULTI 0x1D /* STK500v2, AVRISPmkII,
|
||||||
|
* JTAGICEmkII */
|
||||||
|
#define CMD_SET_SCK 0x1D /* JTAGICE3 */
|
||||||
|
#define CMD_GET_SCK 0x1E /* JTAGICE3 */
|
||||||
|
|
||||||
// *****************[ STK PP command constants ]*******************************
|
// *****************[ STK PP command constants ]*******************************
|
||||||
|
|
||||||
|
@ -307,6 +310,7 @@ struct pdata
|
||||||
PGMTYPE_AVRISP_MKII,
|
PGMTYPE_AVRISP_MKII,
|
||||||
PGMTYPE_JTAGICE_MKII,
|
PGMTYPE_JTAGICE_MKII,
|
||||||
PGMTYPE_STK600,
|
PGMTYPE_STK600,
|
||||||
|
PGMTYPE_JTAGICE3
|
||||||
}
|
}
|
||||||
pgmtype;
|
pgmtype;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue