Merge pull request #1345 from MCUdude/more-extra-parameters

Add `-xvtarg`, `-xvaref` and `-xfosc` extended parameters
This commit is contained in:
Stefan Rueger
2023-04-23 22:48:21 +01:00
committed by GitHub
12 changed files with 1000 additions and 140 deletions

View File

@@ -1185,14 +1185,20 @@ bits before, and
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.
.Nm Power Debugger and Pickit 4 only
.sp 0.5
High-voltage UPDI programming is used to enable a UPDI pin that has previously
been set to RESET or GPIO mode. Use
.Ar -xhvupdi
to enable high-voltage UPDI initialization for targets that supports this.
.It Ar vtarg=VALUE, vtarg
.Nm Power Debugger only
.sp 0.5
The voltage generator can be enabled by setting a target voltage.
The current set-voltage can be read by
.Ar -xvtarg
alone.
.It Ar help
Show help menu and exit.
.El
@@ -1228,6 +1234,51 @@ Also note that the smaller Xplained Nano boards does not have a target power swi
.It Ar help
Show help menu and exit.
.El
.It Ar Curiosity Nano
.Bl -tag -offset indent -width indent
.It Ar vtarg=VALUE, vtarg
The generated on-board target voltage can be changed by specifying a new voltage.
The current set-voltage can be read by
.Ar -xvtarg
alone.
.It Ar help
Show help menu and exit.
.El
.It Ar STK500
.It Ar STK600
.Bl -tag -offset indent -width indent
.It Ar vtarg=VALUE, vtarg
The generated on-board target voltage can be changed by specifying a new voltage.
The current set-voltage can be read by
.Ar -xvtarg
alone.
.It Ar fosc=VALUE[MHz|M|kHz|k|Hz], fosc
Set the programmable oscillator frequency. The current frequency can be read by
.Ar -xfosc
alone.
.It Ar varef=VALUE, varef
The generated on-board analog reference voltage can be changed by specifying
a new reference voltage. The current reference voltage can be read by
.Ar -xvaref
alone.
.It Ar varef[0,1]=VALUE, varef[0,1]
.Nm STK600 only
.sp 0.5
The generated on-board analog reference voltage for channel 0 or channel 1 can
be changed by specifying a new reference voltage.
The current reference voltage can be read by
.Ar -xvaref0
or
.Ar -xvaref1
alone.
.It Ar attemps[=<1..99>]
.Nm STK500V1 only
.sp 0.5
Specify how many connection retry attemps to perform before exiting.
Defaults to 10 if not specified.
.It Ar help
Show help menu and exit.
.El
.It Ar AVR910
.Bl -tag -offset indent -width indent
.It Ar devcode=VALUE
@@ -1260,6 +1311,8 @@ Show help menu and exit.
.It Ar attemps[=<1..99>]
Specify how many connection retry attemps to perform before exiting.
Defaults to 10 if not specified.
.It Ar help
Show help menu and exit.
.El
.It Ar Urclock
.Bl -tag -offset indent -width indent
@@ -1534,14 +1587,6 @@ line.
.It Ar help
Show help menu and exit.
.El
.It Ar STK500
.Bl -tag -offset indent -width indent
.It Ar attemps[=<1..99>]
Specify how many connection retry attemps to perform before exiting.
Defaults to 10 if not specified.
.It Ar help
Show help menu and exit.
.El
.It Ar serialupdi
.Bl -tag -offset indent -width indent
.It Ar rtsdtr=low,high
@@ -1563,6 +1608,7 @@ the CS line being managed outside the application.
.It Ar help
Show help menu and exit.
.El
.El
.Sh FILES
.Bl -tag -offset indent -width /dev/ppi0XXX
.It Pa /dev/ppi0

View File

@@ -71,6 +71,10 @@
# # - HAS_VTARG_SWITCH: Programer has a programmable target power switch
# # - HAS_VTARG_ADJ: Programmer has an adjustable target power source that can
# # be controlled with Avrdude
# # - HAS_FOSC_ADJ: Programmer has a programable frequency generator that
# # can clock an AVR directly through its XTAL1 pin
# # - HAS_VAREF_ADJ: Programmer has an adjustable analog reference voltage that
# # can be controlled with Avrdude
# #
# # (3) Not all programmer types can process a list of PIDs
#
@@ -1285,6 +1289,7 @@ programmer
desc = "Atmel STK500";
type = "stk500generic";
prog_modes = PM_ISP;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ;
connection_type = serial;
;
@@ -1297,6 +1302,7 @@ programmer
desc = "Atmel STK500 version 1.x firmware";
type = "stk500";
prog_modes = PM_ISP;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ;
connection_type = serial;
;
@@ -1321,6 +1327,7 @@ programmer
desc = "Atmel STK500 version 2.x firmware";
type = "stk500v2";
prog_modes = PM_TPI | PM_ISP;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ;
connection_type = serial;
;
@@ -1333,6 +1340,7 @@ programmer
desc = "Atmel STK500 v2 in parallel programming mode";
type = "stk500pp";
prog_modes = PM_HVPP;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ;
connection_type = serial;
;
@@ -1345,6 +1353,7 @@ programmer
desc = "Atmel STK500 v2 in high-voltage serial programming mode";
type = "stk500hvsp";
prog_modes = PM_HVSP;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ;
connection_type = serial;
;
@@ -1357,7 +1366,7 @@ programmer
desc = "Atmel STK600";
type = "stk600";
prog_modes = PM_TPI | PM_ISP | PM_PDI;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ;
connection_type = usb;
;
@@ -1370,7 +1379,7 @@ programmer
desc = "Atmel STK600 in parallel programming mode";
type = "stk600pp";
prog_modes = PM_HVPP;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ;
connection_type = usb;
;
@@ -1383,7 +1392,7 @@ programmer
desc = "Atmel STK600 in high-voltage serial programming mode";
type = "stk600hvsp";
prog_modes = PM_HVSP;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ;
extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ;
connection_type = usb;
;

View File

@@ -336,26 +336,28 @@ TOKEN *new_constant(const char *con) {
tkn->value.type = V_NUM;
tkn->value.number =
!strcmp("PM_SPM", con)? PM_SPM:
!strcmp("PM_TPI", con)? PM_TPI:
!strcmp("PM_ISP", con)? PM_ISP:
!strcmp("PM_PDI", con)? PM_PDI:
!strcmp("PM_UPDI", con)? PM_UPDI:
!strcmp("PM_HVSP", con)? PM_HVSP:
!strcmp("PM_HVPP", con)? PM_HVPP:
!strcmp("PM_debugWIRE", con)? PM_debugWIRE:
!strcmp("PM_JTAG", con)? PM_JTAG:
!strcmp("PM_JTAGmkI", con)? PM_JTAGmkI:
!strcmp("PM_XMEGAJTAG", con)? PM_XMEGAJTAG:
!strcmp("PM_AVR32JTAG", con)? PM_AVR32JTAG:
!strcmp("PM_aWire", con)? PM_aWire:
!strcmp("HAS_SUFFER", con)? HAS_SUFFER:
!strcmp("HAS_VTARG_SWITCH", con)? HAS_VTARG_SWITCH:
!strcmp("HAS_VTARG_ADJ", con)? HAS_VTARG_ADJ:
!strcmp("HAS_VTARG_READ", con)? HAS_VTARG_READ:
!strcmp("pseudo", con)? 2:
!strcmp("yes", con) || !strcmp("true", con)? 1:
!strcmp("no", con) || !strcmp("false", con)? 0:
str_eq(con, "PM_SPM")? PM_SPM:
str_eq(con, "PM_TPI")? PM_TPI:
str_eq(con, "PM_ISP")? PM_ISP:
str_eq(con, "PM_PDI")? PM_PDI:
str_eq(con, "PM_UPDI")? PM_UPDI:
str_eq(con, "PM_HVSP")? PM_HVSP:
str_eq(con, "PM_HVPP")? PM_HVPP:
str_eq(con, "PM_debugWIRE")? PM_debugWIRE:
str_eq(con, "PM_JTAG")? PM_JTAG:
str_eq(con, "PM_JTAGmkI")? PM_JTAGmkI:
str_eq(con, "PM_XMEGAJTAG")? PM_XMEGAJTAG:
str_eq(con, "PM_AVR32JTAG")? PM_AVR32JTAG:
str_eq(con, "PM_aWire")? PM_aWire:
str_eq(con, "HAS_SUFFER")? HAS_SUFFER:
str_eq(con, "HAS_VTARG_SWITCH")? HAS_VTARG_SWITCH:
str_eq(con, "HAS_VTARG_ADJ")? HAS_VTARG_ADJ:
str_eq(con, "HAS_VTARG_READ")? HAS_VTARG_READ:
str_eq(con, "HAS_FOSC_ADJ")? HAS_FOSC_ADJ:
str_eq(con, "HAS_VAREF_ADJ")? HAS_VAREF_ADJ:
str_eq(con, "pseudo")? 2:
str_eq(con, "yes") || str_eq(con, "true")? 1:
str_eq(con, "no") || str_eq(con, "false")? 0:
(assigned = 0);
if(!assigned) {
@@ -495,7 +497,7 @@ const char *cache_string(const char *p) {
hs = hstrings[h] = (char **) cfg_realloc("cache_string()", NULL, (16+1)*sizeof**hstrings);
for(k=0; hs[k]; k++)
if(*p == *hs[k] && !strcmp(p, hs[k]))
if(*p == *hs[k] && str_eq(p, hs[k]))
return hs[k];
if(k && k%16 == 0)
@@ -520,7 +522,7 @@ COMMENT *locate_comment(const LISTID comments, const char *where, int rhs) {
if(comments)
for(LNODEID ln=lfirst(comments); ln; ln=lnext(ln)) {
COMMENT *n = ldata(ln);
if(n && rhs == n->rhs && n->kw && strcmp(where, n->kw) == 0)
if(n && rhs == n->rhs && n->kw && str_eq(where, n->kw))
return n;
}
@@ -563,7 +565,7 @@ void capture_comment_str(const char *com, int lineno) {
// Capture assignments (keywords left of =) and associate comments to them
void capture_lvalue_kw(const char *kw, int lineno) {
if(!strcmp(kw, "memory")) { // Push part comments and start memory comments
if(str_eq(kw, "memory")) { // Push part comments and start memory comments
if(!cfg_pushed) { // config_gram.y pops the part comments
cfg_pushed = 1;
cfg_pushedcomms = cfg_strctcomms;
@@ -571,7 +573,7 @@ void capture_lvalue_kw(const char *kw, int lineno) {
}
}
if(!strcmp(kw, "programmer") || !strcmp(kw, "part") || !strcmp(kw, "memory"))
if(str_eq(kw, "programmer") || str_eq(kw, "part") || str_eq(kw, "memory"))
kw = "*"; // Show comment before programmer/part/memory
if(lkw)

View File

@@ -256,6 +256,10 @@ static char *extra_features_str(int m) {
strcat(mode, " | HAS_VTARG_ADJ");
if(m & HAS_VTARG_READ)
strcat(mode, " | HAS_VTARG_READ");
if(m & HAS_FOSC_ADJ)
strcat(mode, " | HAS_FOSC_ADJ");
if(m & HAS_VAREF_ADJ)
strcat(mode, " | HAS_VAREF_ADJ");
return mode + (mode[1] == 0? 0: 4);
}

View File

@@ -940,14 +940,19 @@ after, @var{BB} bits before, and @var{BA} 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.
@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.
@var{Power Debugger and Pickit 4 only}
@*
High-voltage UPDI programming is used to enable a UPDI pin that has previously
been set to RESET or GPIO mode. Use @samp{-xhvupdi} to enable high-voltage UPDI
initialization for supported targets.
@item @samp{vtarg=VALUE, vtarg}
@var{Power Debugger only}
@*
The voltage generator can be enabled by setting a target voltage.
The current set-voltage can be read by @samp{-xvtarg} alone.
@item @samp{help}
Show help menu and exit.
@@ -988,6 +993,51 @@ Also note that the smaller Xplained Nano boards does not have a target power swi
Show help menu and exit.
@end table
@cindex @code{-x} Curiosity Nano
@item Curiosity Nano
The Curiosity Nano board accepts the following extended parameter:
@table @code
@item @samp{vtarg=VALUE, vtarg}
The generated on-board target voltage can be changed by specifying a new voltage.
The current set-voltage can be read by @samp{-xvtarg} alone.
@item @samp{help}
Show help menu and exit.
@end table
@cindex @code{-x} STK500
@cindex @code{-x} STK600
@item STK500
@item STK600
The STK500 and STK600 boards accept the following extended parameters:
@table @code
@item @samp{vtarg=VALUE, vtarg}
The generated on-board target voltage can be changed by specifying a new voltage.
The current set-voltage can be read by @samp{-xvtarg} alone.
@item @samp{fosc=VALUE[MHz|M|kHz|k|Hz], fosc}
Set the programmable oscillator frequency in MHz, kHz or Hz.
The current frequency can be read by @samp{-xfosc} alone.
@item @samp{varef=VALUE, varef}
The generated on-board analog reference voltage can be changed by specifying
a new reference voltage. The current reference voltage can be read by
@samp{-xvaref} alone.
@item @samp{varef[0,1]=VALUE, varef[0,1]}
@var{STK600 only}
@*
The generated on-board analog reference voltage for channel 0 or channel 1 can
be changed by specifying a new reference voltage.
The current reference voltage can be read by @samp{-xvaref0} or
@samp{-xvaref1} alone.
@item @samp{attemps[=<1..99>]}
@var{STK500V1 only}
@*
Specify how many connection retry attemps to perform before exiting.
Defaults to 10 if not specified.
@item @samp{help}
Show help menu and exit.
@end table
@cindex @code{-x} AVR910
@item AVR910

View File

@@ -84,6 +84,11 @@ struct pdata
bool vtarg_switch_set;
unsigned char vtarg_switch_data[2];
/* Get/set flags for adjustable target voltage */
bool vtarg_get;
bool vtarg_set;
double vtarg_data;
/* Function to set the appropriate clock parameter */
int (*set_sck)(const PROGRAMMER *, unsigned char *);
};
@@ -1099,7 +1104,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
if (PDATA(pgm)->set_sck(pgm, parm) < 0)
return -1;
}
jtag3_print_parms1(pgm, progbuf, stderr);
if (conn == PARM3_CONN_JTAG) {
pmsg_notice2("jtag3_initialize(): "
"trying to set JTAG daisy-chain info to %d,%d,%d,%d\n",
@@ -1109,6 +1114,9 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
return -1;
}
if (verbose && quell_progress < 2)
jtag3_print_parms1(pgm, progbuf, stderr);
// Read or write SUFFER register
if (PDATA(pgm)->suffer_get || PDATA(pgm)->suffer_set) {
// Read existing SUFFER value
@@ -1144,6 +1152,26 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
}
}
// Read or write target voltage
if (PDATA(pgm)->vtarg_get || PDATA(pgm)->vtarg_set) {
// Read current target voltage set value
unsigned char buf[2];
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0)
return -1;
double vtarg_read = b2_to_u16(buf) / 1000.0;
if (PDATA(pgm)->vtarg_get)
msg_info("Target voltage value read as %.2fV\n", vtarg_read);
// Write target voltage value
else {
u16_to_b2(buf, (unsigned)(PDATA(pgm)->vtarg_data * 1000));
msg_info("Changing target voltage from %.2f to %.2fV\n", vtarg_read, PDATA(pgm)->vtarg_data);
if (jtag3_setparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, sizeof(buf)) < 0) {
msg_warning("Cannot set target voltage %.2fV\n", PDATA(pgm)->vtarg_data);
return -1;
}
}
}
/* set device descriptor data */
if ((p->prog_modes & PM_PDI)) {
struct xmega_device_desc xd;
@@ -1528,6 +1556,29 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
}
}
else if (str_starts(extended_param, "vtarg")) {
if (pgm->extra_features & HAS_VTARG_ADJ) {
// Set target voltage
if (str_starts(extended_param, "vtarg=") ) {
double vtarg_set_val = 0;
int sscanf_success = sscanf(extended_param, "vtarg=%lf", &vtarg_set_val);
PDATA(pgm)->vtarg_data = (double)((int)(vtarg_set_val * 100 + .5)) / 100;
if (sscanf_success < 1 || vtarg_set_val < 0) {
pmsg_error("invalid vtarg value '%s'\n", extended_param);
rv = -1;
break;
}
PDATA(pgm)->vtarg_set = true;
continue;
}
// Get target voltage
else if(str_eq(extended_param, "vtarg")) {
PDATA(pgm)->vtarg_get = true;
continue;
}
}
}
else if (str_eq(extended_param, "help")) {
char *prg = (char *)ldata(lfirst(pgm->id));
msg_error("%s -c %s extended options:\n", progname, prg);
@@ -1541,6 +1592,10 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
msg_error(" -xvtarg_switch Read on-board target voltage switch state\n");
msg_error(" -xvtarg_switch=<0..1> Set on-board target voltage switch state\n");
}
if (pgm->extra_features & HAS_VTARG_ADJ) {
msg_error(" -xvtarg Read on-board target supply voltage\n");
msg_error(" -xvtarg=<arg> Set on-board target supply voltage\n");
}
msg_error (" -xhelp Show this help menu and exit\n");
exit(0);
}
@@ -2496,7 +2551,7 @@ void jtag3_display(const PROGRAMMER *pgm, const char *p) {
msg_info("%sICE HW version : %d\n", p, parms[0]);
msg_info("%sICE FW version : %d.%02d (rel. %d)\n", p, parms[1], parms[2],
(parms[3] | (parms[4] << 8)));
msg_info("%sSerial number : %s", p, sn);
msg_info("%sSerial number : %s\n", p, sn);
free(resp);
}
@@ -2509,6 +2564,39 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
return;
msg_info("%sVtarget : %.2f V\n", p, b2_to_u16(buf)/1000.0);
// Print clocks if programmer typ is not TPI
if (!str_eq(pgm->type, "JTAGICE3_TPI")) {
// Get current programming mode and target type from to determine what data to print
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CONNECTION, prog_mode, 1) < 0)
return;
if (jtag3_getparm(pgm, SCOPE_AVR, 0, PARM3_ARCH, &prog_mode[1], 1) < 0)
return;
if (prog_mode[0] == PARM3_CONN_JTAG) {
if (prog_mode[1] == PARM3_ARCH_XMEGA) {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sJTAG clk Xmega : %u kHz\n", p, b2_to_u16(buf));
} else {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sJTAG clk prog. : %u kHz\n", p, b2_to_u16(buf));
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sJTAG clk debug : %u kHz\n", p, b2_to_u16(buf));
}
}
else if (prog_mode[0] == PARM3_CONN_PDI || prog_mode[0] == PARM3_CONN_UPDI) {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sPDI/UPDI clk : %u kHz\n", p, b2_to_u16(buf));
}
}
// Print features unique to the Power Debugger
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) {
if(str_starts(ldata(ln), "powerdebugger")) {
@@ -2579,39 +2667,6 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
break;
}
}
// Print clocks if programmer typ is not TPI
if (strcmp(pgm->type, "JTAGICE3_TPI")) {
// Get current programming mode and target type from to determine what data to print
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CONNECTION, prog_mode, 1) < 0)
return;
if (jtag3_getparm(pgm, SCOPE_AVR, 0, PARM3_ARCH, &prog_mode[1], 1) < 0)
return;
if (prog_mode[0] == PARM3_CONN_JTAG) {
if (prog_mode[1] == PARM3_ARCH_XMEGA) {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sJTAG clk Xmega : %u kHz\n", p, b2_to_u16(buf));
} else {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sJTAG clk prog. : %u kHz\n", p, b2_to_u16(buf));
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sJTAG clk debug : %u kHz\n", p, b2_to_u16(buf));
}
}
else if (prog_mode[0] == PARM3_CONN_PDI || prog_mode[0] == PARM3_CONN_UPDI) {
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0)
return;
if (b2_to_u16(buf) > 0)
fmsg_out(fp, "%sPDI/UPDI clk : %u kHz\n", p, b2_to_u16(buf));
}
}
fmsg_out(fp, "\n");
}
@@ -2761,6 +2816,29 @@ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) {
unsigned char* resp;
int status;
// Read or write target voltage
if (PDATA(pgm)->vtarg_get || PDATA(pgm)->vtarg_set) {
// Read current target voltage set value
unsigned char buf[2];
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0)
return -1;
double vtarg_read = b2_to_u16(buf) / 1000.0;
if (PDATA(pgm)->vtarg_get)
msg_info("Target voltage value read as %.2fV\n", vtarg_read);
// Write target voltage value
else {
u16_to_b2(buf, (unsigned)(PDATA(pgm)->vtarg_data * 1000));
msg_info("Changing target voltage from %.2f to %.2fV\n", vtarg_read, PDATA(pgm)->vtarg_data);
if (jtag3_setparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, sizeof(buf)) < 0) {
msg_warning("Cannot set target voltage %.2fV\n", PDATA(pgm)->vtarg_data);
return -1;
}
}
}
if (verbose && quell_progress < 2)
jtag3_print_parms1(pgm, progbuf, stderr);
pmsg_notice2("jtag3_initialize_tpi() start\n");
cmd[0] = XPRG_CMD_ENTER_PROGMODE;
@@ -2785,8 +2863,6 @@ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) {
return -1;
free(resp);
jtag3_print_parms1(pgm, progbuf, stderr);
return 0;
}
@@ -3100,6 +3176,9 @@ void jtag3_initpgm(PROGRAMMER *pgm) {
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_JTAG;
/*
* hardware dependent functions
*/
if (pgm->extra_features & HAS_VTARG_ADJ)
pgm->set_vtarget = jtag3_set_vtarget;
}
@@ -3129,11 +3208,15 @@ void jtag3_dw_initpgm(PROGRAMMER *pgm) {
pgm->paged_write = jtag3_paged_write;
pgm->paged_load = jtag3_paged_load;
pgm->print_parms = jtag3_print_parms;
pgm->parseextparams = jtag3_parseextparms;
pgm->setup = jtag3_setup;
pgm->teardown = jtag3_teardown;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_DW;
/*
* hardware dependent functions
*/
if (pgm->extra_features & HAS_VTARG_ADJ)
pgm->set_vtarget = jtag3_set_vtarget;
}
@@ -3165,11 +3248,15 @@ void jtag3_pdi_initpgm(PROGRAMMER *pgm) {
pgm->page_erase = jtag3_page_erase;
pgm->print_parms = jtag3_print_parms;
pgm->set_sck_period = jtag3_set_sck_period;
pgm->parseextparams = jtag3_parseextparms;
pgm->setup = jtag3_setup;
pgm->teardown = jtag3_teardown;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_PDI;
/*
* hardware dependent functions
*/
if (pgm->extra_features & HAS_VTARG_ADJ)
pgm->set_vtarget = jtag3_set_vtarget;
}
@@ -3183,7 +3270,6 @@ 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;
@@ -3202,6 +3288,7 @@ void jtag3_updi_initpgm(PROGRAMMER *pgm) {
pgm->page_erase = jtag3_page_erase;
pgm->print_parms = jtag3_print_parms;
pgm->set_sck_period = jtag3_set_sck_period;
pgm->parseextparams = jtag3_parseextparms;
pgm->setup = jtag3_setup;
pgm->teardown = jtag3_teardown;
pgm->page_size = 256;
@@ -3209,6 +3296,9 @@ void jtag3_updi_initpgm(PROGRAMMER *pgm) {
pgm->unlock = jtag3_unlock_erase_key;
pgm->read_sib = jtag3_read_sib;
/*
* hardware dependent functions
*/
if (pgm->extra_features & HAS_VTARG_ADJ)
pgm->set_vtarget = jtag3_set_vtarget;
}
@@ -3238,6 +3328,7 @@ void jtag3_tpi_initpgm(PROGRAMMER *pgm) {
pgm->paged_write = jtag3_paged_write_tpi;
pgm->paged_load = jtag3_paged_load_tpi;
pgm->print_parms = jtag3_print_parms;
pgm->parseextparams = jtag3_parseextparms;
pgm->setup = jtag3_setup;
pgm->teardown = jtag3_teardown;
pgm->page_size = 256;

View File

@@ -145,7 +145,7 @@ SIGN [+-]
(?x: PM_(SPM|TPI|ISP|PDI|UPDI|HVSP|HVPP|debugWIRE|JTAG|JTAGmkI|XMEGAJTAG|AVR32JTAG|aWire) |
HAS_(SUFFER|VTARG_SWITCH|VTARG_ADJ|VTARG_READ) |
HAS_(SUFFER|VTARG_SWITCH|VTARG_ADJ|VTARG_READ|FOSC_ADJ|VAREF_ADJ) |
yes|no|pseudo | true|false ) { /* Constants */
yylval = new_constant(yytext);
return TKN_NUMBER;

View File

@@ -215,6 +215,8 @@ typedef struct opcode {
#define HAS_VTARG_SWITCH 2
#define HAS_VTARG_ADJ 4
#define HAS_VTARG_READ 8
#define HAS_FOSC_ADJ 16
#define HAS_VAREF_ADJ 32
#define AVR_FAMILYIDLEN 7
#define AVR_SIBLEN 16

View File

@@ -45,6 +45,18 @@
#define STK500_XTAL 7372800U
#define MAX_SYNC_ATTEMPTS 10
static double f_to_kHz_MHz(double f, const char **unit) {
if (f > 1e6) {
f /= 1e6;
*unit = "MHz";
} else if (f > 1e3) {
f /= 1000;
*unit = "kHz";
} else
*unit = "Hz";
return f;
}
static int stk500_getparm(const PROGRAMMER *pgm, unsigned parm, unsigned *value);
static int stk500_setparm(const PROGRAMMER *pgm, unsigned parm, unsigned value);
static void stk500_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
@@ -557,6 +569,73 @@ static int stk500_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
}
}
// Read or write target voltage
if (PDATA(pgm)->vtarg_get || PDATA(pgm)->vtarg_set) {
// Read current target voltage set value
unsigned int vtarg_read;
stk500_getparm(pgm, Parm_STK_VTARGET, &vtarg_read);
if (PDATA(pgm)->vtarg_get)
msg_info("Target voltage value read as %.2fV\n", (vtarg_read / 10.0));
// Write target voltage value
else {
msg_info("Changing target voltage from %.2f to %.2fV\n", (vtarg_read / 10.0), PDATA(pgm)->vtarg_data);
if(pgm->set_vtarget(pgm, PDATA(pgm)->vtarg_data) < 0)
return -1;
}
}
// Read or write analog reference voltage
if (PDATA(pgm)->varef_get || PDATA(pgm)->varef_set) {
// Read current analog reference voltage
unsigned int varef_read;
stk500_getparm(pgm, Parm_STK_VADJUST, &varef_read);
if (PDATA(pgm)->varef_get)
msg_info("Analog reference voltage value read as %.2fV\n", (varef_read / 10.0));
// Write analog reference voltage
else {
msg_info("Changing analog reference voltage from %.2f to %.2fV\n",
(varef_read / 10.0), PDATA(pgm)->varef_data);
if(pgm->set_varef(pgm, 0, PDATA(pgm)->varef_data) < 0)
return -1;
}
}
// Read or write clock generator frequency
if (PDATA(pgm)->fosc_get || PDATA(pgm)->fosc_set) {
// Read current target voltage set value
unsigned int osc_pscale;
unsigned int osc_cmatch;
const char *unit_get = {"Hz"};
double f_get = 0.0;
stk500_getparm(pgm, Parm_STK_OSC_PSCALE, &osc_pscale);
stk500_getparm(pgm, Parm_STK_OSC_CMATCH, &osc_cmatch);
if(osc_pscale) {
int prescale = 1;
f_get = STK500_XTAL / 2;
switch (osc_pscale) {
case 2: prescale = 8; break;
case 3: prescale = 32; break;
case 4: prescale = 64; break;
case 5: prescale = 128; break;
case 6: prescale = 256; break;
case 7: prescale = 1024; break;
}
f_get /= prescale;
f_get /= (osc_cmatch + 1);
f_get = f_to_kHz_MHz(f_get, &unit_get);
}
if (PDATA(pgm)->fosc_get)
msg_info("Oscillator currently set to %.3f %s\n", f_get, unit_get);
// Write target voltage value
else {
const char *unit_set;
double f_set = f_to_kHz_MHz(PDATA(pgm)->fosc_data, &unit_set);
msg_info("Changing oscillator frequency from %.3f %s to %.3f %s\n", f_get, unit_get, f_set, unit_set);
if(pgm->set_fosc(pgm, PDATA(pgm)->fosc_data) < 0)
return -1;
}
}
return pgm->program_enable(pgm, p);
}
@@ -570,17 +649,122 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
extended_param = ldata(ln);
if (sscanf(extended_param, "attempts=%2d", &attempts) == 1) {
PDATA(pgm)->retry_attempts = attempts;
pmsg_info("setting number of retry attempts to %d\n", attempts);
continue;
}
if (sscanf(extended_param, "attempts=%2d", &attempts) == 1) {
PDATA(pgm)->retry_attempts = attempts;
pmsg_info("setting number of retry attempts to %d\n", attempts);
continue;
}
else if (str_starts(extended_param, "vtarg")) {
if (pgm->extra_features & HAS_VTARG_ADJ) {
// Set target voltage
if (str_starts(extended_param, "vtarg=") ) {
double vtarg_set_val = 0;
int sscanf_success = sscanf(extended_param, "vtarg=%lf", &vtarg_set_val);
PDATA(pgm)->vtarg_data = (double)((int)(vtarg_set_val * 100 + .5)) / 100;
if (sscanf_success < 1 || vtarg_set_val < 0) {
pmsg_error("invalid vtarg value '%s'\n", extended_param);
rv = -1;
break;
}
PDATA(pgm)->vtarg_set = true;
continue;
}
// Get target voltage
else if(str_eq(extended_param, "vtarg")) {
PDATA(pgm)->vtarg_get = true;
continue;
}
}
}
else if (str_starts(extended_param, "varef")) {
if (pgm->extra_features & HAS_VAREF_ADJ) {
int sscanf_success = 0;
double varef_set_val = 0;
// Get new analog reference voltage for channel 0
if (str_starts(extended_param, "varef=")) {
sscanf_success = sscanf(extended_param, "varef=%lf", &varef_set_val);
PDATA(pgm)->varef_set = true;
}
// Get new analog reference voltage for channel 0
else if(str_starts(extended_param, "varef0=")) {
sscanf_success = sscanf(extended_param, "varef0=%lf", &varef_set_val);
PDATA(pgm)->varef_set = true;
}
// Get current analog reference voltage for channel 0
else if(str_eq(extended_param, "varef") || str_eq(extended_param, "varef0")) {
PDATA(pgm)->varef_get = true;
continue;
}
// Set analog reference voltage
if (PDATA(pgm)->varef_set) {
PDATA(pgm)->varef_data = (double)((int)(varef_set_val * 100 + .5)) / 100;
if (sscanf_success < 1 || varef_set_val < 0) {
pmsg_error("invalid varef value '%s'\n", extended_param);
PDATA(pgm)->varef_set = false;
rv = -1;
break;
}
continue;
}
}
}
else if (str_starts(extended_param, "fosc")) {
if (pgm->extra_features & HAS_VAREF_ADJ) {
// Set clock generator frequency
if (str_starts(extended_param, "fosc=")) {
char fosc_str[16] = {0};
int sscanf_success = sscanf(extended_param, "fosc=%10s", fosc_str);
if (sscanf_success < 1) {
pmsg_error("invalid fosc value '%s'\n", extended_param);
rv = -1;
break;
}
char *endp;
double v = strtod(fosc_str, &endp);
if (endp == fosc_str){
if (str_eq(fosc_str, "off"))
PDATA(pgm)->fosc_data = 0.0;
else {
pmsg_error("cannot parse fosc value %s\n", fosc_str);
rv = -1;
break;
}
}
if (*endp == 'm' || *endp == 'M')
PDATA(pgm)->fosc_data = v * 1e6;
else if (*endp == 'k' || *endp == 'K')
PDATA(pgm)->fosc_data = v * 1e3;
PDATA(pgm)->fosc_set = true;
continue;
}
// Get clock generator frequency
else if(str_eq(extended_param, "fosc")) {
PDATA(pgm)->fosc_get = true;
continue;
}
}
}
else if (str_eq(extended_param, "help")) {
char *prg = (char *)ldata(lfirst(pgm->id));
msg_error("%s -c %s extended options:\n", progname, prg);
msg_error(" -xattempts=<arg> Specify no. connection retry attempts\n");
msg_error(" -xhelp Show this help menu and exit\n");
msg_error(" -xattempts=<arg> Specify no. connection retry attempts\n");
if (pgm->extra_features & HAS_VTARG_ADJ) {
msg_error(" -xvtarg Read target supply voltage\n");
msg_error(" -xvtarg=<arg> Set target supply voltage\n");
}
if (pgm->extra_features & HAS_VAREF_ADJ) {
msg_error(" -xvaref Read analog reference voltage\n");
msg_error(" -xvaref=<arg> Set analog reference voltage\n");
}
if (pgm->extra_features & HAS_FOSC_ADJ) {
msg_error(" -xfosc Read oscillator clock frequency\n");
msg_error(" -xfosc=<arg>[M|k]|off Set oscillator clock frequency\n");
}
msg_error(" -xhelp Show this help menu and exit\n");
exit(0);
}
@@ -966,7 +1150,7 @@ static int stk500_set_vtarget(const PROGRAMMER *pgm, double v) {
}
if (uaref > utarg) {
pmsg_error("reducing V[aref] from %.1f to %.1f\n", uaref / 10.0, v);
pmsg_warning("reducing V[aref] from %.1f to %.1f\n", uaref / 10.0, v);
if (stk500_setparm(pgm, Parm_STK_VADJUST, utarg) != 0)
return -1;
}
@@ -1282,7 +1466,6 @@ void stk500_initpgm(PROGRAMMER *pgm) {
* mandatory functions
*/
pgm->initialize = stk500_initialize;
pgm->parseextparams = stk500_parseextparms;
pgm->display = stk500_display;
pgm->enable = stk500_enable;
pgm->disable = stk500_disable;
@@ -1300,11 +1483,19 @@ void stk500_initpgm(PROGRAMMER *pgm) {
pgm->paged_write = stk500_paged_write;
pgm->paged_load = stk500_paged_load;
pgm->print_parms = stk500_print_parms;
pgm->set_vtarget = stk500_set_vtarget;
pgm->set_varef = stk500_set_varef;
pgm->set_fosc = stk500_set_fosc;
pgm->set_sck_period = stk500_set_sck_period;
pgm->parseextparams = stk500_parseextparms;
pgm->setup = stk500_setup;
pgm->teardown = stk500_teardown;
pgm->page_size = 256;
/*
* hardware dependent functions
*/
if (pgm->extra_features & HAS_VTARG_ADJ)
pgm->set_vtarget = stk500_set_vtarget;
if (pgm->extra_features & HAS_VAREF_ADJ)
pgm->set_varef = stk500_set_varef;
if (pgm->extra_features & HAS_FOSC_ADJ)
pgm->set_fosc = stk500_set_fosc;
}

View File

@@ -42,6 +42,21 @@ struct pdata {
unsigned char ext_addr_byte; // Record ext-addr byte set in the target device (if used)
int retry_attempts; // Number of connection attempts provided by the user
int xbeeResetPin; // Piggy back variable used by xbee programmmer
// Get/set flags for adjustable target voltage
bool vtarg_get;
bool vtarg_set;
double vtarg_data;
// Get/set flags for adjustable analog reference voltage
bool varef_get;
bool varef_set;
double varef_data;
// Get/set flags for programmable clock generator
bool fosc_get;
bool fosc_set;
double fosc_data;
};
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))

View File

@@ -377,6 +377,28 @@ b2_to_u16(unsigned char *b)
return l;
}
static void
u16_to_b2(unsigned char *b, unsigned short l)
{
b[0] = l & 0xff;
b[1] = (l >> 8) & 0xff;
}
static double
f_to_kHz_MHz(double f, const char **unit)
{
if (f > 1e6) {
f /= 1e6;
*unit = "MHz";
} else if (f > 1e3) {
f /= 1000;
*unit = "kHz";
} else
*unit = "Hz";
return f;
}
static int stk500v2_send_mk2(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
if (serial_send(&pgm->fd, data, len) != 0) {
pmsg_error("unable to send command to serial port\n");
@@ -1223,6 +1245,109 @@ static int stk500v2_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
// stk600_setup_isp(pgm); [moved to pgm->enable()]
}
// Read or write target voltage
if (PDATA(pgm)->vtarg_get || PDATA(pgm)->vtarg_set) {
// Read current target voltage set value
unsigned char vtarg_read;
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarg_read);
if (PDATA(pgm)->vtarg_get)
msg_info("Target voltage value read as %.2fV\n", (vtarg_read / 10.0));
// Write target voltage value
else {
msg_info("Changing target voltage from %.2f to %.2fV\n", (vtarg_read / 10.0), PDATA(pgm)->vtarg_data);
if(pgm->set_vtarget(pgm, PDATA(pgm)->vtarg_data) < 0)
return -1;
}
}
// Read or write analog reference voltage
if (PDATA(pgm)->varef_get || PDATA(pgm)->varef_set) {
if(PDATA(pgm)->pgmtype == PGMTYPE_STK500) {
// STK500: Read current analog reference voltage
unsigned char varef_read;
stk500v2_getparm(pgm, PARAM_VADJUST, &varef_read);
if (PDATA(pgm)->varef_get)
msg_info("Analog reference voltage value read as %.2fV\n", (varef_read / 10.0));
// STK500: Write analog reference voltage
else {
msg_info("Changing analog reference voltage from %.2f to %.2fV\n",
(varef_read / 10.0), PDATA(pgm)->varef_data);
if(pgm->set_varef(pgm, 0, PDATA(pgm)->varef_data) < 0)
return -1;
}
} else if(PDATA(pgm)->pgmtype == PGMTYPE_STK600) {
// STK600: Read current target voltage set value
unsigned int varef_read;
stk500v2_getparm2(pgm, PDATA(pgm)->varef_channel == 0 ? PARAM2_AREF0 : PARAM2_AREF1, &varef_read);
if (PDATA(pgm)->varef_get)
msg_info("Analog reference channel %d voltage read as %.2fV\n", PDATA(pgm)->varef_channel, (varef_read / 100.0));
// STK600: Write target voltage value for channel n
else {
msg_info("Changing analog reference channel %d voltage from %.2f to %.2fV\n",
PDATA(pgm)->varef_channel, (varef_read / 100.0), PDATA(pgm)->varef_data);
if(pgm->set_varef(pgm, PDATA(pgm)->varef_channel, PDATA(pgm)->varef_data) < 0)
return -1;
}
}
}
// Read or write clock generator frequency
if (PDATA(pgm)->fosc_get || PDATA(pgm)->fosc_set) {
if(PDATA(pgm)->pgmtype == PGMTYPE_STK500) {
// Read current target voltage set value
unsigned char osc_pscale;
unsigned char osc_cmatch;
const char *unit_get = {"Hz"};
double f_get = 0.0;
stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale);
stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch);
if(osc_pscale) {
int prescale = 1;
f_get = STK500V2_XTAL / 2;
switch (osc_pscale) {
case 2: prescale = 8; break;
case 3: prescale = 32; break;
case 4: prescale = 64; break;
case 5: prescale = 128; break;
case 6: prescale = 256; break;
case 7: prescale = 1024; break;
}
f_get /= prescale;
f_get /= (osc_cmatch + 1);
f_get = f_to_kHz_MHz(f_get, &unit_get);
}
if (PDATA(pgm)->fosc_get)
msg_info("Oscillator currently set to %.3f %s\n", f_get, unit_get);
// Write target voltage value
else {
const char *unit_set;
double f_set = f_to_kHz_MHz(PDATA(pgm)->fosc_data, &unit_set);
msg_info("Changing oscillator frequency from %.3f %s to %.3f %s\n", f_get, unit_get, f_set, unit_set);
if(pgm->set_fosc(pgm, PDATA(pgm)->fosc_data) < 0)
return -1;
}
} else if(PDATA(pgm)->pgmtype == PGMTYPE_STK600) {
// Read current target voltage set value
unsigned int clock_conf;
stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf);
unsigned int oct = (clock_conf & 0xf000) >> 12u;
unsigned int dac = (clock_conf & 0x0ffc) >> 2u;
double f_get = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0);
const char *unit_get = {"Hz"};
f_get = f_to_kHz_MHz(f_get, &unit_get);
if (PDATA(pgm)->fosc_get)
msg_info("Oscillator currently set to %.3f %s\n", f_get, unit_get);
// Write target voltage value
else {
const char *unit_set;
double f_set = f_to_kHz_MHz(PDATA(pgm)->fosc_data, &unit_set);
msg_info("Changing oscillator frequency from %.3f %s to %.3f %s\n", f_get, unit_get, f_set, unit_set);
if(pgm->set_fosc(pgm, PDATA(pgm)->fosc_data) < 0)
return -1;
}
}
}
/*
* Examine the avrpart's memory definitions, and initialize the page
* caches. For devices/memory that are not page oriented, treat
@@ -1350,6 +1475,26 @@ static int stk500v2_jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
}
}
// Read or write target voltage
if (PDATA(pgm)->vtarg_get || PDATA(pgm)->vtarg_set) {
// Read current target voltage set value
unsigned char buf[2];
if (jtag3_getparm(pgmcp, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, 2) < 0)
return -1;
double vtarg_read = b2_to_u16(buf) / 1000.0;
if (PDATA(pgm)->vtarg_get)
msg_info("Target voltage value read as %.2fV\n", vtarg_read);
// Write target voltage value
else {
u16_to_b2(buf, (unsigned)(PDATA(pgm)->vtarg_data * 1000));
msg_info("Changing target voltage from %.2f to %.2fV\n", vtarg_read, PDATA(pgm)->vtarg_data);
if (jtag3_setparm(pgmcp, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, sizeof(buf)) < 0) {
msg_warning("Cannot set target voltage %.2fV\n", PDATA(pgm)->vtarg_data);
return -1;
}
}
}
free(pgmcp);
/*
@@ -1415,6 +1560,109 @@ static int stk500hv_initialize(const PROGRAMMER *pgm, const AVRPART *p, enum hvm
return -1;
}
// Read or write target voltage
if (PDATA(pgm)->vtarg_get || PDATA(pgm)->vtarg_set) {
// Read current target voltage set value
unsigned char vtarg_read;
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarg_read);
if (PDATA(pgm)->vtarg_get)
msg_info("Target voltage value read as %.2fV\n", (vtarg_read / 10.0));
// Write target voltage value
else {
msg_info("Changing target voltage from %.2f to %.2fV\n", (vtarg_read / 10.0), PDATA(pgm)->vtarg_data);
if(pgm->set_vtarget(pgm, PDATA(pgm)->vtarg_data) < 0)
return -1;
}
}
// Read or write analog reference voltage
if (PDATA(pgm)->varef_get || PDATA(pgm)->varef_set) {
if(PDATA(pgm)->pgmtype == PGMTYPE_STK500) {
// STK500: Read current analog reference voltage
unsigned char varef_read;
stk500v2_getparm(pgm, PARAM_VADJUST, &varef_read);
if (PDATA(pgm)->varef_get)
msg_info("Analog reference voltage value read as %.2fV\n", (varef_read / 10.0));
// STK500: Write analog reference voltage
else {
msg_info("Changing analog reference voltage from %.2f to %.2fV\n",
(varef_read / 10.0), PDATA(pgm)->varef_data);
if(pgm->set_varef(pgm, 0, PDATA(pgm)->varef_data) < 0)
return -1;
}
} else if(PDATA(pgm)->pgmtype == PGMTYPE_STK600) {
// STK600: Read current target voltage set value
unsigned int varef_read;
stk500v2_getparm2(pgm, PDATA(pgm)->varef_channel == 0 ? PARAM2_AREF0 : PARAM2_AREF1, &varef_read);
if (PDATA(pgm)->varef_get)
msg_info("Analog reference channel %d voltage read as %.2fV\n", PDATA(pgm)->varef_channel, (varef_read / 100.0));
// STK600: Write target voltage value for channel n
else {
msg_info("Changing analog reference channel %d voltage from %.2f to %.2fV\n",
PDATA(pgm)->varef_channel, (varef_read / 100.0), PDATA(pgm)->varef_data);
if(pgm->set_varef(pgm, PDATA(pgm)->varef_channel, PDATA(pgm)->varef_data) < 0)
return -1;
}
}
}
// Read or write clock generator frequency
if (PDATA(pgm)->fosc_get || PDATA(pgm)->fosc_set) {
if(PDATA(pgm)->pgmtype == PGMTYPE_STK500) {
// Read current target voltage set value
unsigned char osc_pscale;
unsigned char osc_cmatch;
const char *unit_get = {"Hz"};
double f_get = 0.0;
stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale);
stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch);
if(osc_pscale) {
int prescale = 1;
f_get = STK500V2_XTAL / 2;
switch (osc_pscale) {
case 2: prescale = 8; break;
case 3: prescale = 32; break;
case 4: prescale = 64; break;
case 5: prescale = 128; break;
case 6: prescale = 256; break;
case 7: prescale = 1024; break;
}
f_get /= prescale;
f_get /= (osc_cmatch + 1);
f_get = f_to_kHz_MHz(f_get, &unit_get);
}
if (PDATA(pgm)->fosc_get)
msg_info("Oscillator currently set to %.3f %s\n", f_get, unit_get);
// Write target voltage value
else {
const char *unit_set;
double f_set = f_to_kHz_MHz(PDATA(pgm)->fosc_data, &unit_set);
msg_info("Changing oscillator frequency from %.3f %s to %.3f %s\n", f_get, unit_get, f_set, unit_set);
if(pgm->set_fosc(pgm, PDATA(pgm)->fosc_data) < 0)
return -1;
}
} else if(PDATA(pgm)->pgmtype == PGMTYPE_STK600) {
// Read current target voltage set value
unsigned int clock_conf;
stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf);
unsigned int oct = (clock_conf & 0xf000) >> 12u;
unsigned int dac = (clock_conf & 0x0ffc) >> 2u;
double f_get = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0);
const char *unit_get = {"Hz"};
f_get = f_to_kHz_MHz(f_get, &unit_get);
if (PDATA(pgm)->fosc_get)
msg_info("Oscillator currently set to %.3f %s\n", f_get, unit_get);
// Write target voltage value
else {
const char *unit_set;
double f_set = f_to_kHz_MHz(PDATA(pgm)->fosc_data, &unit_set);
msg_info("Changing oscillator frequency from %.3f %s to %.3f %s\n", f_get, unit_get, f_set, unit_set);
if(pgm->set_fosc(pgm, PDATA(pgm)->fosc_data) < 0)
return -1;
}
}
}
/*
* Examine the avrpart's memory definitions, and initialize the page
* caches. For devices/memory that are not page oriented, treat
@@ -1563,6 +1811,157 @@ static void stk500v2_enable(PROGRAMMER *pgm, const AVRPART *p) {
return;
}
static int stk500v2_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
LNODEID ln;
const char *extended_param;
int rv = 0;
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
extended_param = ldata(ln);
if (str_starts(extended_param, "vtarg")) {
if (pgm->extra_features & HAS_VTARG_ADJ) {
// Set target voltage
if (str_starts(extended_param, "vtarg=") ) {
double vtarg_set_val = 0;
int sscanf_success = sscanf(extended_param, "vtarg=%lf", &vtarg_set_val);
PDATA(pgm)->vtarg_data = (double)((int)(vtarg_set_val * 100 + .5)) / 100;
if (sscanf_success < 1 || vtarg_set_val < 0) {
pmsg_error("invalid vtarg value '%s'\n", extended_param);
rv = -1;
break;
}
PDATA(pgm)->vtarg_set = true;
continue;
}
// Get target voltage
else if(str_eq(extended_param, "vtarg")) {
PDATA(pgm)->vtarg_get = true;
continue;
}
}
}
else if (str_starts(extended_param, "varef")) {
if (pgm->extra_features & HAS_VAREF_ADJ) {
int sscanf_success = 0;
double varef_set_val = 0;
// Get new analog reference voltage for channel 0
if (str_starts(extended_param, "varef=")) {
sscanf_success = sscanf(extended_param, "varef=%lf", &varef_set_val);
PDATA(pgm)->varef_channel = 0;
PDATA(pgm)->varef_set = true;
}
// Get new analog reference voltage for channel 0
else if(str_starts(extended_param, "varef0=")) {
sscanf_success = sscanf(extended_param, "varef0=%lf", &varef_set_val);
PDATA(pgm)->varef_channel = 0;
PDATA(pgm)->varef_set = true;
}
// Get new analog reference voltage for channel 1
else if (str_starts(extended_param, "varef1=") && str_contains(pgm->type, "STK600")) {
sscanf_success = sscanf(extended_param, "varef1=%lf", &varef_set_val);
PDATA(pgm)->varef_channel = 1;
PDATA(pgm)->varef_set = true;
}
// Get current analog reference voltage for channel 0
else if(str_eq(extended_param, "varef") || str_eq(extended_param, "varef0")) {
PDATA(pgm)->varef_get = true;
PDATA(pgm)->varef_channel = 0;
continue;
}
// Get current analog reference voltage for channel 1
else if(str_eq(extended_param, "varef1") && str_contains(pgm->type, "STK600")) {
PDATA(pgm)->varef_get = true;
PDATA(pgm)->varef_channel = 1;
continue;
}
// Set analog reference voltage
if (PDATA(pgm)->varef_set) {
PDATA(pgm)->varef_data = (double)((int)(varef_set_val * 100 + .5)) / 100;
if (sscanf_success < 1 || varef_set_val < 0) {
pmsg_error("invalid varef value '%s'\n", extended_param);
PDATA(pgm)->varef_set = false;
rv = -1;
break;
}
continue;
}
}
}
else if (str_starts(extended_param, "fosc")) {
if (pgm->extra_features & HAS_VAREF_ADJ) {
// Set clock generator frequency
if (str_starts(extended_param, "fosc=")) {
char fosc_str[16] = {0};
int sscanf_success = sscanf(extended_param, "fosc=%10s", fosc_str);
if (sscanf_success < 1) {
pmsg_error("invalid fosc value '%s'\n", extended_param);
rv = -1;
break;
}
char *endp;
double v = strtod(fosc_str, &endp);
if (endp == fosc_str){
if (str_eq(fosc_str, "off"))
PDATA(pgm)->fosc_data = 0.0;
else {
pmsg_error("cannot parse fosc value %s\n", fosc_str);
rv = -1;
break;
}
}
if (*endp == 'm' || *endp == 'M')
PDATA(pgm)->fosc_data = v * 1e6;
else if (*endp == 'k' || *endp == 'K')
PDATA(pgm)->fosc_data = v * 1e3;
PDATA(pgm)->fosc_set = true;
continue;
}
// Get clock generator frequency
else if(str_eq(extended_param, "fosc")) {
PDATA(pgm)->fosc_get = true;
continue;
}
}
}
else if (str_eq(extended_param, "help")) {
char *prg = (char *)ldata(lfirst(pgm->id));
msg_error("%s -c %s extended options:\n", progname, prg);
if (pgm->extra_features & HAS_VTARG_ADJ) {
msg_error(" -xvtarg Read target supply voltage\n");
msg_error(" -xvtarg=<arg> Set target supply voltage\n");
}
if (pgm->extra_features & HAS_VAREF_ADJ) {
if (str_contains(pgm->type, "STK500")) {
msg_error(" -xvaref Read analog reference voltage\n");
msg_error(" -xvaref=<arg> Set analog reference voltage\n");
}
else if (str_contains(pgm->type, "STK600")) {
msg_error(" -xvaref Read channel 0 analog reference voltage\n");
msg_error(" -xvaref0 Alias for -xvaref\n");
msg_error(" -xvaref1 Read channel 1 analog reference voltage\n");
msg_error(" -xvaref=<arg> Set channel 0 analog reference voltage\n");
msg_error(" -xvaref0=<arg> Alias for -xvaref=<arg>\n");
msg_error(" -xvaref1=<arg> Set channel 1 analog reference voltage\n");
}
}
if (pgm->extra_features & HAS_FOSC_ADJ) {
msg_error(" -xfosc Read oscillator clock frequency\n");
msg_error(" -xfosc=<arg>[M|k]|off Set oscillator clock frequency\n");
}
msg_error(" -xhelp Show this help menu and exit\n");
exit(0);
}
pmsg_error("invalid extended parameter '%s'\n", extended_param);
rv = -1;
}
return rv;
}
static int stk500v2_jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
LNODEID ln;
const char *extended_param;
@@ -1619,6 +2018,29 @@ static int stk500v2_jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extp
}
}
else if (str_starts(extended_param, "vtarg")) {
if (pgm->extra_features & HAS_VTARG_ADJ) {
// Set target voltage
if (str_starts(extended_param, "vtarg=") ) {
double vtarg_set_val = 0;
int sscanf_success = sscanf(extended_param, "vtarg=%lf", &vtarg_set_val);
PDATA(pgm)->vtarg_data = (double)((int)(vtarg_set_val * 100 + .5)) / 100;
if (sscanf_success < 1 || vtarg_set_val < 0) {
pmsg_error("invalid vtarg value '%s'\n", extended_param);
rv = -1;
break;
}
PDATA(pgm)->vtarg_set = true;
}
// Get target voltage
else if(str_eq(extended_param, "vtarg"))
PDATA(pgm)->vtarg_get = true;
else
break;
continue;
}
}
else if (str_eq(extended_param, "help")) {
char *prg = (char *)ldata(lfirst(pgm->id));
msg_error("%s -c %s extended options:\n", progname, prg);
@@ -1628,6 +2050,10 @@ static int stk500v2_jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extp
msg_error(" -xvtarg_switch Read on-board target voltage switch state\n");
msg_error(" -xvtarg_switch=<0..1> Set on-board target voltage switch state\n");
}
if (pgm->extra_features & HAS_VTARG_ADJ) {
msg_error(" -xvtarg Read on-board target supply voltage\n");
msg_error(" -xvtarg=<arg> Set on-board target supply voltage\n");
}
msg_error (" -xhelp Show this help menu and exit\n");
exit(0);
}
@@ -2925,7 +3351,6 @@ static int stk600_set_vtarget(const PROGRAMMER *pgm, double v) {
unsigned char utarg;
unsigned int uaref;
int rv;
utarg = (unsigned)((v + 0.049) * 10);
if (stk500v2_getparm2(pgm, PARAM2_AREF0, &uaref) != 0) {
@@ -3206,7 +3631,6 @@ static void stk500v2_display(const PROGRAMMER *pgm, const char *p) {
PROGRAMMER *pgmcp = pgm_dup(pgm);
pgmcp->cookie = PDATA(pgm)->chained_pdata;
jtag3_display(pgmcp, p);
msg_info("\n");
pgm_free(pgmcp);
}
stk500v2_print_parms1(pgm, p, stderr);
@@ -3214,20 +3638,6 @@ static void stk500v2_display(const PROGRAMMER *pgm, const char *p) {
return;
}
static double
f_to_kHz_MHz(double f, const char **unit)
{
if (f > 1e6) {
f /= 1e6;
*unit = "MHz";
} else if (f > 1e3) {
f /= 1000;
*unit = "kHz";
} else
*unit = "Hz";
return f;
}
static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) {
unsigned char vtarget = 0, vadjust = 0, osc_pscale = 0, osc_cmatch = 0, sck_duration =0; //XXX 0 is not correct, check caller
@@ -3301,7 +3711,7 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp
pgmcp->id = lcreat(NULL, 0);
// Copy pgm->id contents over to pgmcp->id
for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln))
ladd(pgmcp->id, cfg_strdup("stk500v2_print_parms1()", ldata(ln)));
ladd(pgmcp->id, cfg_strdup("stk500v2_display()", ldata(ln)));
jtag3_print_parms1(pgmcp, p, fp);
pgm_free(pgmcp);
}
@@ -4280,14 +4690,14 @@ static void stk600_setup_xprog(PROGRAMMER * pgm)
*/
static void stk600_setup_isp(PROGRAMMER * pgm)
{
pgm->program_enable = stk500v2_program_enable;
pgm->disable = stk500v2_disable;
pgm->read_byte = stk500isp_read_byte;
pgm->write_byte = stk500isp_write_byte;
pgm->paged_load = stk500v2_paged_load;
pgm->paged_write = stk500v2_paged_write;
pgm->page_erase = stk500v2_page_erase;
pgm->chip_erase = stk500v2_chip_erase;
pgm->program_enable = stk500v2_program_enable;
pgm->disable = stk500v2_disable;
pgm->read_byte = stk500isp_read_byte;
pgm->write_byte = stk500isp_write_byte;
pgm->paged_load = stk500v2_paged_load;
pgm->paged_write = stk500v2_paged_write;
pgm->page_erase = stk500v2_page_erase;
pgm->chip_erase = stk500v2_chip_erase;
}
const char stk500v2_desc[] = "Atmel STK500 Version 2.x firmware";
@@ -4317,14 +4727,22 @@ void stk500v2_initpgm(PROGRAMMER *pgm) {
pgm->paged_load = stk500v2_paged_load;
pgm->page_erase = stk500v2_page_erase;
pgm->print_parms = stk500v2_print_parms;
pgm->set_vtarget = stk500v2_set_vtarget;
pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period;
pgm->perform_osccal = stk500v2_perform_osccal;
pgm->parseextparams = stk500v2_parseextparms;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256;
/*
* hardware dependent functions
*/
if (pgm->extra_features & HAS_VTARG_ADJ)
pgm->set_vtarget = stk500v2_set_vtarget;
if (pgm->extra_features & HAS_VAREF_ADJ)
pgm->set_varef = stk500v2_set_varef;
if (pgm->extra_features & HAS_FOSC_ADJ)
pgm->set_fosc = stk500v2_set_fosc;
}
const char stk500pp_desc[] = "Atmel STK500 V2 in parallel programming mode";
@@ -4352,13 +4770,21 @@ void stk500pp_initpgm(PROGRAMMER *pgm) {
pgm->paged_write = stk500pp_paged_write;
pgm->paged_load = stk500pp_paged_load;
pgm->print_parms = stk500v2_print_parms;
pgm->set_vtarget = stk500v2_set_vtarget;
pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period;
pgm->parseextparams = stk500v2_parseextparms;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256;
/*
* hardware dependent functions
*/
if (pgm->extra_features & HAS_VTARG_ADJ)
pgm->set_vtarget = stk500v2_set_vtarget;
if (pgm->extra_features & HAS_VAREF_ADJ)
pgm->set_varef = stk500v2_set_varef;
if (pgm->extra_features & HAS_FOSC_ADJ)
pgm->set_fosc = stk500v2_set_fosc;
}
const char stk500hvsp_desc[] = "Atmel STK500 V2 in high-voltage serial programming mode";
@@ -4386,13 +4812,21 @@ void stk500hvsp_initpgm(PROGRAMMER *pgm) {
pgm->paged_write = stk500hvsp_paged_write;
pgm->paged_load = stk500hvsp_paged_load;
pgm->print_parms = stk500v2_print_parms;
pgm->set_vtarget = stk500v2_set_vtarget;
pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period;
pgm->parseextparams = stk500v2_parseextparms;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256;
/*
* hardware dependent functions
*/
if (pgm->extra_features & HAS_VTARG_ADJ)
pgm->set_vtarget = stk500v2_set_vtarget;
if (pgm->extra_features & HAS_VAREF_ADJ)
pgm->set_varef = stk500v2_set_varef;
if (pgm->extra_features & HAS_FOSC_ADJ)
pgm->set_fosc = stk500v2_set_fosc;
}
const char stk500v2_jtagmkII_desc[] = "Atmel JTAG ICE mkII in ISP mode";
@@ -4487,9 +4921,6 @@ void stk500v2_dragon_pp_initpgm(PROGRAMMER *pgm) {
pgm->paged_write = stk500pp_paged_write;
pgm->paged_load = stk500pp_paged_load;
pgm->print_parms = stk500v2_print_parms;
pgm->set_vtarget = stk500v2_set_vtarget;
pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period_mk2;
pgm->setup = stk500v2_jtagmkII_setup;
pgm->teardown = stk500v2_jtagmkII_teardown;
@@ -4521,9 +4952,6 @@ void stk500v2_dragon_hvsp_initpgm(PROGRAMMER *pgm) {
pgm->paged_write = stk500hvsp_paged_write;
pgm->paged_load = stk500hvsp_paged_load;
pgm->print_parms = stk500v2_print_parms;
pgm->set_vtarget = stk500v2_set_vtarget;
pgm->set_varef = stk500v2_set_varef;
pgm->set_fosc = stk500v2_set_fosc;
pgm->set_sck_period = stk500v2_set_sck_period_mk2;
pgm->setup = stk500v2_jtagmkII_setup;
pgm->teardown = stk500v2_jtagmkII_teardown;
@@ -4562,6 +4990,7 @@ void stk600_initpgm(PROGRAMMER *pgm) {
pgm->set_fosc = stk600_set_fosc;
pgm->set_sck_period = stk600_set_sck_period;
pgm->perform_osccal = stk500v2_perform_osccal;
pgm->parseextparams = stk500v2_parseextparms;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256;
@@ -4596,6 +5025,7 @@ void stk600pp_initpgm(PROGRAMMER *pgm) {
pgm->set_varef = stk600_set_varef;
pgm->set_fosc = stk600_set_fosc;
pgm->set_sck_period = stk600_set_sck_period;
pgm->parseextparams = stk500v2_parseextparms;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256;
@@ -4630,6 +5060,7 @@ void stk600hvsp_initpgm(PROGRAMMER *pgm) {
pgm->set_varef = stk600_set_varef;
pgm->set_fosc = stk600_set_fosc;
pgm->set_sck_period = stk600_set_sck_period;
pgm->parseextparams = stk500v2_parseextparms;
pgm->setup = stk500v2_setup;
pgm->teardown = stk500v2_teardown;
pgm->page_size = 256;
@@ -4644,7 +5075,6 @@ void stk500v2_jtag3_initpgm(PROGRAMMER *pgm) {
* mandatory functions
*/
pgm->initialize = stk500v2_jtag3_initialize;
pgm->parseextparams = stk500v2_jtag3_parseextparms;
pgm->display = stk500v2_display;
pgm->enable = stk500v2_enable;
pgm->disable = stk500v2_jtag3_disable;
@@ -4665,10 +5095,14 @@ void stk500v2_jtag3_initpgm(PROGRAMMER *pgm) {
pgm->print_parms = stk500v2_print_parms;
pgm->set_sck_period = stk500v2_jtag3_set_sck_period;
pgm->perform_osccal = stk500v2_perform_osccal;
pgm->parseextparams = stk500v2_jtag3_parseextparms;
pgm->setup = stk500v2_jtag3_setup;
pgm->teardown = stk500v2_jtag3_teardown;
pgm->page_size = 256;
/*
* hardware dependent functions
*/
if (pgm->extra_features & HAS_VTARG_ADJ)
pgm->set_vtarget = jtag3_set_vtarget;
}

View File

@@ -280,6 +280,22 @@ struct pdata
bool vtarg_switch_set;
unsigned char vtarg_switch_data[2];
/* Get/set flags for adjustable target voltage */
bool vtarg_get;
bool vtarg_set;
double vtarg_data;
/* Get/set flags for adjustable analog reference voltage */
bool varef_get;
bool varef_set;
int varef_channel;
double varef_data;
/* Get/set flags for programmable clock generator */
bool fosc_get;
bool fosc_set;
double fosc_data;
const AVRPART *lastpart;
/* Start address of Xmega boot area */