Implement debugWire programming support. Several limitations are

imposed by debugWire itself, so effectively, only flash ROM can be
read and written.

Currently, the required changes to avrdude.conf.in are only present
for the ATtiny44.


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@688 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
joerg_wunsch 2006-11-20 23:23:37 +00:00
parent 46e0286657
commit 8ed8377442
9 changed files with 477 additions and 48 deletions

View File

@ -1,3 +1,15 @@
2006-11-21 Joerg Wunsch <j@uriah.heep.sax.de>
Implement debugWire programming support.
* avrpart.h: Implement debugWire support.
* config_gram.y: (Ditto.)
* jtagmkII.c: (Ditto.)
* jtagmkII.h: (Ditto.)
* lexer.l: (Ditto.)
* avrdude.conf.in: Add the new dW programmers.
* avrdude.1: Document the dW support.
* doc/avrdude.texi: (Ditto.)
2006-11-20 Joerg Wunsch <j@uriah.heep.sax.de> 2006-11-20 Joerg Wunsch <j@uriah.heep.sax.de>
* jtagmkI.c (jtagmkI_close): remove two unused variables. * jtagmkI.c (jtagmkI_close): remove two unused variables.

View File

@ -112,10 +112,11 @@ 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 (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). areas from/to an AVR target (no support for on-chip debugging).
For the JTAG ICE mkII, both JTAG and ISP mode are supported. For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported.
See below for the limitations of debugWire.
.Pp .Pp
The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP). The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP, debugWire).
When used in JTAG mode, the AVR Dragon behaves similar to a When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a
JTAG ICE mkII, so all device-specific comments for that device JTAG ICE mkII, so all device-specific comments for that device
will apply as well. will apply as well.
When used in ISP mode, the AVR Dragon behaves similar to an When used in ISP mode, the AVR Dragon behaves similar to an
@ -710,6 +711,33 @@ ll.
10 MISO (from MCU) 10 MISO (from MCU)
18-25 GND 18-25 GND
.TE .TE
.Ss debugWire limitations
The debugWire protocol is Atmel's proprietary one-wire (plus ground)
protocol to allow an in-circuit emulation of the smaller AVR devices,
using the
.Ql /RESET
line.
DebugWire mode is initiated by activating the
.Ql DWEN
fuse, and then power-cycling the target.
While this mode is mainly intented for debugging/emulation, it
also offers limited programming capabilities.
Effectively, the only memory area that can be read or programmed
in this mode is the flash ROM.
It is also possible to read out the signature.
All other memory areas cannot be accessed.
There is no
.Em chip erase
functionality in debugWire mode; instead, while reprogramming the
flash ROM, each flash ROM page is erased right before updating it.
This is done transparently by the JTAG ICE mkII (or AVR Dragon).
The only way back from debugWire mode is to initiate a special
sequence of commands to the JTAG ICE mkII (or AVR Dragon), so the
debugWire mode will be temporarily disabled, and the target can
be accessed using normal ISP programming.
This sequence is automatically initiated by using the JTAG ICE mkII
or AVR Dragon in ISP mode, when they detect that ISP mode cannot be
entered.
.Sh FILES .Sh FILES
.Bl -tag -offset indent -width /dev/ppi0XXX .Bl -tag -offset indent -width /dev/ppi0XXX
.It Pa /dev/ppi0 .It Pa /dev/ppi0

View File

@ -17,8 +17,8 @@
# desc = <description> ; # quoted string # desc = <description> ; # quoted string
# type = par | stk500 | stk500v2 | stk500pp | stk500hvsp | stk500generic | # type = par | stk500 | stk500v2 | stk500pp | stk500hvsp | stk500generic |
# avr910 | butterfly | usbasp | # avr910 | butterfly | usbasp |
# jtagmki | jtagmkii | jtagmkii_isp | # jtagmki | jtagmkii | jtagmkii_isp | jtagmkii_dw |
# dragon_jtag | dragon_isp | dragon_pp | # dragon_dw | dragon_jtag | dragon_isp | dragon_pp |
# dragon_hvsp; # programmer type # dragon_hvsp; # programmer type
# baudrate = <num> ; # baudrate for avr910-programmer # baudrate = <num> ; # baudrate for avr910-programmer
# vcc = <num1> [, <num2> ... ] ; # pin number(s) # vcc = <num1> [, <num2> ... ] ; # pin number(s)
@ -36,6 +36,7 @@
# id = <id> ; # quoted string # id = <id> ; # quoted string
# desc = <description> ; # quoted string # desc = <description> ; # quoted string
# has_jtag = <yes/no> ; # part has JTAG i/f # has_jtag = <yes/no> ; # part has JTAG i/f
# has_debugwire = <yes/no> ; # part has debugWire i/f
# devicecode = <num> ; # deprecated, use stk500_devcode # devicecode = <num> ; # deprecated, use stk500_devcode
# stk500_devcode = <num> ; # numeric # stk500_devcode = <num> ; # numeric
# avr910_devcode = <num> ; # numeric # avr910_devcode = <num> ; # numeric
@ -443,6 +444,14 @@ programmer
type = jtagmkii_isp; type = jtagmkii_isp;
; ;
# JTAG ICE mkII in debugWire mode
programmer
id = "jtag2dw";
desc = "Atmel JTAG ICE mkII in debugWire mode";
baudrate = 115200;
type = jtagmkii_dw;
;
# AVR Dragon in JTAG mode # AVR Dragon in JTAG mode
programmer programmer
id = "dragon_jtag"; id = "dragon_jtag";
@ -475,6 +484,14 @@ programmer
type = dragon_hvsp; type = dragon_hvsp;
; ;
# AVR Dragon in debugWire mode
programmer
id = "dragon_dw";
desc = "Atmel AVR Dragon in debugWire mode";
baudrate = 115200;
type = dragon_dw;
;
programmer programmer
id = "pavr"; id = "pavr";
desc = "Jason Kyle's pAVR Serial Programmer"; desc = "Jason Kyle's pAVR Serial Programmer";
@ -9182,6 +9199,7 @@ part
part part
id = "t44"; id = "t44";
desc = "ATtiny44"; desc = "ATtiny44";
has_debugwire = yes;
## no STK500 devcode in XML file, use the ATtiny45 one ## no STK500 devcode in XML file, use the ATtiny45 one
stk500_devcode = 0x14; stk500_devcode = 0x14;
## avr910_devcode = ?; ## avr910_devcode = ?;
@ -9228,6 +9246,8 @@ part
programfusepolltimeout = 25; programfusepolltimeout = 25;
programlockpolltimeout = 25; programlockpolltimeout = 25;
flash_instr = 0xb4, 0x07, 0x17;
memory "eeprom" memory "eeprom"
size = 256; size = 256;
paged = no; paged = no;

View File

@ -89,10 +89,12 @@ typedef struct opcode {
#define AVRPART_HAS_JTAG 0x0008 /* part has a JTAG i/f */ #define AVRPART_HAS_JTAG 0x0008 /* part has a JTAG i/f */
#define AVRPART_ALLOWFULLPAGEBITSTREAM 0x0010 /* JTAG ICE mkII param. */ #define AVRPART_ALLOWFULLPAGEBITSTREAM 0x0010 /* JTAG ICE mkII param. */
#define AVRPART_ENABLEPAGEPROGRAMMING 0x0020 /* JTAG ICE mkII param. */ #define AVRPART_ENABLEPAGEPROGRAMMING 0x0020 /* JTAG ICE mkII param. */
#define AVRPART_HAS_DW 0x0040 /* part has a debugWire i/f */
#define AVR_DESCLEN 64 #define AVR_DESCLEN 64
#define AVR_IDLEN 32 #define AVR_IDLEN 32
#define CTL_STACK_SIZE 32 #define CTL_STACK_SIZE 32
#define FLASH_INSTR_SIZE 3
typedef struct avrpart { typedef struct avrpart {
char desc[AVR_DESCLEN]; /* long part name */ char desc[AVR_DESCLEN]; /* long part name */
char id[AVR_IDLEN]; /* short part name */ char id[AVR_IDLEN]; /* short part name */
@ -120,6 +122,7 @@ typedef struct avrpart {
enum ctl_stack_t ctl_stack_type; /* what to use the ctl stack for */ enum ctl_stack_t ctl_stack_type; /* what to use the ctl stack for */
unsigned char controlstack[CTL_STACK_SIZE]; /* stk500v2 PP/HVSP ctl stack */ unsigned char controlstack[CTL_STACK_SIZE]; /* stk500v2 PP/HVSP ctl stack */
unsigned char flash_instr[FLASH_INSTR_SIZE]; /* flash instructions (debugWire, JTAG) */
int hventerstabdelay; /* stk500 v2 hv mode parameter */ int hventerstabdelay; /* stk500 v2 hv mode parameter */
int progmodedelay; /* stk500 v2 hv mode parameter */ int progmodedelay; /* stk500 v2 hv mode parameter */

View File

@ -88,6 +88,7 @@ static int parse_cmdbits(OPCODE * op);
%token K_DEFAULT_SERIAL %token K_DEFAULT_SERIAL
%token K_DESC %token K_DESC
%token K_DEVICECODE %token K_DEVICECODE
%token K_DRAGON_DW
%token K_DRAGON_HVSP %token K_DRAGON_HVSP
%token K_DRAGON_ISP %token K_DRAGON_ISP
%token K_DRAGON_JTAG %token K_DRAGON_JTAG
@ -101,6 +102,7 @@ static int parse_cmdbits(OPCODE * op);
%token K_IO %token K_IO
%token K_JTAG_MKI %token K_JTAG_MKI
%token K_JTAG_MKII %token K_JTAG_MKII
%token K_JTAG_MKII_DW
%token K_JTAG_MKII_ISP %token K_JTAG_MKII_ISP
%token K_LOADPAGE %token K_LOADPAGE
%token K_MAX_WRITE_DELAY %token K_MAX_WRITE_DELAY
@ -194,10 +196,12 @@ static int parse_cmdbits(OPCODE * op);
*/ */
%token K_ENABLEPAGEPROGRAMMING /* ? yes for mega256*, mega406 */ %token K_ENABLEPAGEPROGRAMMING /* ? yes for mega256*, mega406 */
%token K_HAS_JTAG /* MCU has JTAG i/f. */ %token K_HAS_JTAG /* MCU has JTAG i/f. */
%token K_HAS_DW /* MCU has debugWire i/f. */
%token K_IDR /* address of OCD register in IO space */ %token K_IDR /* address of OCD register in IO space */
%token K_RAMPZ /* address of RAMPZ reg. in IO space */ %token K_RAMPZ /* address of RAMPZ reg. in IO space */
%token K_SPMCR /* address of SPMC[S]R in memory space */ %token K_SPMCR /* address of SPMC[S]R in memory space */
%token K_EECR /* address of EECR in memory space */ %token K_EECR /* address of EECR in memory space */
%token K_FLASH_INSTR /* flash instructions */
%token TKN_COMMA %token TKN_COMMA
%token TKN_EQUAL %token TKN_EQUAL
@ -435,12 +439,24 @@ prog_parm :
} }
} | } |
K_TYPE TKN_EQUAL K_JTAG_MKII_DW {
{
jtagmkII_dw_initpgm(current_prog);
}
} |
K_TYPE TKN_EQUAL K_JTAG_MKII_ISP { K_TYPE TKN_EQUAL K_JTAG_MKII_ISP {
{ {
stk500v2_jtagmkII_initpgm(current_prog); stk500v2_jtagmkII_initpgm(current_prog);
} }
} | } |
K_TYPE TKN_EQUAL K_DRAGON_DW {
{
jtagmkII_dragon_dw_initpgm(current_prog);
}
} |
K_TYPE TKN_EQUAL K_DRAGON_HVSP { K_TYPE TKN_EQUAL K_DRAGON_HVSP {
{ {
stk500v2_dragon_hvsp_initpgm(current_prog); stk500v2_dragon_hvsp_initpgm(current_prog);
@ -703,6 +719,38 @@ part_parm :
} }
} | } |
K_FLASH_INSTR TKN_EQUAL num_list {
{
TOKEN * t;
unsigned nbytes;
int ok;
nbytes = 0;
ok = 1;
while (lsize(number_list)) {
t = lrmv_n(number_list, 1);
if (nbytes < FLASH_INSTR_SIZE)
{
current_part->flash_instr[nbytes] = t->value.number;
nbytes++;
}
else
{
ok = 0;
}
free_token(t);
}
if (!ok)
{
fprintf(stderr,
"%s: Warning: line %d of %s: "
"too many bytes in flash instructions\n",
progname, lineno, infile);
}
}
} |
K_CHIP_ERASE_DELAY TKN_EQUAL TKN_NUMBER K_CHIP_ERASE_DELAY TKN_EQUAL TKN_NUMBER
{ {
current_part->chip_erase_delay = $3->value.number; current_part->chip_erase_delay = $3->value.number;
@ -909,6 +957,16 @@ part_parm :
free_token($3); free_token($3);
} | } |
K_HAS_DW TKN_EQUAL yesno
{
if ($3->primary == K_YES)
current_part->flags |= AVRPART_HAS_DW;
else if ($3->primary == K_NO)
current_part->flags &= ~AVRPART_HAS_DW;
free_token($3);
} |
K_ALLOWFULLPAGEBITSTREAM TKN_EQUAL yesno K_ALLOWFULLPAGEBITSTREAM TKN_EQUAL yesno
{ {
if ($3->primary == K_YES) if ($3->primary == K_YES)

View File

@ -182,11 +182,12 @@ protocol is more sophisticated.
(The JTAG ICE mkII protocol can also be run on top of USB.) (The JTAG ICE mkII protocol can also be run on top of USB.)
Only the memory programming functionality of the JTAG ICE is supported Only the memory programming functionality of the JTAG ICE is supported
by AVRDUDE. by AVRDUDE.
For the JTAG ICE mkII, both JTAG and ISP mode are supported. For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported.
See below for the limitations of debugWire.
The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP). The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP, debugWire).
(High-voltage programming is not yet supported.) (High-voltage programming is not yet supported.)
When used in JTAG mode, the AVR Dragon behaves similar to a When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a
JTAG ICE mkII, so all device-specific comments for that device JTAG ICE mkII, so all device-specific comments for that device
will apply as well. will apply as well.
When used in ISP mode, the AVR Dragon behaves similar to an When used in ISP mode, the AVR Dragon behaves similar to an
@ -385,6 +386,8 @@ Brian Dean's Programmer,@*
Atmel Butterfly Development Board Atmel Butterfly Development Board
@item @code{dt006} @tab @item @code{dt006} @tab
Dontronics DT006 Dontronics DT006
@item @code{dragon_dw} @tab
AVR Dragon in debugWire mode
@item @code{dragon_hvsp} @tab @item @code{dragon_hvsp} @tab
AVR Dragon in high-voltage serial programming mode AVR Dragon in high-voltage serial programming mode
@item @code{dragon_isp} @tab @item @code{dragon_isp} @tab
@ -409,6 +412,8 @@ Atmel JTAG ICE mkII, running at 115200 Bd
@emph{Same as before.} @emph{Same as before.}
@item @code{jtag2isp} @tab @item @code{jtag2isp} @tab
Atmel JTAG ICE mkII in ISP mode. Atmel JTAG ICE mkII in ISP mode.
@item @code{jtag2dw} @tab
Atmel JTAG ICE mkII in debugWire mode.
@item @code{pavr} @tab @item @code{pavr} @tab
Jason Kyle's pAVR Serial Programmer Jason Kyle's pAVR Serial Programmer
@item @code{picoweb} @tab @item @code{picoweb} @tab
@ -1927,6 +1932,36 @@ Solution: none at this time. The simplicity of the USBasp programmer
doesn't offer a method to distinguish multiple programmers that are doesn't offer a method to distinguish multiple programmers that are
connected simultaneously, so effectively only one USBasp is supported. connected simultaneously, so effectively only one USBasp is supported.
@item
Problem: I cannot do @dots{} when the target is in debugWire mode.
Solution: debugWire mode imposes several limitations.
The debugWire protocol is Atmel's proprietary one-wire (plus ground)
protocol to allow an in-circuit emulation of the smaller AVR devices,
using the @var{/RESET} line.
DebugWire mode is initiated by activating the @var{DWEN}
fuse, and then power-cycling the target.
While this mode is mainly intented for debugging/emulation, it
also offers limited programming capabilities.
Effectively, the only memory area that can be read or programmed
in this mode is the flash ROM.
It is also possible to read out the signature.
All other memory areas cannot be accessed.
There is no
@emph{chip erase}
functionality in debugWire mode; instead, while reprogramming the
flash ROM, each flash ROM page is erased right before updating it.
This is done transparently by the JTAG ICE mkII (or AVR Dragon).
The only way back from debugWire mode is to initiate a special
sequence of commands to the JTAG ICE mkII (or AVR Dragon), so the
debugWire mode will be temporarily disabled, and the target can
be accessed using normal ISP programming.
This sequence is automatically initiated by using the JTAG ICE mkII
or AVR Dragon in ISP mode, when they detect that ISP mode cannot be
entered.
@end itemize @end itemize

View File

@ -106,6 +106,11 @@ static struct {
RC(RSP_SET_N_PARAMETERS) RC(RSP_SET_N_PARAMETERS)
}; };
/*
* pgm->flag is marked as "for private use of the programmer".
* The following defines this programmer's use of that field.
*/
#define PGM_FL_IS_DW (0x0001)
/* The length of the device descriptor is firmware-dependent. */ /* The length of the device descriptor is firmware-dependent. */
static size_t device_descriptor_length; static size_t device_descriptor_length;
@ -801,6 +806,18 @@ static int jtagmkII_chip_erase(PROGRAMMER * pgm, AVRPART * p)
return 0; return 0;
} }
/*
* There is no chip erase functionality in debugWire mode.
*/
static int jtagmkII_chip_erase_dw(PROGRAMMER * pgm, AVRPART * p)
{
fprintf(stderr, "%s: Chip erase not supported in debugWire mode\n",
progname);
return 0;
}
static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p) static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p)
{ {
int status; int status;
@ -829,6 +846,8 @@ static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p)
u32_to_b4(sendbuf.dd.ulFlashSize, m->size); u32_to_b4(sendbuf.dd.ulFlashSize, m->size);
u16_to_b2(sendbuf.dd.uiFlashPageSize, flash_pagesize); u16_to_b2(sendbuf.dd.uiFlashPageSize, flash_pagesize);
u16_to_b2(sendbuf.dd.uiFlashpages, m->size / flash_pagesize); u16_to_b2(sendbuf.dd.uiFlashpages, m->size / flash_pagesize);
if (p->flags & AVRPART_HAS_DW)
memcpy(sendbuf.dd.ucFlashInst, p->flash_instr, FLASH_INSTR_SIZE);
} else if (strcmp(m->desc, "eeprom") == 0) { } else if (strcmp(m->desc, "eeprom") == 0) {
sendbuf.dd.ucEepromPageSize = eeprom_pagesize = m->page_size; sendbuf.dd.ucEepromPageSize = eeprom_pagesize = m->page_size;
} }
@ -874,11 +893,21 @@ static int jtagmkII_reset(PROGRAMMER * pgm, unsigned char flags)
int status; int status;
unsigned char buf[2], *resp, c; unsigned char buf[2], *resp, c;
buf[0] = CMND_RESET; /*
buf[1] = flags; * In debugWire mode, don't reset. Do a forced stop, and tell the
* ICE to stop any timers, too.
*/
if (pgm->flag & PGM_FL_IS_DW) {
unsigned char parm[] = { 0 };
(void)jtagmkII_setparm(pgm, PAR_TIMERS_RUNNING, parm);
}
buf[0] = (pgm->flag & PGM_FL_IS_DW)? CMND_FORCED_STOP: CMND_RESET;
buf[1] = (pgm->flag & PGM_FL_IS_DW)? 1: flags;
if (verbose >= 2) if (verbose >= 2)
fprintf(stderr, "%s: jtagmkII_reset(): Sending reset command: ", fprintf(stderr, "%s: jtagmkII_reset(): Sending %s command: ",
progname); progname, (pgm->flag & PGM_FL_IS_DW)? "stop": "reset");
jtagmkII_send(pgm, buf, 2); jtagmkII_send(pgm, buf, 2);
status = jtagmkII_recv(pgm, &resp); status = jtagmkII_recv(pgm, &resp);
@ -1038,10 +1067,23 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p)
{ {
AVRMEM hfuse; AVRMEM hfuse;
unsigned char b; unsigned char b;
int ok;
const char *ifname;
if (!(p->flags & AVRPART_HAS_JTAG)) { ok = 0;
fprintf(stderr, "%s: jtagmkII_initialize(): part %s has no JTAG interface\n", if (pgm->flag & PGM_FL_IS_DW) {
progname, p->desc); ifname = "debugWire";
if (p->flags & AVRPART_HAS_DW)
ok = 1;
} else {
ifname = "JTAG";
if (p->flags & AVRPART_HAS_JTAG)
ok = 1;
}
if (!ok) {
fprintf(stderr, "%s: jtagmkII_initialize(): part %s has no %s interface\n",
progname, p->desc, ifname);
return -1; return -1;
} }
@ -1058,7 +1100,7 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p)
serial_setspeed(pgm->fd, pgm->baudrate); serial_setspeed(pgm->fd, pgm->baudrate);
} }
} }
if (pgm->bitclock != 0.0) { if (!(pgm->flag & PGM_FL_IS_DW) && pgm->bitclock != 0.0) {
if (verbose >= 2) if (verbose >= 2)
fprintf(stderr, "%s: jtagmkII_initialize(): " fprintf(stderr, "%s: jtagmkII_initialize(): "
"trying to set JTAG clock period to %.1f us\n", "trying to set JTAG clock period to %.1f us\n",
@ -1090,14 +1132,16 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p)
if (jtagmkII_reset(pgm, 0x01) < 0) if (jtagmkII_reset(pgm, 0x01) < 0)
return -1; return -1;
strcpy(hfuse.desc, "hfuse"); if (!(pgm->flag & PGM_FL_IS_DW)) {
if (jtagmkII_read_byte(pgm, p, &hfuse, 1, &b) < 0) strcpy(hfuse.desc, "hfuse");
return -1; if (jtagmkII_read_byte(pgm, p, &hfuse, 1, &b) < 0)
if ((b & OCDEN) != 0) return -1;
fprintf(stderr, if ((b & OCDEN) != 0)
"%s: jtagmkII_initialize(): warning: OCDEN fuse not programmed, " fprintf(stderr,
"single-byte EEPROM updates not possible\n", "%s: jtagmkII_initialize(): warning: OCDEN fuse not programmed, "
progname); "single-byte EEPROM updates not possible\n",
progname);
}
return 0; return 0;
} }
@ -1111,7 +1155,8 @@ static void jtagmkII_disable(PROGRAMMER * pgm)
free(eeprom_pagecache); free(eeprom_pagecache);
eeprom_pagecache = NULL; eeprom_pagecache = NULL;
(void)jtagmkII_program_disable(pgm); if (!(pgm->flag & PGM_FL_IS_DW))
(void)jtagmkII_program_disable(pgm);
} }
static void jtagmkII_enable(PROGRAMMER * pgm) static void jtagmkII_enable(PROGRAMMER * pgm)
@ -1165,6 +1210,51 @@ static int jtagmkII_open(PROGRAMMER * pgm, char * port)
} }
static int jtagmkII_open_dw(PROGRAMMER * pgm, char * port)
{
long baud;
if (verbose >= 2)
fprintf(stderr, "%s: jtagmkII_open_dw()\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
*/
jtagmkII_drain(pgm, 0);
jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE);
return 0;
}
static int jtagmkII_dragon_open(PROGRAMMER * pgm, char * port) static int jtagmkII_dragon_open(PROGRAMMER * pgm, char * port)
{ {
long baud; long baud;
@ -1210,6 +1300,51 @@ static int jtagmkII_dragon_open(PROGRAMMER * pgm, char * port)
} }
static int jtagmkII_dragon_open_dw(PROGRAMMER * pgm, char * port)
{
long baud;
if (verbose >= 2)
fprintf(stderr, "%s: jtagmkII_dragon_open_dw()\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_AVRDRAGON;
#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
*/
jtagmkII_drain(pgm, 0);
jtagmkII_getsync(pgm, EMULATOR_MODE_DEBUGWIRE);
return 0;
}
void jtagmkII_close(PROGRAMMER * pgm) void jtagmkII_close(PROGRAMMER * pgm)
{ {
int status; int status;
@ -1299,7 +1434,7 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
fprintf(stderr, "%s: jtagmkII_paged_write(.., %s, %d, %d)\n", fprintf(stderr, "%s: jtagmkII_paged_write(.., %s, %d, %d)\n",
progname, m->desc, page_size, n_bytes); progname, m->desc, page_size, n_bytes);
if (jtagmkII_program_enable(pgm) < 0) if (!(pgm->flag & PGM_FL_IS_DW) && jtagmkII_program_enable(pgm) < 0)
return -1; return -1;
if (page_size == 0) page_size = 256; if (page_size == 0) page_size = 256;
@ -1319,6 +1454,10 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[1] = MTYPE_EEPROM_PAGE; cmd[1] = MTYPE_EEPROM_PAGE;
eeprom_pageaddr = (unsigned long)-1L; eeprom_pageaddr = (unsigned long)-1L;
page_size = eeprom_pagesize; page_size = eeprom_pagesize;
if (pgm->flag & PGM_FL_IS_DW) {
free(cmd);
return -1;
}
} }
serial_recv_timeout = 100; serial_recv_timeout = 100;
@ -1393,6 +1532,7 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
return -1; return -1;
} }
free(resp); free(resp);
usleep(1000000);
} }
free(cmd); free(cmd);
@ -1414,7 +1554,7 @@ static int jtagmkII_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
fprintf(stderr, "%s: jtagmkII_paged_load(.., %s, %d, %d)\n", fprintf(stderr, "%s: jtagmkII_paged_load(.., %s, %d, %d)\n",
progname, m->desc, page_size, n_bytes); progname, m->desc, page_size, n_bytes);
if (jtagmkII_program_enable(pgm) < 0) if (!(pgm->flag & PGM_FL_IS_DW) && jtagmkII_program_enable(pgm) < 0)
return -1; return -1;
page_size = m->readsize; page_size = m->readsize;
@ -1424,6 +1564,8 @@ static int jtagmkII_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[1] = MTYPE_FLASH_PAGE; cmd[1] = MTYPE_FLASH_PAGE;
} else if (strcmp(m->desc, "eeprom") == 0) { } else if (strcmp(m->desc, "eeprom") == 0) {
cmd[1] = MTYPE_EEPROM_PAGE; cmd[1] = MTYPE_EEPROM_PAGE;
if (pgm->flag & PGM_FL_IS_DW)
return -1;
} }
serial_recv_timeout = 100; serial_recv_timeout = 100;
@ -1497,7 +1639,7 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
{ {
unsigned char cmd[10]; unsigned char cmd[10];
unsigned char *resp = NULL, *cache_ptr = NULL; unsigned char *resp = NULL, *cache_ptr = NULL;
int status, tries; int status, tries, unsupp;
unsigned long paddr = 0UL, *paddr_ptr = NULL; unsigned long paddr = 0UL, *paddr_ptr = NULL;
unsigned int pagesize = 0; unsigned int pagesize = 0;
@ -1505,10 +1647,11 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
fprintf(stderr, "%s: jtagmkII_read_byte(.., %s, 0x%lx, ...)\n", fprintf(stderr, "%s: jtagmkII_read_byte(.., %s, 0x%lx, ...)\n",
progname, mem->desc, addr); progname, mem->desc, addr);
if (jtagmkII_program_enable(pgm) < 0) if (!(pgm->flag & PGM_FL_IS_DW) && jtagmkII_program_enable(pgm) < 0)
return -1; return -1;
cmd[0] = CMND_READ_MEMORY; cmd[0] = CMND_READ_MEMORY;
unsupp = 0;
if (strcmp(mem->desc, "flash") == 0) { if (strcmp(mem->desc, "flash") == 0) {
cmd[1] = MTYPE_FLASH_PAGE; cmd[1] = MTYPE_FLASH_PAGE;
@ -1522,21 +1665,71 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
paddr = addr & ~(pagesize - 1); paddr = addr & ~(pagesize - 1);
paddr_ptr = &eeprom_pageaddr; paddr_ptr = &eeprom_pageaddr;
cache_ptr = eeprom_pagecache; cache_ptr = eeprom_pagecache;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "lfuse") == 0) { } else if (strcmp(mem->desc, "lfuse") == 0) {
cmd[1] = MTYPE_FUSE_BITS; cmd[1] = MTYPE_FUSE_BITS;
addr = 0; addr = 0;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "hfuse") == 0) { } else if (strcmp(mem->desc, "hfuse") == 0) {
cmd[1] = MTYPE_FUSE_BITS; cmd[1] = MTYPE_FUSE_BITS;
addr = 1; addr = 1;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "efuse") == 0) { } else if (strcmp(mem->desc, "efuse") == 0) {
cmd[1] = MTYPE_FUSE_BITS; cmd[1] = MTYPE_FUSE_BITS;
addr = 2; addr = 2;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "lock") == 0) { } else if (strcmp(mem->desc, "lock") == 0) {
cmd[1] = MTYPE_LOCK_BITS; cmd[1] = MTYPE_LOCK_BITS;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "calibration") == 0) { } else if (strcmp(mem->desc, "calibration") == 0) {
cmd[1] = MTYPE_OSCCAL_BYTE; cmd[1] = MTYPE_OSCCAL_BYTE;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "signature") == 0) { } else if (strcmp(mem->desc, "signature") == 0) {
cmd[1] = MTYPE_SIGN_JTAG; cmd[1] = MTYPE_SIGN_JTAG;
if (pgm->flag & PGM_FL_IS_DW) {
/*
* In debugWire mode, there is no accessible memory area to read
* the signature from, but the essential two bytes can be read
* as a parameter from the ICE.
*/
unsigned char parm[4];
switch (addr) {
case 0:
*value = 0x1E; /* Atmel vendor ID */
break;
case 1:
case 2:
if (jtagmkII_getparm(pgm, PAR_TARGET_SIGNATURE, parm) < 0)
return -1;
*value = parm[2 - addr];
break;
default:
fprintf(stderr, "%s: illegal address %lu for signature memory\n",
progname, addr);
*value = 42;
return -1;
}
return 0;
}
}
/*
* If the respective memory area is not supported under debugWire,
* leave here.
*/
if (unsupp) {
*value = 42;
return -1;
} }
/* /*
@ -1720,6 +1913,17 @@ fail:
} }
static int jtagmkII_write_byte_dw(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char data)
{
fprintf(stderr,
"%s: jtagmkII_write_byte_dw(): no single-byte writes supported in debugWire\n",
progname);
return -1;
}
/* /*
* Set the JTAG clock. The actual frequency is quite a bit of * Set the JTAG clock. The actual frequency is quite a bit of
* guesswork, based on the values claimed by AVR Studio. Inside the * guesswork, based on the values claimed by AVR Studio. Inside the
@ -1824,6 +2028,7 @@ static int jtagmkII_setparm(PROGRAMMER * pgm, unsigned char parm,
case PAR_BAUD_RATE: size = 1; break; case PAR_BAUD_RATE: size = 1; break;
case PAR_OCD_VTARGET: size = 2; break; case PAR_OCD_VTARGET: size = 2; break;
case PAR_OCD_JTAG_CLK: size = 1; break; case PAR_OCD_JTAG_CLK: size = 1; break;
case PAR_TIMERS_RUNNING: size = 1; break;
default: default:
fprintf(stderr, "%s: jtagmkII_setparm(): unknown parameter 0x%02x\n", fprintf(stderr, "%s: jtagmkII_setparm(): unknown parameter 0x%02x\n",
progname, parm); progname, parm);
@ -1895,28 +2100,33 @@ static void jtagmkII_print_parms1(PROGRAMMER * pgm, char * p)
char clkbuf[20]; char clkbuf[20];
double clk; double clk;
if (jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget) < 0 || if (jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget) < 0)
jtagmkII_getparm(pgm, PAR_OCD_JTAG_CLK, jtag_clock) < 0)
return; return;
if (jtag_clock[0] == 0) {
strcpy(clkbuf, "6.4 MHz");
clk = 6.4e6;
} else if (jtag_clock[0] == 1) {
strcpy(clkbuf, "2.8 MHz");
clk = 2.8e6;
} else if (jtag_clock[0] <= 5) {
sprintf(clkbuf, "%.1f MHz", 5.35 / (double)jtag_clock[0]);
clk = 5.35e6 / (double)jtag_clock[0];
} else {
sprintf(clkbuf, "%.1f kHz", 5.35e3 / (double)jtag_clock[0]);
clk = 5.35e6 / (double)jtag_clock[0];
}
fprintf(stderr, "%sVtarget : %.1f V\n", p, fprintf(stderr, "%sVtarget : %.1f V\n", p,
b2_to_u16(vtarget) / 1000.0); b2_to_u16(vtarget) / 1000.0);
fprintf(stderr, "%sJTAG clock : %s (%.1f us)\n", p, clkbuf,
1.0e6 / clk); if (!(pgm->flag & PGM_FL_IS_DW)) {
if (jtagmkII_getparm(pgm, PAR_OCD_JTAG_CLK, jtag_clock) < 0)
return;
if (jtag_clock[0] == 0) {
strcpy(clkbuf, "6.4 MHz");
clk = 6.4e6;
} else if (jtag_clock[0] == 1) {
strcpy(clkbuf, "2.8 MHz");
clk = 2.8e6;
} else if (jtag_clock[0] <= 5) {
sprintf(clkbuf, "%.1f MHz", 5.35 / (double)jtag_clock[0]);
clk = 5.35e6 / (double)jtag_clock[0];
} else {
sprintf(clkbuf, "%.1f kHz", 5.35e3 / (double)jtag_clock[0]);
clk = 5.35e6 / (double)jtag_clock[0];
fprintf(stderr, "%sJTAG clock : %s (%.1f us)\n", p, clkbuf,
1.0e6 / clk);
}
}
return; return;
} }
@ -1957,6 +2167,35 @@ void jtagmkII_initpgm(PROGRAMMER * pgm)
} }
void jtagmkII_dw_initpgm(PROGRAMMER * pgm)
{
strcpy(pgm->type, "JTAGMKII_DW");
/*
* mandatory functions
*/
pgm->initialize = jtagmkII_initialize;
pgm->display = jtagmkII_display;
pgm->enable = jtagmkII_enable;
pgm->disable = jtagmkII_disable;
pgm->program_enable = jtagmkII_program_enable_dummy;
pgm->chip_erase = jtagmkII_chip_erase_dw;
pgm->open = jtagmkII_open_dw;
pgm->close = jtagmkII_close;
pgm->read_byte = jtagmkII_read_byte;
pgm->write_byte = jtagmkII_write_byte_dw;
/*
* optional functions
*/
pgm->paged_write = jtagmkII_paged_write;
pgm->paged_load = jtagmkII_paged_load;
pgm->print_parms = jtagmkII_print_parms;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_DW;
}
void jtagmkII_dragon_initpgm(PROGRAMMER * pgm) void jtagmkII_dragon_initpgm(PROGRAMMER * pgm)
{ {
strcpy(pgm->type, "DRAGON_JTAG"); strcpy(pgm->type, "DRAGON_JTAG");
@ -1984,3 +2223,32 @@ void jtagmkII_dragon_initpgm(PROGRAMMER * pgm)
pgm->set_sck_period = jtagmkII_set_sck_period; pgm->set_sck_period = jtagmkII_set_sck_period;
pgm->page_size = 256; pgm->page_size = 256;
} }
void jtagmkII_dragon_dw_initpgm(PROGRAMMER * pgm)
{
strcpy(pgm->type, "DRAGON_DW");
/*
* mandatory functions
*/
pgm->initialize = jtagmkII_initialize;
pgm->display = jtagmkII_display;
pgm->enable = jtagmkII_enable;
pgm->disable = jtagmkII_disable;
pgm->program_enable = jtagmkII_program_enable_dummy;
pgm->chip_erase = jtagmkII_chip_erase_dw;
pgm->open = jtagmkII_dragon_open_dw;
pgm->close = jtagmkII_close;
pgm->read_byte = jtagmkII_read_byte;
pgm->write_byte = jtagmkII_write_byte_dw;
/*
* optional functions
*/
pgm->paged_write = jtagmkII_paged_write;
pgm->paged_load = jtagmkII_paged_load;
pgm->print_parms = jtagmkII_print_parms;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_DW;
}

View File

@ -30,7 +30,9 @@ int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm,
unsigned char * value); unsigned char * value);
void jtagmkII_initpgm (PROGRAMMER * pgm); void jtagmkII_initpgm (PROGRAMMER * pgm);
void jtagmkII_dw_initpgm (PROGRAMMER * pgm);
void jtagmkII_dragon_initpgm (PROGRAMMER * pgm); void jtagmkII_dragon_initpgm (PROGRAMMER * pgm);
void jtagmkII_dragon_dw_initpgm (PROGRAMMER * pgm);
#endif #endif

View File

@ -135,6 +135,7 @@ default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; }
default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; } default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; }
default_serial { yylval=NULL; return K_DEFAULT_SERIAL; } default_serial { yylval=NULL; return K_DEFAULT_SERIAL; }
devicecode { yylval=NULL; return K_DEVICECODE; } devicecode { yylval=NULL; return K_DEVICECODE; }
dragon_dw { yylval=NULL; return K_DRAGON_DW; }
dragon_hvsp { yylval=NULL; return K_DRAGON_HVSP; } dragon_hvsp { yylval=NULL; return K_DRAGON_HVSP; }
dragon_isp { yylval=NULL; return K_DRAGON_ISP; } dragon_isp { yylval=NULL; return K_DRAGON_ISP; }
dragon_jtag { yylval=NULL; return K_DRAGON_JTAG; } dragon_jtag { yylval=NULL; return K_DRAGON_JTAG; }
@ -145,10 +146,12 @@ enablepageprogramming { yylval=NULL; return K_ENABLEPAGEPROGRAMMING; }
errled { yylval=NULL; return K_ERRLED; } errled { yylval=NULL; return K_ERRLED; }
flash { yylval=NULL; return K_FLASH; } flash { yylval=NULL; return K_FLASH; }
has_jtag { yylval=NULL; return K_HAS_JTAG; } has_jtag { yylval=NULL; return K_HAS_JTAG; }
has_debugwire { yylval=NULL; return K_HAS_DW; }
id { yylval=NULL; return K_ID; } id { yylval=NULL; return K_ID; }
idr { yylval=NULL; return K_IDR; } idr { yylval=NULL; return K_IDR; }
jtagmki { yylval=NULL; return K_JTAG_MKI; } jtagmki { yylval=NULL; return K_JTAG_MKI; }
jtagmkii { yylval=NULL; return K_JTAG_MKII; } jtagmkii { yylval=NULL; return K_JTAG_MKII; }
jtagmkii_dw { yylval=NULL; return K_JTAG_MKII_DW; }
jtagmkii_isp { yylval=NULL; return K_JTAG_MKII_ISP; } jtagmkii_isp { yylval=NULL; return K_JTAG_MKII_ISP; }
max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; } max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; }
memory { yylval=NULL; return K_MEMORY; } memory { yylval=NULL; return K_MEMORY; }
@ -220,7 +223,7 @@ programfusepulsewidth { yylval=NULL; return K_PROGRAMFUSEPULSEWIDTH; }
programfusepolltimeout { yylval=NULL; return K_PROGRAMFUSEPOLLTIMEOUT; } programfusepolltimeout { yylval=NULL; return K_PROGRAMFUSEPOLLTIMEOUT; }
programlockpulsewidth { yylval=NULL; return K_PROGRAMLOCKPULSEWIDTH; } programlockpulsewidth { yylval=NULL; return K_PROGRAMLOCKPULSEWIDTH; }
programlockpolltimeout { yylval=NULL; return K_PROGRAMLOCKPOLLTIMEOUT; } programlockpolltimeout { yylval=NULL; return K_PROGRAMLOCKPOLLTIMEOUT; }
flash_instr { yylval=NULL; return K_FLASH_INSTR; }
dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; } dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; }
io { yylval=new_token(K_IO); return K_IO; } io { yylval=new_token(K_IO); return K_IO; }