diff --git a/src/avrdude.1 b/src/avrdude.1 index c4fc850f..b312fff5 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -180,7 +180,7 @@ has a revision 1 hardware and firmware version of at least 5.37 (decimal). For ATxmega devices, the JTAGICE3 is supported in PDI mode. .Pp Atmel-ICE (ARM/AVR) is supported in all modes (JTAG, PDI for Xmega, debugWIRE, -ISP). +ISP, UPDI). .Pp Atmel's XplainedPro boards, using the EDBG protocol (CMSIS-DAP compatible), are supported using the "jtag3" programmer type. @@ -226,7 +226,7 @@ thus the name SerialUPDI programmer implementation is based on Microchip's .Em pymcuprog Li https://github.com/microchip-pic-avr-tools/pymcuprog utility, but it also contains some performance improvements included in -Spence Kohde's +Spence Konde's .Em DxCore Arduino core .Li https://github.com/SpenceKonde/DxCore . @@ -978,9 +978,13 @@ versions of the bootloader. .It Ar JTAG ICE mkII .It Ar JTAGICE3 .It Ar Atmel-ICE +.It Ar Power Debugger +.It Ar PICkit 4 +.It Ar MPLAB SNAP .It Ar AVR Dragon -When using the JTAG ICE mkII, JTAGICE3, Atmel-ICE or AVR Dragon in JTAG mode, the -following extended parameter is accepted: +When using the JTAG ICE mkII, JTAGICE3, Atmel-ICE, PICkit 4, MPLAB SNAP, +Power Debugger or AVR Dragon in JTAG mode, the following extended parameter +is accepted: .Bl -tag -offset indent -width indent .It Ar jtagchain=UB,UA,BB,BA Setup the JTAG scan chain for @@ -995,6 +999,14 @@ bits after the target AVR, respectively. Each AVR unit within the chain shifts by 4 bits. Other JTAG units might require a different bit shift count. .El +.Pp +The PICkit 4 and the Power Debugger also supports high-voltage UPDI programming. +This is used to enable a UPDI pin that has previously been set to RESET or +GPIO mode. High-voltage UPDI can be utilized by using an extended parameter: +.Bl -tag -offset indent -width indent +.It Ar hvupdi +Enable high-voltage UPDI initialization for targets that supports this. +.El .It Ar AVR910 .Bl -tag -offset indent -width indent .It Ar devcode=VALUE diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 5e07b26c..8fc67080 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -40,6 +40,7 @@ # usbvendor = ; # USB Vendor Name # usbproduct = ; # USB Product Name # usbsn = ; # USB Serial Number +# hvupdi_support = [, , ... ] ; # UPDI HV Variants Support # # To invert a bit, use = ~ , the spaces are important. # For a pin list all pins must be inverted. @@ -631,6 +632,7 @@ programmer desc = "SerialUPDI"; type = "serialupdi"; connection_type = serial; + hvupdi_support = 1; ; programmer @@ -1178,6 +1180,7 @@ programmer type = "jtagice3_updi"; connection_type = usb; usbpid = 0x2110, 0x2140; + hvupdi_support = 1; ; programmer @@ -1210,6 +1213,7 @@ programmer type = "jtagice3_updi"; connection_type = usb; usbpid = 0x2111; + hvupdi_support = 1; ; programmer @@ -1234,6 +1238,7 @@ programmer type = "jtagice3_updi"; connection_type = usb; usbpid = 0x2145; + hvupdi_support = 1; ; programmer @@ -1258,6 +1263,7 @@ programmer type = "jtagice3_updi"; connection_type = usb; usbpid = 0x2141; + hvupdi_support = 1; ; programmer @@ -1298,6 +1304,7 @@ programmer type = "jtagice3_updi"; connection_type = usb; usbpid = 0x2144; + hvupdi_support = 0, 1; ; programmer @@ -1322,6 +1329,7 @@ programmer type = "jtagice3_updi"; connection_type = usb; usbpid = 0x2177, 0x2178, 0x2179; + hvupdi_support = 0, 1, 2; ; programmer @@ -1346,6 +1354,7 @@ programmer type = "jtagice3_updi"; connection_type = usb; usbpid = 0x217F, 0x2180, 0x2181; + hvupdi_support = 1; ; programmer @@ -1370,6 +1379,7 @@ programmer type = "jtagice3_updi"; connection_type = usb; usbpid = 0x2175; + hvupdi_support = 1; ; programmer @@ -1739,6 +1749,7 @@ programmer type = "jtagmkii_pdi"; connection_type = serial; baudrate = 115200; + hvupdi_support = 1; ; # @@ -17124,13 +17135,15 @@ part # AVR8X tiny family common values #------------------------------------------------------------ -part parent ".avr8x" - id = ".avr8x_tiny"; - desc = "AVR8X tiny family common values"; - family_id = "tinyAVR"; +part parent ".avr8x" + id = ".avr8x_tiny"; + desc = "AVR8X tiny family common values"; + family_id = "tinyAVR"; + # Shared UPDI pin, HV on UPDI pin + hvupdi_variant = 0; memory "userrow" - size = 0x20; + size = 0x20; offset = 0x1300; page_size = 0x20; readsize = 0x100; @@ -17145,13 +17158,15 @@ part parent ".avr8x" # AVR8X mega family common values #------------------------------------------------------------ -part parent ".avr8x" - id = ".avr8x_mega"; - desc = "AVR8X mega family common values"; - family_id = "megaAVR"; +part parent ".avr8x" + id = ".avr8x_mega"; + desc = "AVR8X mega family common values"; + family_id = "megaAVR"; + # Dedicated UPDI pin, no HV + hvupdi_variant = 1; memory "userrow" - size = 0x40; + size = 0x40; offset = 0x1300; page_size = 0x40; readsize = 0x100; @@ -18250,11 +18265,13 @@ part parent ".avr8x_mega" #------------------------------------------------------------ part - id = ".avrdx"; - desc = "AVR-Dx family common values"; - has_updi = yes; - nvm_base = 0x1000; - ocd_base = 0x0F80; + id = ".avrdx"; + desc = "AVR-Dx family common values"; + has_updi = yes; + nvm_base = 0x1000; + ocd_base = 0x0F80; + # Dedicated UPDI pin, no HV + hvupdi_variant = 1; memory "signature" size = 3; @@ -18936,6 +18953,7 @@ part parent ".avrdx" id = "avr16dd14"; desc = "AVR16DD14"; signature = 0x1E 0x94 0x34; + hvupdi_variant = 2; memory "flash" size = 0x4000; @@ -18960,6 +18978,7 @@ part parent ".avrdx" id = "avr16dd20"; desc = "AVR16DD20"; signature = 0x1E 0x94 0x33; + hvupdi_variant = 2; memory "flash" size = 0x4000; @@ -18984,6 +19003,7 @@ part parent ".avrdx" id = "avr16dd28"; desc = "AVR16DD28"; signature = 0x1E 0x94 0x32; + hvupdi_variant = 2; memory "flash" size = 0x4000; @@ -19008,6 +19028,7 @@ part parent ".avrdx" id = "avr16dd32"; desc = "AVR16DD32"; signature = 0x1E 0x94 0x31; + hvupdi_variant = 2; memory "flash" size = 0x4000; @@ -19032,6 +19053,7 @@ part parent ".avrdx" id = "avr32dd14"; desc = "AVR32DD14"; signature = 0x1E 0x95 0x3B; + hvupdi_variant = 2; memory "flash" size = 0x8000; @@ -19056,6 +19078,7 @@ part parent ".avrdx" id = "avr32dd20"; desc = "AVR32DD20"; signature = 0x1E 0x95 0x3A; + hvupdi_variant = 2; memory "flash" size = 0x8000; @@ -19080,6 +19103,7 @@ part parent ".avrdx" id = "avr32dd28"; desc = "AVR32DD28"; signature = 0x1E 0x95 0x39; + hvupdi_variant = 2; memory "flash" size = 0x8000; @@ -19104,6 +19128,7 @@ part parent ".avrdx" id = "avr32dd32"; desc = "AVR32DD32"; signature = 0x1E 0x95 0x38; + hvupdi_variant = 2; memory "flash" size = 0x8000; @@ -19128,6 +19153,7 @@ part parent ".avrdx" id = "avr64dd14"; desc = "AVR64DD14"; signature = 0x1E 0x96 0x1D; + hvupdi_variant = 2; memory "flash" size = 0x10000; @@ -19152,6 +19178,7 @@ part parent ".avrdx" id = "avr64dd20"; desc = "AVR64DD20"; signature = 0x1E 0x96 0x1C; + hvupdi_variant = 2; memory "flash" size = 0x10000; @@ -19176,6 +19203,7 @@ part parent ".avrdx" id = "avr64dd28"; desc = "AVR64DD28"; signature = 0x1E 0x96 0x1B; + hvupdi_variant = 2; memory "flash" size = 0x10000; @@ -19200,6 +19228,7 @@ part parent ".avrdx" id = "avr64dd32"; desc = "AVR64DD32"; signature = 0x1E 0x96 0x1A; + hvupdi_variant = 2; memory "flash" size = 0x10000; @@ -19220,9 +19249,11 @@ part parent ".avrdx" # AVR-Ex family common values #------------------------------------------------------------ -part parent ".avrdx" - id = ".avrex"; - desc = "AVR-Ex family common values"; +part parent ".avrdx" + id = ".avrex"; + desc = "AVR-Ex family common values"; + # Shared UPDI pin, HV on _RESET + hvupdi_variant = 2; memory "userrow" size = 0x40; diff --git a/src/avrpart.c b/src/avrpart.c index fdff0f78..d862ae24 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -573,6 +573,7 @@ AVRPART * avr_new_part(void) memset(p->signature, 0xFF, 3); p->ctl_stack_type = CTL_STACK_NONE; p->ocdrev = -1; + p->hvupdi_variant = -1; p->mem = lcreat(NULL, 0); p->mem_alias = lcreat(NULL, 0); diff --git a/src/config_gram.y b/src/config_gram.y index 20830ca7..d8c51ca2 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -82,6 +82,8 @@ static int pin_name; %token K_DEFAULT_SPI %token K_DESC %token K_FAMILY_ID +%token K_HVUPDI_SUPPORT +%token K_HVUPDI_VARIANT %token K_DEVICECODE %token K_STK500_DEVCODE %token K_AVR910_DEVCODE @@ -483,7 +485,8 @@ prog_parm : current_prog->baudrate = $3->value.number; free_token($3); } - } + } | + prog_parm_updi ; prog_parm_type: @@ -585,6 +588,38 @@ usb_pid_list: } ; +prog_parm_updi: + K_HVUPDI_SUPPORT TKN_EQUAL hvupdi_support_list +; + +hvupdi_support_list: + TKN_NUMBER { + { + /* overwrite list entries, so clear the existing entries */ + ldestroy_cb(current_prog->hvupdi_support, free); + current_prog->hvupdi_support = lcreat(NULL, 0); + } + { + int *ip = malloc(sizeof(int)); + if (ip) { + *ip = $1->value.number; + ladd(current_prog->hvupdi_support, ip); + } + free_token($1); + } + } | + hvupdi_support_list TKN_COMMA TKN_NUMBER { + { + int *ip = malloc(sizeof(int)); + if (ip) { + *ip = $3->value.number; + ladd(current_prog->hvupdi_support, ip); + } + free_token($3); + } + } +; + pin_number_non_empty: TKN_NUMBER { if(0 != assign_pin(pin_name, $1, 0)) YYABORT; } | @@ -685,6 +720,12 @@ part_parm : free_token($3); } | + K_HVUPDI_VARIANT TKN_EQUAL TKN_NUMBER + { + current_part->hvupdi_variant = $3->value.number; + free_token($3); + } | + K_DEVICECODE TKN_EQUAL TKN_NUMBER { { yyerror("devicecode is deprecated, use " diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index d99b0a85..83b6fb3f 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -250,7 +250,8 @@ See below for the limitations of debugWire. For ATxmega devices, the JTAG ICE mkII/3 is supported in PDI mode, provided it has a revision 1 hardware and firmware version of at least 5.37 (decimal). -The Atmel-ICE (ARM/AVR) is supported (JTAG, PDI for Xmega, debugWIRE, ISP modes). +The Atmel-ICE (ARM/AVR) is supported (JTAG, PDI for Xmega, debugWIRE, ISP, +UPDI). Atmel's XplainedPro boards, using EDBG protocol (CMSIS-DAP compliant), are supported by the ``jtag3'' programmer type. @@ -854,10 +855,15 @@ accepting extended parameters. @table @code @item JTAG ICE mkII/3 +@itemx Atmel-ICE +@itemx PICkit 4 +@itemx MPLAB SNAP +@itemx Power Debugger @itemx AVR Dragon -When using the JTAG ICE mkII/3 or AVR Dragon in JTAG mode, the -following extended parameter is accepted: +When using the JTAG ICE mkII, JTAGICE3, Atmel-ICE, PICkit 4, MPLAB SNAP, +Power Debugger or AVR Dragon in JTAG mode, the following extended parameter +is accepted: @table @code @item @samp{jtagchain=UB,UA,BB,BA} Setup the JTAG scan chain for @var{UB} units before, @var{UA} units @@ -867,6 +873,14 @@ Each AVR unit within the chain shifts by 4 bits. Other JTAG units might require a different bit shift count. @end table +The PICkit 4 and the Power Debugger also supports high-voltage UPDI programming. +This is used to enable a UPDI pin that has previously been set to RESET or +GPIO mode. High-voltage UPDI can be utilized by using an extended parameter: +@table @code +@item @samp{hvupdi} +Enable high-voltage UPDI initialization for targets that supports this. +@end table + @cindex @code{-x} AVR910 @item AVR910 diff --git a/src/jtag3.c b/src/jtag3.c index 6a4004f3..5612d0ed 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -71,6 +71,9 @@ struct pdata /* Start address of Xmega boot area */ unsigned long boot_start; + /* Flag for triggering HV UPDI */ + bool use_hvupdi; + /* Function to set the appropriate clock parameter */ int (*set_sck)(PROGRAMMER *, unsigned char *); }; @@ -1204,6 +1207,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p) u16_to_b2(xd.nvm_base_addr, p->nvm_base); u16_to_b2(xd.ocd_base_addr, p->ocd_base); + xd.hvupdi_variant = p->hvupdi_variant; for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { @@ -1258,6 +1262,29 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p) } } + // Generate UPDI high-voltage pulse if user asks for it and hardware supports it + LNODEID support; + if (p->flags & AVRPART_HAS_UPDI && + PDATA(pgm)->use_hvupdi == true && + p->hvupdi_variant != HV_UPDI_VARIANT_1) { + parm[0] = PARM3_UPDI_HV_NONE; + for (support = lfirst(pgm->hvupdi_support); support != NULL; support = lnext(support)) { + if(*(int *) ldata(support) == p->hvupdi_variant) { + avrdude_message(MSG_NOTICE, "%s: Sending HV pulse to targets %s pin\n", + progname, p->hvupdi_variant == HV_UPDI_VARIANT_0 ? "UPDI" : "RESET"); + parm[0] = PARM3_UPDI_HV_SIMPLE_PULSE; + break; + } + if (parm[0] == PARM3_UPDI_HV_NONE) { + avrdude_message(MSG_INFO, "%s: %s does not support sending HV pulse to target %s\n", + progname, pgm->desc, p->desc); + return -1; + } + } + if (jtag3_setparm(pgm, SCOPE_AVR, 3, PARM3_OPT_12V_UPDI_ENABLE, parm, 1) < 0) + return -1; + } + u16_to_b2(xd.default_min_div1_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV1_VOLTAGE_MV); u16_to_b2(xd.default_min_div2_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV2_VOLTAGE_MV); u16_to_b2(xd.default_min_div4_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV4_VOLTAGE_MV); @@ -1483,6 +1510,12 @@ static int jtag3_parseextparms(PROGRAMMER * pgm, LISTID extparms) continue; } + else if ((strcmp(extended_param, "hvupdi") == 0) && + (lsize(pgm->hvupdi_support) > 1)) { + PDATA(pgm)->use_hvupdi = true; + continue; + } + avrdude_message(MSG_INFO, "%s: jtag3_parseextparms(): invalid extended parameter '%s'\n", progname, extended_param); rv = -1; @@ -1630,6 +1663,12 @@ static int jtag3_open_updi(PROGRAMMER * pgm, char * port) { avrdude_message(MSG_NOTICE2, "%s: jtag3_open_updi()\n", progname); + LNODEID ln; + avrdude_message(MSG_NOTICE2, "%s: HV UPDI support:", progname); + for (ln = lfirst(pgm->hvupdi_support); ln; ln = lnext(ln)) + avrdude_message(MSG_NOTICE2, " %d", *(int *) ldata(ln)); + avrdude_message(MSG_NOTICE2, "\n", progname); + if (jtag3_open_common(pgm, port) < 0) return -1; @@ -2606,6 +2645,7 @@ void jtag3_updi_initpgm(PROGRAMMER * pgm) * mandatory functions */ pgm->initialize = jtag3_initialize; + pgm->parseextparams = jtag3_parseextparms; pgm->display = jtag3_display; pgm->enable = jtag3_enable; pgm->disable = jtag3_disable; diff --git a/src/jtag3_private.h b/src/jtag3_private.h index 7d0cbb74..ddc7e2e3 100644 --- a/src/jtag3_private.h +++ b/src/jtag3_private.h @@ -237,6 +237,14 @@ #define PARM3_OPT_12V_UPDI_ENABLE 0x06 #define PARM3_OPT_CHIP_ERASE_TO_ENTER 0x07 +/* + * UPDI high-voltage enable modes + */ +#define PARM3_UPDI_HV_NONE 0x00 /* Do not use high-voltage */ +#define PARM3_UPDI_HV_SIMPLE_PULSE 0x01 /* Issue a single high-voltage pulse immediately*/ +#define PARM3_UPDI_HV_AUTO_POWER_TOGGLE 0x02 /* Toggle power automatically and then apply a high-voltage pulse */ +#define PARM3_UPDI_HV_USER_POWER_TOGGLE 0x03 /* The user toggles power, and the tool applies a high-voltage pulse on power-up */ + /* Xmega erase memory types, for CMND_XMEGA_ERASE */ #define XMEGA_ERASE_CHIP 0x00 #define XMEGA_ERASE_APP 0x01 @@ -393,5 +401,7 @@ struct updi_device_desc { unsigned char flash_page_size_msb; // Extends flash_page_size, used in 24-bit mode unsigned char address_mode; // 0x00 = 16-bit mode, 0x01 = 24-bit mode + + unsigned char hvupdi_variant; // Indicates the target UPDI HV implementation }; #endif /* JTAG3_PRIVATE_EXPORTED */ diff --git a/src/lexer.l b/src/lexer.l index 00e83d6b..38d988db 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -160,6 +160,8 @@ hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; } hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; } hvsp_controlstack { yylval=NULL; return K_HVSP_CONTROLSTACK; } hvspcmdexedelay { yylval=NULL; return K_HVSPCMDEXEDELAY; } +hvupdi_support { yylval=NULL; return K_HVUPDI_SUPPORT; } +hvupdi_variant { yylval=NULL; return K_HVUPDI_VARIANT; } id { yylval=NULL; return K_ID; } idr { yylval=NULL; return K_IDR; } io { yylval=new_token(K_IO); return K_IO; } diff --git a/src/libavrdude.h b/src/libavrdude.h index e8c2a362..36ad9aa8 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -198,6 +198,10 @@ typedef struct opcode { #define AVRPART_IS_AT90S1200 0x1000 /* part is an AT90S1200 (needs special treatment) */ #define AVRPART_HAS_UPDI 0x2000 /* part has UPDI i/f (AVR8X) */ +#define HV_UPDI_VARIANT_0 0 /* Shared UPDI/GPIO/RESET pin, HV on UPDI pin (tinyAVR0/1/2)*/ +#define HV_UPDI_VARIANT_1 1 /* Dedicated UPDI pin, no HV (megaAVR0/AVR-Dx) */ +#define HV_UPDI_VARIANT_2 2 /* Shared UPDI pin, HV on _RESET (AVR-Ex) */ + #define AVR_DESCLEN 64 #define AVR_IDLEN 32 #define AVR_FAMILYIDLEN 7 @@ -212,6 +216,7 @@ typedef struct avrpart { char desc[AVR_DESCLEN]; /* long part name */ char id[AVR_IDLEN]; /* short part name */ char family_id[AVR_FAMILYIDLEN+1]; /* family id in the SIB (avr8x) */ + int hvupdi_variant; /* HV pulse on UPDI pin, no pin or RESET pin */ int stk500_devcode; /* stk500 device code */ int avr910_devcode; /* avr910 device code */ int chip_erase_delay; /* microseconds */ @@ -725,6 +730,7 @@ typedef struct programmer_t { int lineno; /* config file line number */ void *cookie; /* for private use by the programmer */ char flag; /* for private use of the programmer */ + LISTID hvupdi_support; /* List of UPDI HV variants the tool supports. See HV_UPDI_VARIANT_ */ } PROGRAMMER; #ifdef __cplusplus diff --git a/src/pgm.c b/src/pgm.c index 851ac5a8..4580cbbd 100644 --- a/src/pgm.c +++ b/src/pgm.c @@ -83,6 +83,7 @@ PROGRAMMER * pgm_new(void) pgm->lineno = 0; pgm->baudrate = 0; pgm->initpgm = NULL; + pgm->hvupdi_support = lcreat(NULL, 0); for (i=0; ipinno[i] = 0;