From 27d0aebbbe77c8d263252510bfa2eb891f51841b Mon Sep 17 00:00:00 2001 From: joerg_wunsch Date: Wed, 29 Nov 2017 23:09:51 +0000 Subject: [PATCH] Submitted by Jan Egil Ruud patch #9482: Add support for UPDI and AVR8X * avrdude.conf.in (xplainedpro_updi): New programmer * avrdude.conf.in (.avr8x, ATtiny1617, ATtiny817): New device family and devices * config_gram.y: add K_OCD_BASE and K_HAS_UPDI * lexer.l: (Ditto.) * doc/avrdude.texi: Document "has_updi" flag * jtag3.c: Implement UPDI * jtag3.h: (Ditto.) * jtag3_private.h: (Ditto.) * libavrdude.h: Add ocd_base value and AVRPART_HAS_UPDI flag * pgm_type.c: Add jtagice3_updi git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1398 81a1dc3b-b13d-400b-aceb-764788c761c2 --- AUTHORS | 1 + ChangeLog | 16 +++++ NEWS | 6 ++ avrdude.conf.in | 149 +++++++++++++++++++++++++++++++++++++++++++++++ config_gram.y | 18 ++++++ doc/avrdude.texi | 1 + jtag3.c | 134 ++++++++++++++++++++++++++++++++++++++---- jtag3.h | 2 + jtag3_private.h | 13 +++++ lexer.l | 2 + libavrdude.h | 2 + pgm_type.c | 1 + 12 files changed, 335 insertions(+), 10 deletions(-) diff --git a/AUTHORS b/AUTHORS index 6abbec06..d37851b0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -23,6 +23,7 @@ Contributors: Brett Hagman Rene Liebscher Jim Paris + Jan Egil Ruud For minor contributions, please see the ChangeLog files. diff --git a/ChangeLog b/ChangeLog index 7c87dd1f..a3ad54e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2017-11-29 Joerg Wunsch + + Submitted by Jan Egil Ruud + patch #9482: Add support for UPDI and AVR8X + * avrdude.conf.in (xplainedpro_updi): New programmer + * avrdude.conf.in (.avr8x, ATtiny1617, ATtiny817): New device + family and devices + * config_gram.y: add K_OCD_BASE and K_HAS_UPDI + * lexer.l: (Ditto.) + * doc/avrdude.texi: Document "has_updi" flag + * jtag3.c: Implement UPDI + * jtag3.h: (Ditto.) + * jtag3_private.h: (Ditto.) + * libavrdude.h: Add ocd_base value and AVRPART_HAS_UPDI flag + * pgm_type.c: Add jtagice3_updi + 2017-11-29 Joerg Wunsch Submitted by Jan Egil Ruud diff --git a/NEWS b/NEWS index 5a34c2c6..82005b06 100644 --- a/NEWS +++ b/NEWS @@ -12,20 +12,26 @@ Current: - libhidapi support (part of patch #8717) - use libhidapi as (optional) transport for CMSIS-DAP compliant debuggers (JTAGICE3 with firmware 3+, AtmelICE, EDBG, mEDBG) + - UPDI support added (AVR8X family) * New devices supported: - ATmega328PB + - AVR8X family, ATtiny1617, ATtiny817 * New programmers supported: - ehajo-isp (commercial version of USBtiny) + - XplainedPro in UPDI mode * Bugfixes: bug #47550: Linux GPIO broken bug #47718: "lfuse reads as" not displayed in verbose mode - SOLUTION bug #48084: Avoid compiled-in timestamp for reproducible release builds + * Patches: + patch #9482: Add support for UPDI and AVR8X + * Internals: diff --git a/avrdude.conf.in b/avrdude.conf.in index f55a3ff0..cae2a958 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -55,6 +55,7 @@ # has_jtag = ; # part has JTAG i/f # has_debugwire = ; # part has debugWire i/f # has_pdi = ; # part has PDI i/f +# has_updi = ; # part has UPDI i/f # has_tpi = ; # part has TPI i/f # devicecode = ; # deprecated, use stk500_devcode # stk500_devcode = ; # numeric @@ -1104,6 +1105,14 @@ programmer usbpid = 0x2111; ; +programmer + id = "xplainedpro_updi"; + desc = "Atmel AVR XplainedPro in UPDI mode"; + type = "jtagice3_updi"; + connection_type = usb; + usbpid = 0x2111; +; + programmer id = "xplainedmini"; desc = "Atmel AVR XplainedMini in ISP mode"; @@ -1136,6 +1145,14 @@ programmer usbpid = 0x2141; ; +programmer + id = "atmelice_updi"; + desc = "Atmel-ICE (ARM/AVR) in UPDI mode"; + type = "jtagice3_updi"; + connection_type = usb; + usbpid = 0x2141; +; + programmer id = "atmelice_dw"; desc = "Atmel-ICE (ARM/AVR) in debugWIRE mode"; @@ -14989,4 +15006,136 @@ part ; ; +#------------------------------------------------------------ +# AVR8X family common values +#------------------------------------------------------------ +part + id = ".avr8x"; + desc = "AVR8X family common values"; + has_updi = yes; + nvm_base = 0x1000; + ocd_base = 0x0F80; + + memory "signature" + size = 3; + offset = 0x1100; + ; + + memory "userrow" + size = 0x20; + offset = 0x1300; + page_size = 0x20; + readsize = 0x100; + ; + + memory "prodsig" + size = 0x3D; + offset = 0x1103; + page_size = 0x3D; + readsize = 0x3D; + ; + + memory "fuses" + size = 9; + offset = 0x1280; + ; + + memory "fuse0" + size = 1; + offset = 0x1280; + ; + + memory "fuse1" + size = 1; + offset = 0x1281; + ; + + memory "fuse2" + size = 1; + offset = 0x1282; + ; + + memory "fuse4" + size = 1; + offset = 0x1284; + ; + + memory "fuse5" + size = 1; + offset = 0x1285; + ; + + memory "fuse6" + size = 1; + offset = 0x1286; + ; + + memory "fuse7" + size = 1; + offset = 0x1287; + ; + + memory "fuse8" + size = 1; + offset = 0x1288; + ; + + memory "lock" + size = 1; + offset = 0x128a; + ; + + memory "data" + # SRAM, only used to supply the offset + offset = 0x1000000; + ; +; + +#------------------------------------------------------------ +# ATtiny1617 +#------------------------------------------------------------ + +part parent ".avr8x" + id = "tn1617"; + desc = "ATtiny1617"; + signature = 0x1e 0x94 0x20; + + memory "eeprom" + size = 0x0100; + offset = 0x1400; + page_size = 0x20; + readsize = 0x100; + ; + + memory "flash" + size = 0x4000; + offset = 0x8000; + page_size = 0x40; + readsize = 0x100; + ; +; + +#------------------------------------------------------------ +# ATtiny817 +#------------------------------------------------------------ + +part parent ".avr8x" + id = "tn817"; + desc = "ATtiny817"; + signature = 0x1e 0x93 0x20; + + memory "eeprom" + size = 0x0100; + offset = 0x1400; + page_size = 0x20; + readsize = 0x100; + ; + + memory "flash" + size = 0x2000; + offset = 0x8000; + page_size = 0x40; + readsize = 0x100; + ; +; diff --git a/config_gram.y b/config_gram.y index 0aa95a8e..21dccb0b 100644 --- a/config_gram.y +++ b/config_gram.y @@ -96,6 +96,7 @@ static int pin_name; %token K_MOSI %token K_NUM_PAGES %token K_NVM_BASE +%token K_OCD_BASE %token K_OCDREV %token K_OFFSET %token K_PAGEL @@ -183,6 +184,7 @@ static int pin_name; %token K_HAS_JTAG /* MCU has JTAG i/f. */ %token K_HAS_DW /* MCU has debugWire i/f. */ %token K_HAS_PDI /* MCU has PDI i/f rather than ISP (ATxmega). */ +%token K_HAS_UPDI /* MCU has UPDI i/f (AVR8X). */ %token K_HAS_TPI /* MCU has TPI i/f rather than ISP (ATtiny4/5/9/10). */ %token K_IDR /* address of OCD register in IO space */ %token K_IS_AT90S1200 /* chip is an AT90S1200 (needs special treatment) */ @@ -1062,6 +1064,16 @@ part_parm : free_token($3); } | + K_HAS_UPDI TKN_EQUAL yesno + { + if ($3->primary == K_YES) + current_part->flags |= AVRPART_HAS_UPDI; + else if ($3->primary == K_NO) + current_part->flags &= ~AVRPART_HAS_UPDI; + + free_token($3); + } | + K_HAS_TPI TKN_EQUAL yesno { if ($3->primary == K_YES) @@ -1148,6 +1160,12 @@ part_parm : free_token($3); } | + K_OCD_BASE TKN_EQUAL TKN_NUMBER + { + current_part->ocd_base = $3->value.number; + free_token($3); + } | + K_OCDREV TKN_EQUAL TKN_NUMBER { current_part->ocdrev = $3->value.number; diff --git a/doc/avrdude.texi b/doc/avrdude.texi index 6941389d..161c6473 100644 --- a/doc/avrdude.texi +++ b/doc/avrdude.texi @@ -1440,6 +1440,7 @@ part has_jtag = ; # part has JTAG i/f has_debugwire = ; # part has debugWire i/f has_pdi = ; # part has PDI i/f + has_updi = ; # part has UPDI i/f has_tpi = ; # part has TPI i/f devicecode = ; # numeric stk500_devcode = ; # numeric diff --git a/jtag3.c b/jtag3.c index 3084c320..4cda747c 100644 --- a/jtag3.c +++ b/jtag3.c @@ -84,6 +84,7 @@ struct pdata #define PGM_FL_IS_PDI (0x0002) #define PGM_FL_IS_JTAG (0x0004) #define PGM_FL_IS_EDBG (0x0008) +#define PGM_FL_IS_UPDI (0x0010) static int jtag3_open(PROGRAMMER * pgm, char * port); static int jtag3_edbg_prepare(PROGRAMMER * pgm); @@ -1014,6 +1015,10 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p) ifname = "PDI"; if (p->flags & AVRPART_HAS_PDI) conn = PARM3_CONN_PDI; + } else if (pgm->flag & PGM_FL_IS_UPDI) { + ifname = "UPDI"; + if (p->flags & AVRPART_HAS_UPDI) + conn = PARM3_CONN_UPDI; } else { ifname = "JTAG"; if (p->flags & AVRPART_HAS_JTAG) @@ -1028,6 +1033,8 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p) if (p->flags & AVRPART_HAS_PDI) parm[0] = PARM3_ARCH_XMEGA; + else if (p->flags & AVRPART_HAS_UPDI) + parm[0] = PARM3_ARCH_UPDI; else if (p->flags & AVRPART_HAS_DW) parm[0] = PARM3_ARCH_TINY; else @@ -1043,7 +1050,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p) if (jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CONNECTION, parm, 1) < 0) return -1; - if (conn == PARM3_CONN_PDI) + if (conn == PARM3_CONN_PDI || conn == PARM3_CONN_UPDI) PDATA(pgm)->set_sck = jtag3_set_sck_xmega_pdi; else if (conn == PARM3_CONN_JTAG) { if (p->flags & AVRPART_HAS_PDI) @@ -1119,6 +1126,50 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p) if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&xd, sizeof xd) < 0) return -1; } + else if ((p->flags & AVRPART_HAS_UPDI)) + { + struct updi_device_desc xd; + LNODEID ln; + AVRMEM *m; + + u16_to_b2(xd.nvm_base_addr, p->nvm_base); + u16_to_b2(xd.ocd_base_addr, p->ocd_base); + + for (ln = lfirst(p->mem); ln; ln = lnext(ln)) + { + m = ldata(ln); + if (strcmp(m->desc, "flash") == 0) + { + u16_to_b2(xd.prog_base, m->offset); + + if (m->readsize != 0 && m->readsize < m->page_size) + PDATA(pgm)->flash_pagesize = m->readsize; + else + PDATA(pgm)->flash_pagesize = m->page_size; + xd.flash_page_size = m->page_size; + } + else if (strcmp(m->desc, "eeprom") == 0) + { + PDATA(pgm)->eeprom_pagesize = m->page_size; + xd.eeprom_page_size = m->page_size; + } + } + + avrdude_message(MSG_NOTICE2, "UPDI SET: \n\t" + "xd->prog_base=%x %x\n\t" + "xd->flash_page_size=%x\n\t" + "xd->eeprom_page_size=%x\n\t" + "xd->nvmctrl=%x %x\n\t" + "xd->ocd=%x %x\n", + xd.prog_base[0], xd.prog_base[1], + xd.flash_page_size, + xd.eeprom_page_size, + xd.nvm_base_addr[0], xd.nvm_base_addr[1], + xd.ocd_base_addr[0], xd.ocd_base_addr[1]); + + if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&xd, sizeof xd) < 0) + return -1; + } else { struct mega_device_desc md; @@ -1443,6 +1494,18 @@ static int jtag3_open_pdi(PROGRAMMER * pgm, char * port) return 0; } +static int jtag3_open_updi(PROGRAMMER * pgm, char * port) +{ + avrdude_message(MSG_NOTICE2, "%s: jtag3_open_updi()\n", progname); + + if (jtag3_open_common(pgm, port) < 0) + return -1; + + if (jtag3_getsync(pgm, PARM3_CONN_UPDI) < 0) + return -1; + + return 0; +} void jtag3_close(PROGRAMMER * pgm) { @@ -1571,7 +1634,7 @@ static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[3] = MTYPE_USERSIG; } else if ( ( strcmp(m->desc, "boot") == 0 ) ) { cmd[3] = MTYPE_BOOT_FLASH; - } else if ( p->flags & AVRPART_HAS_PDI ) { + } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) { cmd[3] = MTYPE_FLASH; } else { cmd[3] = MTYPE_SPM; @@ -1648,7 +1711,7 @@ static int jtag3_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, /* dynamically decide between flash/boot memtype */ dynamic_memtype = 1; } else if (strcmp(m->desc, "eeprom") == 0) { - cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE; + cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE; if (pgm->flag & PGM_FL_IS_DW) return -1; } else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) { @@ -1657,7 +1720,7 @@ static int jtag3_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[3] = MTYPE_USERSIG; } else if ( ( strcmp(m->desc, "boot") == 0 ) ) { cmd[3] = MTYPE_BOOT_FLASH; - } else if ( p->flags & AVRPART_HAS_PDI ) { + } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) { cmd[3] = MTYPE_FLASH; } else { cmd[3] = MTYPE_SPM; @@ -1716,7 +1779,9 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, cmd[1] = CMD3_READ_MEMORY; cmd[2] = 0; - cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE; + cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE; + if (p->flags & AVRPART_HAS_UPDI) + addr += mem->offset; if (strcmp(mem->desc, "flash") == 0 || strcmp(mem->desc, "application") == 0 || strcmp(mem->desc, "apptable") == 0 || @@ -1727,7 +1792,7 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, paddr_ptr = &PDATA(pgm)->flash_pageaddr; cache_ptr = PDATA(pgm)->flash_pagecache; } else if (strcmp(mem->desc, "eeprom") == 0) { - if ( (pgm->flag & PGM_FL_IS_DW) || ( p->flags & AVRPART_HAS_PDI ) ) { + if ( (pgm->flag & PGM_FL_IS_DW) || ( p->flags & AVRPART_HAS_PDI ) || ( p->flags & AVRPART_HAS_UPDI ) ) { cmd[3] = MTYPE_EEPROM; } else { cmd[3] = MTYPE_EEPROM_PAGE; @@ -1757,7 +1822,8 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsupp = 1; } else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) { cmd[3] = MTYPE_FUSE_BITS; - addr = mem->offset & 7; + if (!(p->flags & AVRPART_HAS_UPDI)) + addr = mem->offset & 7; } else if (strcmp(mem->desc, "usersig") == 0) { cmd[3] = MTYPE_USERSIG; } else if (strcmp(mem->desc, "prodsig") == 0) { @@ -1778,7 +1844,11 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, * harm for other connection types either. */ u32_to_b4(cmd + 8, 3); - u32_to_b4(cmd + 4, 0); + u32_to_b4(cmd + 4, mem->offset); + + if (p->flags & AVRPART_HAS_UPDI){ + addr -= mem->offset; + } if (addr == 0) { if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0) @@ -1867,7 +1937,9 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, cmd[0] = SCOPE_AVR; cmd[1] = CMD3_WRITE_MEMORY; cmd[2] = 0; - cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_SPM; + cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_SPM; + if (p->flags & AVRPART_HAS_UPDI) + addr += mem->offset; if (strcmp(mem->desc, "flash") == 0) { cache_ptr = PDATA(pgm)->flash_pagecache; pagesize = PDATA(pgm)->flash_pagesize; @@ -1899,9 +1971,12 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsupp = 1; } else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) { cmd[3] = MTYPE_FUSE_BITS; - addr = mem->offset & 7; + if (!(p->flags & AVRPART_HAS_UPDI)) + addr = mem->offset & 7; } else if (strcmp(mem->desc, "usersig") == 0) { cmd[3] = MTYPE_USERSIG; + } else if (strcmp(mem->desc, "userrow") == 0) { + cmd[3] = MTYPE_USERSIG; } else if (strcmp(mem->desc, "prodsig") == 0) { cmd[3] = MTYPE_PRODSIG; } else if (strncmp(mem->desc, "lock", 4) == 0) { @@ -2179,6 +2254,11 @@ static unsigned int jtag3_memaddr(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, uns /* * Non-Xmega device. */ + if (p->flags & AVRPART_HAS_UPDI) { + if (strcmp(m->desc, "flash") != 0) { + addr += m->offset; + } + } return addr; } @@ -2284,3 +2364,37 @@ void jtag3_pdi_initpgm(PROGRAMMER * pgm) pgm->flag = PGM_FL_IS_PDI; } +const char jtag3_updi_desc[] = "Atmel JTAGICE3 in UPDI mode"; + +void jtag3_updi_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "JTAGICE3_UPDI"); + + /* + * mandatory functions + */ + pgm->initialize = jtag3_initialize; + pgm->display = jtag3_display; + pgm->enable = jtag3_enable; + pgm->disable = jtag3_disable; + pgm->program_enable = jtag3_program_enable_dummy; + pgm->chip_erase = jtag3_chip_erase; + pgm->open = jtag3_open_updi; + pgm->close = jtag3_close; + pgm->read_byte = jtag3_read_byte; + pgm->write_byte = jtag3_write_byte; + + /* + * optional functions + */ + pgm->paged_write = jtag3_paged_write; + pgm->paged_load = jtag3_paged_load; + pgm->page_erase = jtag3_page_erase; + pgm->print_parms = jtag3_print_parms; + pgm->set_sck_period = jtag3_set_sck_period; + pgm->setup = jtag3_setup; + pgm->teardown = jtag3_teardown; + pgm->page_size = 256; + pgm->flag = PGM_FL_IS_UPDI; +} + diff --git a/jtag3.h b/jtag3.h index fef3be01..4e49c586 100644 --- a/jtag3.h +++ b/jtag3.h @@ -41,9 +41,11 @@ int jtag3_command(PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen, extern const char jtag3_desc[]; extern const char jtag3_dw_desc[]; extern const char jtag3_pdi_desc[]; +extern const char jtag3_updi_desc[]; void jtag3_initpgm (PROGRAMMER * pgm); void jtag3_dw_initpgm (PROGRAMMER * pgm); void jtag3_pdi_initpgm (PROGRAMMER * pgm); +void jtag3_updi_initpgm (PROGRAMMER * pgm); /* * These functions are referenced from stk500v2.c for JTAGICE3 in diff --git a/jtag3_private.h b/jtag3_private.h index 8ee37505..80ffb2ab 100644 --- a/jtag3_private.h +++ b/jtag3_private.h @@ -109,6 +109,7 @@ #define CMD3_GET_PARAMETER 0x02 #define CMD3_SIGN_ON 0x10 #define CMD3_SIGN_OFF 0x11 /* takes one parameter? */ +#define CMD3_GET_ID 0x12 #define CMD3_START_DW_DEBUG 0x13 #define CMD3_MONCON_DISABLE 0x17 @@ -165,6 +166,7 @@ #define MTYPE_EEPROM_XMEGA 0xc4 /* xmega EEPROM in debug mode - undocumented in AVR067 */ #define MTYPE_USERSIG 0xc5 /* xmega user signature - undocumented in AVR067 */ #define MTYPE_PRODSIG 0xc6 /* xmega production signature - undocumented in AVR067 */ +#define MTYPE_SIB 0xD3 /* AVR8X System Information Block */ /* * Parameters are divided into sections, where the section number @@ -189,6 +191,7 @@ # define PARM3_ARCH_TINY 1 /* also small megaAVR with ISP/DW only */ # define PARM3_ARCH_MEGA 2 # define PARM3_ARCH_XMEGA 3 +# define PARM3_ARCH_UPDI 5 /* AVR devices with UPDI i/f */ #define PARM3_SESS_PURPOSE 0x01 /* section 0, AVR scope, 1 byte */ # define PARM3_SESS_PROGRAMMING 1 @@ -199,6 +202,7 @@ # define PARM3_CONN_JTAG 4 # define PARM3_CONN_DW 5 # define PARM3_CONN_PDI 6 +# define PARM3_CONN_UPDI 8 #define PARM3_JTAGCHAIN 0x01 /* JTAG chain info, AVR scope (units @@ -316,4 +320,13 @@ struct xmega_device_desc { unsigned char nvm_base_addr[2]; // IO space base address of NVM controller unsigned char mcu_base_addr[2]; // IO space base address of MCU control }; + +/* UPDI device descriptor */ +struct updi_device_desc { + unsigned char prog_base[2]; + unsigned char flash_page_size; + unsigned char eeprom_page_size; + unsigned char nvm_base_addr[2]; + unsigned char ocd_base_addr[2]; +}; #endif /* JTAG3_PRIVATE_EXPORTED */ diff --git a/lexer.l b/lexer.l index 34af33d6..ab7feb70 100644 --- a/lexer.l +++ b/lexer.l @@ -152,6 +152,7 @@ has_debugwire { yylval=NULL; return K_HAS_DW; } has_jtag { yylval=NULL; return K_HAS_JTAG; } has_pdi { yylval=NULL; return K_HAS_PDI; } has_tpi { yylval=NULL; return K_HAS_TPI; } +has_updi { yylval=NULL; return K_HAS_UPDI; } hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; } hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; } hvsp_controlstack { yylval=NULL; return K_HVSP_CONTROLSTACK; } @@ -176,6 +177,7 @@ no { yylval=new_token(K_NO); return K_NO; } num_banks { yylval=NULL; return K_NUM_PAGES; } num_pages { yylval=NULL; return K_NUM_PAGES; } nvm_base { yylval=NULL; return K_NVM_BASE; } +ocd_base { yylval=NULL; return K_OCD_BASE; } ocdrev { yylval=NULL; return K_OCDREV; } offset { yylval=NULL; return K_OFFSET; } page_size { yylval=NULL; return K_PAGE_SIZE; } diff --git a/libavrdude.h b/libavrdude.h index d5f32e46..5636f20c 100644 --- a/libavrdude.h +++ b/libavrdude.h @@ -199,6 +199,7 @@ typedef struct opcode { #define AVRPART_WRITE 0x0400 /* at least one write operation specified */ #define AVRPART_HAS_TPI 0x0800 /* part has TPI i/f rather than ISP (ATtiny4/5/9/10) */ #define AVRPART_IS_AT90S1200 0x1000 /* part is an AT90S1200 (needs special treatment) */ +#define AVRPART_HAS_UPDI 0x2000 /* part has UPDI i/f (AVR8X) */ #define AVR_DESCLEN 64 #define AVR_IDLEN 32 @@ -264,6 +265,7 @@ typedef struct avrpart { unsigned short eecr; /* JTAC ICE mkII XML file parameter */ unsigned int mcu_base; /* Base address of MCU control block in ATxmega devices */ unsigned int nvm_base; /* Base address of NVM controller in ATxmega devices */ + unsigned int ocd_base; /* Base address of OCD module in AVR8X/UPDI devices */ int ocdrev; /* OCD revision (JTAGICE3 parameter, from AS6 XML files) */ OPCODE * op[AVR_OP_MAX]; /* opcodes */ diff --git a/pgm_type.c b/pgm_type.c index 7724987f..9b6bdccc 100644 --- a/pgm_type.c +++ b/pgm_type.c @@ -77,6 +77,7 @@ const PROGRAMMER_TYPE programmers_types[] = { {"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc}, {"jtagice3", jtag3_initpgm, jtag3_desc}, {"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc}, + {"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc}, {"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc}, {"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc}, {"linuxgpio", linuxgpio_initpgm, linuxgpio_desc},