Merge pull request #1015 from MCUdude/hv-updi

Add support for high-voltage UPDI
This commit is contained in:
Stefan Rueger 2022-07-18 14:28:39 +01:00 committed by GitHub
commit 6fa7400e4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 184 additions and 26 deletions

View File

@ -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

View File

@ -40,6 +40,7 @@
# usbvendor = <vendorname>; # USB Vendor Name
# usbproduct = <productname>; # USB Product Name
# usbsn = <serialno>; # USB Serial Number
# hvupdi_support = <num> [, <num>, ... ] ; # UPDI HV Variants Support
#
# To invert a bit, use = ~ <num>, 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;

View File

@ -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);

View File

@ -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 "

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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; }

View File

@ -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

View File

@ -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; i<N_PINS; i++) {
pgm->pinno[i] = 0;