* 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:
Joerg Wunsch 2012-12-03 15:52:38 +00:00
parent 1acbb2fb64
commit 2c540d02b6
12 changed files with 707 additions and 22 deletions

View File

@ -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>
* jtag3.c (jtag3_read_byte, jtag3_write_byte): Remove the

2
NEWS
View File

@ -35,7 +35,7 @@ Current:
X3(1), sck = DSR X3(2), mosi = DCD X3(3), reset = RI X3(4))
+ diecimila (alias for arduino-ft232r)
- Atmel JTAGICE3 (megaAVR/JTAG, Xmega/JTAG/PDI only so far)
- Atmel JTAGICE3
* Bugfixes
- bug #34027: avrdude AT90S1200 Problem

View File

@ -18,7 +18,7 @@
.\"
.\" $Id$
.\"
.Dd DATE February 2, 2012
.Dd DATE December 3, 2012
.Os
.Dt AVRDUDE 1
.Sh NAME
@ -59,7 +59,7 @@ microcontrollers.
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),
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),
as well as a simple hard-wired
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
supported on a serial port.
.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).
For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported, provided
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.
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).
For ATxmega devices, the JTAGICE3 is supported in PDI mode.
.Pp
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
@ -432,7 +434,7 @@ language notation (i. e., hexadecimal values are prefixed by
.Ql 0x
).
.Pp
For the JTAG ICE mkII, if
For the JTAG ICE mkII and JTAGICE3, if
.Nm
has been configured with libusb support,
.Ar port
@ -440,7 +442,7 @@ can alternatively be specified as
.Pa usb Ns Op \&: Ns Ar serialno .
This will cause
.Nm
to search a JTAG ICE mkII on USB.
to search the programmer on USB.
If
.Ar serialno
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
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
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.
.It Ar parms
.Em STK500 and STK600 programmer only:
@ -829,8 +831,9 @@ entered.
.Ss Programmers accepting extended parameters
.Bl -tag -offset indent -width indent
.It Ar JTAG ICE mkII
.It Ar JTAGICE3
.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:
.Bl -tag -offset indent -width indent
.It Ar jtagchain=UB,UA,BB,BA

View File

@ -912,6 +912,13 @@ programmer
connection_type = usb;
;
programmer
id = "jtag3isp";
desc = "Atmel AVR JTAGICE3 in ISP mode";
type = "jtagice3_isp";
connection_type = usb;
;
programmer
id = "pavr";

View File

@ -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)
{
switch (op) {

View File

@ -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_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_index(OPCODE * op);
/* Functions for AVRMEM structures */
AVRMEM * avr_new_memtype(void);

11
jtag3.c
View File

@ -106,9 +106,6 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char data);
static int jtag3_reset(PROGRAMMER * pgm, unsigned char flags);
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 int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size,
@ -1554,7 +1551,7 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
return 0;
} else {
/* 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;
}
}
@ -1773,9 +1770,9 @@ int jtag3_getparm(PROGRAMMER * pgm, unsigned char scope,
/*
* Write an emulator parameter.
*/
static int jtag3_setparm(PROGRAMMER * pgm, unsigned char scope,
unsigned char section, unsigned char parm,
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)
{
int status;
unsigned char *buf, *resp;

View File

@ -32,6 +32,9 @@ int jtag3_getsync(PROGRAMMER * pgm, int mode);
int jtag3_getparm(PROGRAMMER * pgm, unsigned char scope,
unsigned char section, unsigned char parm,
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_dw_desc[];
extern const char jtag3_pdi_desc[];

View File

@ -73,6 +73,7 @@ const PROGRAMMER_TYPE const programmers_types[] = {
{"jtagice3", jtag3_initpgm, jtag3_desc},
{"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc},
{"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc},
{"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc},
{"par", par_initpgm, par_desc},
{"pickit2", pickit2_initpgm, pickit2_desc},
{"serbb", serbb_initpgm, serbb_desc},

View File

@ -67,6 +67,10 @@
#define JTAGMKII_PRIVATE_EXPORTED
#include "jtagmkII_private.h"
#include "jtag3.h" // public interfaces from jtagmkII.c
#define JTAG3_PRIVATE_EXPORTED
#include "jtag3_private.h"
#define STK500V2_XTAL 7372800U
// Timeout (in seconds) for waiting for serial response
@ -113,6 +117,7 @@ static const char *pgmname[] =
"AVRISP mkII",
"JTAG ICE mkII",
"STK600",
"JTAGICE3",
};
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_setparm_real(PROGRAMMER * pgm, unsigned char parm, unsigned char value);
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);
@ -315,6 +326,30 @@ static void stk500v2_jtagmkII_setup(PROGRAMMER * pgm)
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)
{
free(pgm->cookie);
@ -331,6 +366,17 @@ static void stk500v2_jtagmkII_teardown(PROGRAMMER * pgm)
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
b2_to_u16(unsigned char *b)
@ -415,6 +461,31 @@ static int stk500v2_jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t
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)
{
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);
else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII)
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[1] = PDATA(pgm)->command_sequence;
@ -512,6 +585,40 @@ static int stk500v2_jtagmkII_recv(PROGRAMMER * pgm, unsigned char msg[],
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) {
enum states { sINIT, sSTART, sSEQNUM, sSIZE1, sSIZE2, sTOKEN, sDATA, sCSUM, sDONE } state = sSTART;
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);
else if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII)
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(): ");
@ -632,7 +741,8 @@ int stk500v2_getsync(PROGRAMMER * pgm) {
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;
retry:
@ -796,6 +906,10 @@ retry:
fprintf(stderr,
"%s: stk500v2_command(): command failed\n",
progname);
} else if (buf[1] == STATUS_CMD_UNKNOWN) {
fprintf(stderr,
"%s: stk500v2_command(): unknown command\n",
progname);
} else {
fprintf(stderr, "%s: stk500v2_command(): unknown status 0x%02x\n",
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
*/
@ -1080,7 +1205,6 @@ static int stk500hvsp_program_enable(PROGRAMMER * pgm, AVRPART * p)
}
/*
* 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
*/
@ -1154,7 +1369,7 @@ static int stk500hv_initialize(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode)
if (result < 0) {
fprintf(stderr,
"%s: stk500pp_initalize(): "
"%s: stk500hv_initalize(): "
"failed to set control stack\n",
progname);
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)->eeprom_pagecache);
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);
return -1;
}
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);
free(PDATA(pgm)->flash_pagecache);
return -1;
@ -1215,6 +1430,31 @@ static int stk500hvsp_initialize(PROGRAMMER * pgm, AVRPART * p)
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)
{
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);
}
/*
* 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
*/
@ -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,
unsigned int page_size,
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);
}
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)
{
@ -2616,7 +3100,8 @@ static void stk500v2_display(PROGRAMMER * pgm, const char * p)
case PGMTYPE_STK600: pgmname = "STK600"; break;
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);
stk500v2_getparm(pgm, PARAM_HW_VER, &hdw);
stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
@ -2698,6 +3183,14 @@ static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p)
pgm->cookie = mycookie;
fprintf(stderr, "%sVtarget : %.1f V\n", p,
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 {
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
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]);
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:
stk500v2_getparm2(pgm, PARAM2_AREF0, &varef);
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
* 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;
}
/*
* 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
*/
@ -4080,3 +4675,38 @@ void stk600hvsp_initpgm(PROGRAMMER * pgm)
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;
}

View File

@ -33,6 +33,7 @@ extern const char stk500v2_jtagmkII_desc[];
extern const char stk500v2_dragon_hvsp_desc[];
extern const char stk500v2_dragon_isp_desc[];
extern const char stk500v2_dragon_pp_desc[];
extern const char stk500v2_jtag3_desc[];
extern const char stk600_desc[];
extern const char stk600hvsp_desc[];
extern const char stk600pp_desc[];
@ -40,6 +41,7 @@ void stk500v2_initpgm (PROGRAMMER * pgm);
void stk500hvsp_initpgm (PROGRAMMER * pgm);
void stk500pp_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_isp_initpgm(PROGRAMMER * pgm);
void stk500v2_dragon_pp_initpgm(PROGRAMMER * pgm);

View File

@ -45,7 +45,10 @@
#define CMD_READ_LOCK_ISP 0x1A
#define CMD_READ_SIGNATURE_ISP 0x1B
#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 ]*******************************
@ -307,6 +310,7 @@ struct pdata
PGMTYPE_AVRISP_MKII,
PGMTYPE_JTAGICE_MKII,
PGMTYPE_STK600,
PGMTYPE_JTAGICE3
}
pgmtype;