diff --git a/ChangeLog b/ChangeLog index 83bd59be..68ac0fc0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-01-13 Joerg Wunsch + + * jtagmkII.c: Implement PDI mode support for the JTAG ICE mkII + and the AVR Dragon. + * jtagmkII.h: (Dito.) + * config_gram.y: (Dito.) + * jtagmkII_private.h: (Dito.) + * avrdude.conf.in: (Dito.) + * lexer.l: (Dito.) + 2010-01-13 Joerg Wunsch * stk500v2.c: Update STK600 routing and socket card data from XML diff --git a/NEWS b/NEWS index cefb9bef..861de969 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ Current: - BusPirate - Arduino + - JTAGICEmkII and AVR Dragon in PDI mode (ATxmega devices) * Bugfixes diff --git a/avrdude.conf.in b/avrdude.conf.in index 51ca2bcf..950d1de7 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -18,9 +18,10 @@ # type = par | stk500 | stk500v2 | stk500pp | stk500hvsp | stk500generic | # stk600 | stk600pp | stk600hvsp | # avr910 | butterfly | usbasp | -# jtagmki | jtagmkii | jtagmkii_isp | jtagmkii_dw | jtagmkII_avr32 | +# jtagmki | jtagmkii | jtagmkii_isp | jtagmkii_dw | +# jtagmkII_avr32 | jtagmkii_pdi | # dragon_dw | dragon_jtag | dragon_isp | dragon_pp | -# dragon_hvsp | arduino; # programmer type +# dragon_hvsp | dragon_pdi | arduino; # programmer type # baudrate = ; # baudrate for avr910-programmer # vcc = [, ... ] ; # pin number(s) # reset = ; # pin number @@ -515,9 +516,26 @@ programmer programmer id = "jtagmkII_avr32"; desc = "Atmel JTAG ICE mkII im AVR32 mode"; - baudrate = 115200; + baudrate = 115200; type = jtagmkii_avr32; ; + +# JTAG ICE mkII in AVR32 mode +programmer + id = "jtag2avr32"; + desc = "Atmel JTAG ICE mkII im AVR32 mode"; + baudrate = 115200; + type = jtagmkii_avr32; +; + +# JTAG ICE mkII in PDI mode +programmer + id = "jtag2pdi"; + desc = "Atmel JTAG ICE mkII PDI mode"; + baudrate = 115200; + type = jtagmkii_pdi; +; + # AVR Dragon in JTAG mode programmer id = "dragon_jtag"; @@ -558,6 +576,14 @@ programmer type = dragon_dw; ; +# AVR Dragon in PDI mode +programmer + id = "dragon_pdi"; + desc = "Atmel AVR Dragon in PDI mode"; + baudrate = 115200; + type = dragon_pdi; +; + programmer id = "pavr"; desc = "Jason Kyle's pAVR Serial Programmer"; diff --git a/config_gram.y b/config_gram.y index cf412ce0..32dedc92 100644 --- a/config_gram.y +++ b/config_gram.y @@ -97,6 +97,7 @@ static int parse_cmdbits(OPCODE * op); %token K_DRAGON_HVSP %token K_DRAGON_ISP %token K_DRAGON_JTAG +%token K_DRAGON_PDI %token K_DRAGON_PP %token K_STK500_DEVCODE %token K_AVR910_DEVCODE @@ -110,6 +111,7 @@ static int parse_cmdbits(OPCODE * op); %token K_JTAG_MKII_AVR32 %token K_JTAG_MKII_DW %token K_JTAG_MKII_ISP +%token K_JTAG_MKII_PDI %token K_LOADPAGE %token K_MAX_WRITE_DELAY %token K_MIN_WRITE_DELAY @@ -506,6 +508,12 @@ prog_parm : } } | + K_TYPE TKN_EQUAL K_JTAG_MKII_PDI { + { + jtagmkII_pdi_initpgm(current_prog); + } + } | + K_TYPE TKN_EQUAL K_DRAGON_DW { { jtagmkII_dragon_dw_initpgm(current_prog); @@ -530,6 +538,12 @@ prog_parm : } } | + K_TYPE TKN_EQUAL K_DRAGON_PDI { + { + jtagmkII_dragon_pdi_initpgm(current_prog); + } + } | + K_TYPE TKN_EQUAL K_DRAGON_PP { { stk500v2_dragon_pp_initpgm(current_prog); diff --git a/jtagmkII.c b/jtagmkII.c index 2c9b37c8..317952c7 100644 --- a/jtagmkII.c +++ b/jtagmkII.c @@ -119,6 +119,8 @@ static struct { * The following defines this programmer's use of that field. */ #define PGM_FL_IS_DW (0x0001) +#define PGM_FL_IS_PDI (0x0002) +#define PGM_FL_IS_JTAG (0x0004) static int jtagmkII_open(PROGRAMMER * pgm, char * port); @@ -1185,6 +1187,10 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) ifname = "debugWire"; if (p->flags & AVRPART_HAS_DW) ok = 1; + } else if (pgm->flag & PGM_FL_IS_PDI) { + ifname = "PDI"; + if (p->flags & AVRPART_HAS_PDI) + ok = 1; } else { ifname = "JTAG"; if (p->flags & AVRPART_HAS_JTAG) @@ -1210,7 +1216,7 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) serial_setspeed(&pgm->fd, pgm->baudrate); } } - if (!(pgm->flag & PGM_FL_IS_DW) && pgm->bitclock != 0.0) { + if ((pgm->flag & PGM_FL_IS_JTAG) && pgm->bitclock != 0.0) { if (verbose >= 2) fprintf(stderr, "%s: jtagmkII_initialize(): " "trying to set JTAG clock period to %.1f us\n", @@ -1231,10 +1237,10 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) jtagmkII_set_devdescr(pgm, p); /* - * If this is an ATxmega device, change the emulator mode from JTAG - * to JTAG_XMEGA. + * If this is an ATxmega device in JTAG mode, change the emulator + * mode from JTAG to JTAG_XMEGA. */ - if (!(pgm->flag & PGM_FL_IS_DW) && + if ((pgm->flag & PGM_FL_IS_JTAG) && (p->flags & AVRPART_HAS_PDI)) jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG_XMEGA); @@ -1256,7 +1262,7 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) if (jtagmkII_reset(pgm, 0x01) < 0) return -1; - if (!(pgm->flag & PGM_FL_IS_DW) && !(p->flags & AVRPART_HAS_PDI)) { + if ((pgm->flag & PGM_FL_IS_JTAG) && !(p->flags & AVRPART_HAS_PDI)) { strcpy(hfuse.desc, "hfuse"); if (jtagmkII_read_byte(pgm, p, &hfuse, 1, &b) < 0) return -1; @@ -1278,8 +1284,12 @@ static void jtagmkII_disable(PROGRAMMER * pgm) free(PDATA(pgm)->eeprom_pagecache); PDATA(pgm)->eeprom_pagecache = NULL; - if (!(pgm->flag & (PGM_FL_IS_DW | AVRPART_AVR32))) - (void)jtagmkII_program_disable(pgm); + /* + * jtagmkII_program_disable() doesn't do anything if the + * device is currently not in programming mode, so just + * call it unconditionally here. + */ + (void)jtagmkII_program_disable(pgm); } static void jtagmkII_enable(PROGRAMMER * pgm) @@ -1419,6 +1429,50 @@ static int jtagmkII_open_dw(PROGRAMMER * pgm, char * port) return 0; } +static int jtagmkII_open_pdi(PROGRAMMER * pgm, char * port) +{ + long baud; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_open_pdi()\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); + serial_open(port, baud, &pgm->fd); + + /* + * drain any extraneous input + */ + jtagmkII_drain(pgm, 0); + + jtagmkII_getsync(pgm, EMULATOR_MODE_PDI); + + return 0; +} + static int jtagmkII_dragon_open(PROGRAMMER * pgm, char * port) { @@ -1510,6 +1564,51 @@ static int jtagmkII_dragon_open_dw(PROGRAMMER * pgm, char * port) } +static int jtagmkII_dragon_open_pdi(PROGRAMMER * pgm, char * port) +{ + long baud; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_dragon_open_pdi()\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); + serial_open(port, baud, &pgm->fd); + + /* + * drain any extraneous input + */ + jtagmkII_drain(pgm, 0); + + jtagmkII_getsync(pgm, EMULATOR_MODE_PDI); + + return 0; +} + + void jtagmkII_close(PROGRAMMER * pgm) { int status; @@ -2308,7 +2407,7 @@ static void jtagmkII_print_parms1(PROGRAMMER * pgm, const char * p) fprintf(stderr, "%sVtarget : %.1f V\n", p, b2_to_u16(vtarget) / 1000.0); - if (!(pgm->flag & PGM_FL_IS_DW)) { + if ((pgm->flag & PGM_FL_IS_JTAG)) { if (jtagmkII_getparm(pgm, PAR_OCD_JTAG_CLK, jtag_clock) < 0) return; @@ -3438,6 +3537,7 @@ void jtagmkII_initpgm(PROGRAMMER * pgm) pgm->setup = jtagmkII_setup; pgm->teardown = jtagmkII_teardown; pgm->page_size = 256; + pgm->flag = PGM_FL_IS_JTAG; } void jtagmkII_dw_initpgm(PROGRAMMER * pgm) @@ -3471,6 +3571,37 @@ void jtagmkII_dw_initpgm(PROGRAMMER * pgm) } +void jtagmkII_pdi_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "JTAGMKII_PDI"); + + /* + * 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; + pgm->open = jtagmkII_open_pdi; + pgm->close = jtagmkII_close; + pgm->read_byte = jtagmkII_read_byte; + pgm->write_byte = jtagmkII_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtagmkII_paged_write; + pgm->paged_load = jtagmkII_paged_load; + pgm->print_parms = jtagmkII_print_parms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_PDI; +} + + void jtagmkII_dragon_initpgm(PROGRAMMER * pgm) { strcpy(pgm->type, "DRAGON_JTAG"); @@ -3500,6 +3631,7 @@ void jtagmkII_dragon_initpgm(PROGRAMMER * pgm) pgm->setup = jtagmkII_setup; pgm->teardown = jtagmkII_teardown; pgm->page_size = 256; + pgm->flag = PGM_FL_IS_JTAG; } @@ -3562,5 +3694,36 @@ void jtagmkII_avr32_initpgm(PROGRAMMER * pgm) pgm->setup = jtagmkII_setup; pgm->teardown = jtagmkII_teardown; pgm->page_size = 256; + pgm->flag = PGM_FL_IS_JTAG; +} + +void jtagmkII_dragon_pdi_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "DRAGON_PDI"); + + /* + * 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; + pgm->open = jtagmkII_dragon_open_pdi; + pgm->close = jtagmkII_close; + pgm->read_byte = jtagmkII_read_byte; + pgm->write_byte = jtagmkII_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtagmkII_paged_write; + pgm->paged_load = jtagmkII_paged_load; + pgm->print_parms = jtagmkII_print_parms; + pgm->setup = jtagmkII_setup; + pgm->teardown = jtagmkII_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_PDI; } diff --git a/jtagmkII.h b/jtagmkII.h index 2098af85..22a15f82 100644 --- a/jtagmkII.h +++ b/jtagmkII.h @@ -36,8 +36,10 @@ int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm, void jtagmkII_initpgm (PROGRAMMER * pgm); void jtagmkII_avr32_initpgm (PROGRAMMER * pgm); void jtagmkII_dw_initpgm (PROGRAMMER * pgm); +void jtagmkII_pdi_initpgm (PROGRAMMER * pgm); void jtagmkII_dragon_initpgm (PROGRAMMER * pgm); void jtagmkII_dragon_dw_initpgm (PROGRAMMER * pgm); +void jtagmkII_dragon_pdi_initpgm (PROGRAMMER * pgm); /* * These functions are referenced from stk500v2.c for JTAG ICE mkII diff --git a/jtagmkII_private.h b/jtagmkII_private.h index 40e7327c..de12c214 100644 --- a/jtagmkII_private.h +++ b/jtagmkII_private.h @@ -192,6 +192,7 @@ # define EMULATOR_MODE_JTAG 0x01 # define EMULATOR_MODE_HV 0x02 /* HVSP or PP mode of AVR Dragon */ # define EMULATOR_MODE_SPI 0x03 +# define EMULATOR_MODE_JTAG_AVR32 0x04 # define EMULATOR_MODE_JTAG_XMEGA 0x05 # define EMULATOR_MODE_PDI 0x06 #define PAR_IREG 0x04 diff --git a/lexer.l b/lexer.l index 0447d97a..faf4596f 100644 --- a/lexer.l +++ b/lexer.l @@ -139,6 +139,7 @@ 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; } +dragon_pdi { yylval=NULL; return K_DRAGON_PDI; } dragon_pp { yylval=NULL; return K_DRAGON_PP; } eecr { yylval=NULL; return K_EECR; } eeprom { yylval=NULL; return K_EEPROM; } @@ -156,6 +157,7 @@ jtagmkii { yylval=NULL; return K_JTAG_MKII; } jtagmkii_avr32 { yylval=NULL; return K_JTAG_MKII_AVR32; } jtagmkii_dw { yylval=NULL; return K_JTAG_MKII_DW; } jtagmkii_isp { yylval=NULL; return K_JTAG_MKII_ISP; } +jtagmkii_pdi { yylval=NULL; return K_JTAG_MKII_PDI; } max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; } memory { yylval=NULL; return K_MEMORY; } min_write_delay { yylval=NULL; return K_MIN_WRITE_DELAY; }