diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog index 3a467f7a..2edfbef3 100644 --- a/avrdude/ChangeLog +++ b/avrdude/ChangeLog @@ -1,3 +1,15 @@ +2006-11-21 Joerg Wunsch + + 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 * jtagmkI.c (jtagmkI_close): remove two unused variables. diff --git a/avrdude/avrdude.1 b/avrdude/avrdude.1 index 5907e42b..f5f8de26 100644 --- a/avrdude/avrdude.1 +++ b/avrdude/avrdude.1 @@ -112,10 +112,11 @@ supported on a serial port. .Pp Atmel's JTAG ICE (both mkI and mkII) is supported as well to up- or download memory areas from/to an AVR target (no support for on-chip debugging). -For the JTAG ICE mkII, both JTAG and ISP mode are supported. +For the JTAG ICE mkII, JTAG, debugWire and ISP mode are supported. +See below for the limitations of debugWire. .Pp -The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP). -When used in JTAG mode, the AVR Dragon behaves similar to a +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 JTAG ICE mkII, so all device-specific comments for that device will apply as well. When used in ISP mode, the AVR Dragon behaves similar to an @@ -710,6 +711,33 @@ ll. 10 MISO (from MCU) 18-25 GND .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 .Bl -tag -offset indent -width /dev/ppi0XXX .It Pa /dev/ppi0 diff --git a/avrdude/avrdude.conf.in b/avrdude/avrdude.conf.in index 365b6367..762a8679 100644 --- a/avrdude/avrdude.conf.in +++ b/avrdude/avrdude.conf.in @@ -17,8 +17,8 @@ # desc = ; # quoted string # type = par | stk500 | stk500v2 | stk500pp | stk500hvsp | stk500generic | # avr910 | butterfly | usbasp | -# jtagmki | jtagmkii | jtagmkii_isp | -# dragon_jtag | dragon_isp | dragon_pp | +# jtagmki | jtagmkii | jtagmkii_isp | jtagmkii_dw | +# dragon_dw | dragon_jtag | dragon_isp | dragon_pp | # dragon_hvsp; # programmer type # baudrate = ; # baudrate for avr910-programmer # vcc = [, ... ] ; # pin number(s) @@ -36,6 +36,7 @@ # id = ; # quoted string # desc = ; # quoted string # has_jtag = ; # part has JTAG i/f +# has_debugwire = ; # part has debugWire i/f # devicecode = ; # deprecated, use stk500_devcode # stk500_devcode = ; # numeric # avr910_devcode = ; # numeric @@ -443,6 +444,14 @@ programmer 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 programmer id = "dragon_jtag"; @@ -475,6 +484,14 @@ programmer 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 id = "pavr"; desc = "Jason Kyle's pAVR Serial Programmer"; @@ -9182,6 +9199,7 @@ part part id = "t44"; desc = "ATtiny44"; + has_debugwire = yes; ## no STK500 devcode in XML file, use the ATtiny45 one stk500_devcode = 0x14; ## avr910_devcode = ?; @@ -9228,6 +9246,8 @@ part programfusepolltimeout = 25; programlockpolltimeout = 25; + flash_instr = 0xb4, 0x07, 0x17; + memory "eeprom" size = 256; paged = no; diff --git a/avrdude/avrpart.h b/avrdude/avrpart.h index 0b90faae..2e5bc48d 100644 --- a/avrdude/avrpart.h +++ b/avrdude/avrpart.h @@ -89,10 +89,12 @@ typedef struct opcode { #define AVRPART_HAS_JTAG 0x0008 /* part has a JTAG i/f */ #define AVRPART_ALLOWFULLPAGEBITSTREAM 0x0010 /* 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_IDLEN 32 #define CTL_STACK_SIZE 32 +#define FLASH_INSTR_SIZE 3 typedef struct avrpart { char desc[AVR_DESCLEN]; /* long 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 */ 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 progmodedelay; /* stk500 v2 hv mode parameter */ diff --git a/avrdude/config_gram.y b/avrdude/config_gram.y index ad8978d7..185e4725 100644 --- a/avrdude/config_gram.y +++ b/avrdude/config_gram.y @@ -88,6 +88,7 @@ static int parse_cmdbits(OPCODE * op); %token K_DEFAULT_SERIAL %token K_DESC %token K_DEVICECODE +%token K_DRAGON_DW %token K_DRAGON_HVSP %token K_DRAGON_ISP %token K_DRAGON_JTAG @@ -101,6 +102,7 @@ static int parse_cmdbits(OPCODE * op); %token K_IO %token K_JTAG_MKI %token K_JTAG_MKII +%token K_JTAG_MKII_DW %token K_JTAG_MKII_ISP %token K_LOADPAGE %token K_MAX_WRITE_DELAY @@ -194,10 +196,12 @@ static int parse_cmdbits(OPCODE * op); */ %token K_ENABLEPAGEPROGRAMMING /* ? yes for mega256*, mega406 */ %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_RAMPZ /* address of RAMPZ reg. in IO space */ %token K_SPMCR /* address of SPMC[S]R in memory space */ %token K_EECR /* address of EECR in memory space */ +%token K_FLASH_INSTR /* flash instructions */ %token TKN_COMMA %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 { { 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 { { 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 { current_part->chip_erase_delay = $3->value.number; @@ -909,6 +957,16 @@ part_parm : 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 { if ($3->primary == K_YES) diff --git a/avrdude/doc/avrdude.texi b/avrdude/doc/avrdude.texi index 5a81c9e2..472a323f 100644 --- a/avrdude/doc/avrdude.texi +++ b/avrdude/doc/avrdude.texi @@ -182,11 +182,12 @@ protocol is more sophisticated. (The JTAG ICE mkII protocol can also be run on top of USB.) Only the memory programming functionality of the JTAG ICE is supported by AVRDUDE. -For the JTAG ICE mkII, both JTAG and ISP mode are supported. +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.) -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 will apply as well. When used in ISP mode, the AVR Dragon behaves similar to an @@ -385,6 +386,8 @@ Brian Dean's Programmer,@* Atmel Butterfly Development Board @item @code{dt006} @tab Dontronics DT006 +@item @code{dragon_dw} @tab +AVR Dragon in debugWire mode @item @code{dragon_hvsp} @tab AVR Dragon in high-voltage serial programming mode @item @code{dragon_isp} @tab @@ -409,6 +412,8 @@ Atmel JTAG ICE mkII, running at 115200 Bd @emph{Same as before.} @item @code{jtag2isp} @tab Atmel JTAG ICE mkII in ISP mode. +@item @code{jtag2dw} @tab +Atmel JTAG ICE mkII in debugWire mode. @item @code{pavr} @tab Jason Kyle's pAVR Serial Programmer @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 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 diff --git a/avrdude/jtagmkII.c b/avrdude/jtagmkII.c index 505b0107..7e6f38a1 100644 --- a/avrdude/jtagmkII.c +++ b/avrdude/jtagmkII.c @@ -106,6 +106,11 @@ static struct { 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. */ static size_t device_descriptor_length; @@ -801,6 +806,18 @@ static int jtagmkII_chip_erase(PROGRAMMER * pgm, AVRPART * p) 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) { int status; @@ -829,6 +846,8 @@ static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p) u32_to_b4(sendbuf.dd.ulFlashSize, m->size); u16_to_b2(sendbuf.dd.uiFlashPageSize, 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) { sendbuf.dd.ucEepromPageSize = eeprom_pagesize = m->page_size; } @@ -874,11 +893,21 @@ static int jtagmkII_reset(PROGRAMMER * pgm, unsigned char flags) int status; 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) - fprintf(stderr, "%s: jtagmkII_reset(): Sending reset command: ", - progname); + fprintf(stderr, "%s: jtagmkII_reset(): Sending %s command: ", + progname, (pgm->flag & PGM_FL_IS_DW)? "stop": "reset"); jtagmkII_send(pgm, buf, 2); status = jtagmkII_recv(pgm, &resp); @@ -1038,10 +1067,23 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) { AVRMEM hfuse; unsigned char b; + int ok; + const char *ifname; - if (!(p->flags & AVRPART_HAS_JTAG)) { - fprintf(stderr, "%s: jtagmkII_initialize(): part %s has no JTAG interface\n", - progname, p->desc); + ok = 0; + if (pgm->flag & PGM_FL_IS_DW) { + 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; } @@ -1058,7 +1100,7 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) 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) fprintf(stderr, "%s: jtagmkII_initialize(): " "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) return -1; - strcpy(hfuse.desc, "hfuse"); - if (jtagmkII_read_byte(pgm, p, &hfuse, 1, &b) < 0) - return -1; - if ((b & OCDEN) != 0) - fprintf(stderr, - "%s: jtagmkII_initialize(): warning: OCDEN fuse not programmed, " - "single-byte EEPROM updates not possible\n", - progname); + if (!(pgm->flag & PGM_FL_IS_DW)) { + strcpy(hfuse.desc, "hfuse"); + if (jtagmkII_read_byte(pgm, p, &hfuse, 1, &b) < 0) + return -1; + if ((b & OCDEN) != 0) + fprintf(stderr, + "%s: jtagmkII_initialize(): warning: OCDEN fuse not programmed, " + "single-byte EEPROM updates not possible\n", + progname); + } return 0; } @@ -1111,7 +1155,8 @@ static void jtagmkII_disable(PROGRAMMER * pgm) free(eeprom_pagecache); 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) @@ -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) { 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) { 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", 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; 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; eeprom_pageaddr = (unsigned long)-1L; page_size = eeprom_pagesize; + if (pgm->flag & PGM_FL_IS_DW) { + free(cmd); + return -1; + } } serial_recv_timeout = 100; @@ -1393,6 +1532,7 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, return -1; } free(resp); + usleep(1000000); } 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", 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; page_size = m->readsize; @@ -1424,6 +1564,8 @@ static int jtagmkII_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[1] = MTYPE_FLASH_PAGE; } else if (strcmp(m->desc, "eeprom") == 0) { cmd[1] = MTYPE_EEPROM_PAGE; + if (pgm->flag & PGM_FL_IS_DW) + return -1; } 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 *resp = NULL, *cache_ptr = NULL; - int status, tries; + int status, tries, unsupp; unsigned long paddr = 0UL, *paddr_ptr = NULL; 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", progname, mem->desc, addr); - if (jtagmkII_program_enable(pgm) < 0) + if (!(pgm->flag & PGM_FL_IS_DW) && jtagmkII_program_enable(pgm) < 0) return -1; cmd[0] = CMND_READ_MEMORY; + unsupp = 0; if (strcmp(mem->desc, "flash") == 0) { 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_ptr = &eeprom_pageaddr; cache_ptr = eeprom_pagecache; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; } else if (strcmp(mem->desc, "lfuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; addr = 0; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; } else if (strcmp(mem->desc, "hfuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; addr = 1; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; } else if (strcmp(mem->desc, "efuse") == 0) { cmd[1] = MTYPE_FUSE_BITS; addr = 2; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; } else if (strcmp(mem->desc, "lock") == 0) { cmd[1] = MTYPE_LOCK_BITS; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; } else if (strcmp(mem->desc, "calibration") == 0) { cmd[1] = MTYPE_OSCCAL_BYTE; + if (pgm->flag & PGM_FL_IS_DW) + unsupp = 1; } else if (strcmp(mem->desc, "signature") == 0) { 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 * 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_OCD_VTARGET: size = 2; break; case PAR_OCD_JTAG_CLK: size = 1; break; + case PAR_TIMERS_RUNNING: size = 1; break; default: fprintf(stderr, "%s: jtagmkII_setparm(): unknown parameter 0x%02x\n", progname, parm); @@ -1895,28 +2100,33 @@ static void jtagmkII_print_parms1(PROGRAMMER * pgm, char * p) char clkbuf[20]; double clk; - if (jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget) < 0 || - jtagmkII_getparm(pgm, PAR_OCD_JTAG_CLK, jtag_clock) < 0) + if (jtagmkII_getparm(pgm, PAR_OCD_VTARGET, vtarget) < 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, "%sVtarget : %.1f V\n", p, 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; } @@ -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) { strcpy(pgm->type, "DRAGON_JTAG"); @@ -1984,3 +2223,32 @@ void jtagmkII_dragon_initpgm(PROGRAMMER * pgm) pgm->set_sck_period = jtagmkII_set_sck_period; 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; +} diff --git a/avrdude/jtagmkII.h b/avrdude/jtagmkII.h index 39eea580..87023357 100644 --- a/avrdude/jtagmkII.h +++ b/avrdude/jtagmkII.h @@ -30,7 +30,9 @@ int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value); void jtagmkII_initpgm (PROGRAMMER * pgm); +void jtagmkII_dw_initpgm (PROGRAMMER * pgm); void jtagmkII_dragon_initpgm (PROGRAMMER * pgm); +void jtagmkII_dragon_dw_initpgm (PROGRAMMER * pgm); #endif diff --git a/avrdude/lexer.l b/avrdude/lexer.l index a52f914a..22a35dda 100644 --- a/avrdude/lexer.l +++ b/avrdude/lexer.l @@ -135,6 +135,7 @@ default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; } default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; } default_serial { yylval=NULL; return K_DEFAULT_SERIAL; } devicecode { yylval=NULL; return K_DEVICECODE; } +dragon_dw { yylval=NULL; return K_DRAGON_DW; } dragon_hvsp { yylval=NULL; return K_DRAGON_HVSP; } dragon_isp { yylval=NULL; return K_DRAGON_ISP; } dragon_jtag { yylval=NULL; return K_DRAGON_JTAG; } @@ -145,10 +146,12 @@ enablepageprogramming { yylval=NULL; return K_ENABLEPAGEPROGRAMMING; } errled { yylval=NULL; return K_ERRLED; } flash { yylval=NULL; return K_FLASH; } has_jtag { yylval=NULL; return K_HAS_JTAG; } +has_debugwire { yylval=NULL; return K_HAS_DW; } id { yylval=NULL; return K_ID; } idr { yylval=NULL; return K_IDR; } jtagmki { yylval=NULL; return K_JTAG_MKI; } jtagmkii { yylval=NULL; return K_JTAG_MKII; } +jtagmkii_dw { yylval=NULL; return K_JTAG_MKII_DW; } jtagmkii_isp { yylval=NULL; return K_JTAG_MKII_ISP; } max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; } memory { yylval=NULL; return K_MEMORY; } @@ -220,7 +223,7 @@ programfusepulsewidth { yylval=NULL; return K_PROGRAMFUSEPULSEWIDTH; } programfusepolltimeout { yylval=NULL; return K_PROGRAMFUSEPOLLTIMEOUT; } programlockpulsewidth { yylval=NULL; return K_PROGRAMLOCKPULSEWIDTH; } programlockpolltimeout { yylval=NULL; return K_PROGRAMLOCKPOLLTIMEOUT; } - +flash_instr { yylval=NULL; return K_FLASH_INSTR; } dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; } io { yylval=new_token(K_IO); return K_IO; }