diff --git a/src/jtag3.c b/src/jtag3.c index 3126f21d2..e2b8dc29b 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2402,6 +2402,49 @@ static int jtag3_set_sck_period(const PROGRAMMER *pgm, double v) { } +static int jtag3_get_sck_period(const PROGRAMMER *pgm, double *v) { + unsigned char conn, arch; + unsigned char buf[2]; + *v = 0; + + if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CONNECTION, &conn, 1) < 0) { + pmsg_error("cannot obtain connection type\n"); + return -1; + } + if (jtag3_getparm(pgm, SCOPE_AVR, 0, PARM3_ARCH, &arch, 1) < 0) { + pmsg_error("cannot obtain target architecture\n"); + return -1; + } + + if (conn == PARM3_CONN_JTAG) { + if (arch == PARM3_ARCH_XMEGA) { + if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0) { + pmsg_error("cannot read Xmega JTAG clock speed\n"); + return -1; + } + } else { + if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0) { + pmsg_error("cannot read JTAG clock speed\n"); + return -1; + } + } + } else if (conn & (PARM3_CONN_PDI | PARM3_CONN_UPDI)) { + if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0) { + pmsg_error("cannot read PDI/UPDI clock speed\n"); + return -1; + } + } + + if (b2_to_u16(buf) <= 0) { + pmsg_error("cannot calculate programmer clock speed\n"); + return -1; + } + *v = 1.0/(1000*b2_to_u16(buf)); + + return 0; +} + + /* * Read (an) emulator parameter(s). */ @@ -2499,7 +2542,7 @@ int jtag3_read_sib(const PROGRAMMER *pgm, const AVRPART *p, char *sib) { return status; memcpy(sib, resp+3, AVR_SIBLEN); - sib[AVR_SIBLEN] = 0; // Zero terminate string + sib[AVR_SIBLEN-1] = 0; // Zero terminate string pmsg_debug("jtag3_read_sib(): received SIB: %s\n", sib); free(resp); return 0; @@ -2549,6 +2592,18 @@ int jtag3_set_vtarget(const PROGRAMMER *pgm, double v) { return 0; } +int jtag3_get_vtarget(const PROGRAMMER *pgm, double *v) { + unsigned char buf[2]; + + if(jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) { + pmsg_error("cannot read target voltage\n"); + return -1; + } + + *v = b2_to_u16(buf)/1000.0; + return 0; +} + void jtag3_display(const PROGRAMMER *pgm, const char *p) { unsigned char parms[5]; unsigned char *resp = NULL; @@ -3212,6 +3267,7 @@ void jtag3_initpgm(PROGRAMMER *pgm) { pgm->page_erase = jtag3_page_erase; pgm->print_parms = jtag3_print_parms; pgm->set_sck_period = jtag3_set_sck_period; + pgm->get_sck_period = jtag3_get_sck_period; pgm->parseextparams = jtag3_parseextparms; pgm->setup = jtag3_setup; pgm->teardown = jtag3_teardown; @@ -3222,6 +3278,8 @@ void jtag3_initpgm(PROGRAMMER *pgm) { /* * hardware dependent functions */ + if (pgm->extra_features & HAS_VTARG_READ) + pgm->get_vtarget = jtag3_get_vtarget; if (pgm->extra_features & HAS_VTARG_ADJ) pgm->set_vtarget = jtag3_set_vtarget; } @@ -3261,6 +3319,8 @@ void jtag3_dw_initpgm(PROGRAMMER *pgm) { /* * hardware dependent functions */ + if (pgm->extra_features & HAS_VTARG_READ) + pgm->get_vtarget = jtag3_get_vtarget; if (pgm->extra_features & HAS_VTARG_ADJ) pgm->set_vtarget = jtag3_set_vtarget; } @@ -3292,6 +3352,7 @@ 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->get_sck_period = jtag3_get_sck_period; pgm->parseextparams = jtag3_parseextparms; pgm->setup = jtag3_setup; pgm->teardown = jtag3_teardown; @@ -3302,6 +3363,8 @@ void jtag3_pdi_initpgm(PROGRAMMER *pgm) { /* * hardware dependent functions */ + if (pgm->extra_features & HAS_VTARG_READ) + pgm->get_vtarget = jtag3_get_vtarget; if (pgm->extra_features & HAS_VTARG_ADJ) pgm->set_vtarget = jtag3_set_vtarget; } @@ -3333,6 +3396,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->get_sck_period = jtag3_get_sck_period; pgm->parseextparams = jtag3_parseextparms; pgm->setup = jtag3_setup; pgm->teardown = jtag3_teardown; @@ -3345,6 +3409,8 @@ void jtag3_updi_initpgm(PROGRAMMER *pgm) { /* * hardware dependent functions */ + if (pgm->extra_features & HAS_VTARG_READ) + pgm->get_vtarget = jtag3_get_vtarget; if (pgm->extra_features & HAS_VTARG_ADJ) pgm->set_vtarget = jtag3_set_vtarget; } @@ -3380,4 +3446,10 @@ void jtag3_tpi_initpgm(PROGRAMMER *pgm) { pgm->teardown = jtag3_teardown; pgm->page_size = 256; pgm->flag = PGM_FL_IS_TPI; + + /* + * hardware dependent functions + */ + if (pgm->extra_features & HAS_VTARG_READ) + pgm->get_vtarget = jtag3_get_vtarget; } diff --git a/src/jtag3.h b/src/jtag3.h index 85ca44418..9eb47e0f1 100644 --- a/src/jtag3.h +++ b/src/jtag3.h @@ -41,6 +41,7 @@ int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen void jtag3_display(const PROGRAMMER *pgm, const char *p); void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp); int jtag3_set_vtarget(const PROGRAMMER *pgm, double voltage); +int jtag3_get_vtarget(const PROGRAMMER *pgm, double *voltage); extern const char jtag3_desc[]; extern const char jtag3_dw_desc[]; extern const char jtag3_pdi_desc[]; diff --git a/src/jtagmkII.c b/src/jtagmkII.c index f17122140..a1722f20e 100644 --- a/src/jtagmkII.c +++ b/src/jtagmkII.c @@ -2424,6 +2424,24 @@ static int jtagmkII_set_sck_period(const PROGRAMMER *pgm, double v) { return jtagmkII_setparm(pgm, PAR_OCD_JTAG_CLK, &dur); } +static int jtagmkII_get_sck_period(const PROGRAMMER *pgm, double *v) { + unsigned char buf[4]; + double clk; + if (jtagmkII_getparm(pgm, PAR_OCD_JTAG_CLK, buf) < 0) { + pmsg_error("cannot read JTAG clock speed\n"); + return -1; + } + + if (buf[0] == 0) + clk = 6.4e6; + else if (buf[0] == 1) + clk = 2.8e6; + else + clk = 5.35e6 / buf[0]; + + *v = 1 / clk; + return 0; +} /* * Read an emulator parameter. As the maximal parameter length is 4 @@ -3614,6 +3632,7 @@ void jtagmkII_initpgm(PROGRAMMER *pgm) { pgm->page_erase = jtagmkII_page_erase; pgm->print_parms = jtagmkII_print_parms; pgm->set_sck_period = jtagmkII_set_sck_period; + pgm->get_sck_period = jtagmkII_get_sck_period; pgm->parseextparams = jtagmkII_parseextparms; pgm->setup = jtagmkII_setup; pgm->teardown = jtagmkII_teardown; @@ -3747,6 +3766,7 @@ void jtagmkII_dragon_initpgm(PROGRAMMER *pgm) { pgm->page_erase = jtagmkII_page_erase; pgm->print_parms = jtagmkII_print_parms; pgm->set_sck_period = jtagmkII_set_sck_period; + pgm->get_sck_period = jtagmkII_get_sck_period; pgm->parseextparams = jtagmkII_parseextparms; pgm->setup = jtagmkII_setup; pgm->teardown = jtagmkII_teardown; diff --git a/src/main.c b/src/main.c index 7c15750d8..0d8cca5b7 100644 --- a/src/main.c +++ b/src/main.c @@ -680,50 +680,24 @@ int main(int argc, char * argv []) } break; - case 'B': /* specify JTAG ICE bit clock period */ + case 'B': /* specify bit clock period */ bitclock = strtod(optarg, &e); - if (*e != 0) { - /* trailing unit of measure present */ - int suffixlen = strlen(e); - switch (suffixlen) { - case 2: - if ((e[0] != 'h' && e[0] != 'H') || e[1] != 'z') - bitclock = 0.0; - else - /* convert from Hz to microseconds */ - bitclock = 1E6 / bitclock; - break; - - case 3: - if ((e[1] != 'h' && e[1] != 'H') || e[2] != 'z') - bitclock = 0.0; - else { - switch (e[0]) { - case 'M': - case 'm': /* no Millihertz here :) */ - bitclock = 1.0 / bitclock; - break; - - case 'k': - bitclock = 1E3 / bitclock; - break; - - default: - bitclock = 0.0; - break; - } - } - break; - - default: - bitclock = 0.0; - break; - } - if (bitclock == 0.0) - pmsg_error("invalid bit clock unit of measure '%s'\n", e); + if ((e == optarg) || bitclock <= 0.0) { + pmsg_error("invalid bit clock period %s\n", optarg); + exit(1); } - if ((e == optarg) || bitclock == 0.0) { - pmsg_error("invalid bit clock period specified '%s'\n", optarg); + while(*e && isascii(*e & 0xff) && isspace(*e & 0xff)) + e++; + if(*e == 0 || str_caseeq(e, "us")) // us is optional and the default + ; + else if(str_caseeq(e, "m") || str_caseeq(e, "mhz")) + bitclock = 1 / bitclock; + else if(str_caseeq(e, "k") || str_caseeq(e, "khz")) + bitclock = 1e3 / bitclock; + else if(str_caseeq(e, "hz")) + bitclock = 1e6 / bitclock; + else { + pmsg_error("invalid bit clock unit %s\n", e); exit(1); } break; diff --git a/src/stk500v2.c b/src/stk500v2.c index 9d7e9e47d..f94e37c6b 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -3237,10 +3237,20 @@ static int stk500v2_set_varef(const PROGRAMMER *pgm, unsigned int chan /* unused } -static int stk500v2_get_varef(const PROGRAMMER *pgm, unsigned int chan /* unused */, - double *v) +static int stk500v2_get_varef(const PROGRAMMER *pgm, unsigned int chan, double *v) { - *v = stk500v2_varef_value(pgm); + if(PDATA(pgm)->pgmtype == PGMTYPE_STK500) + *v = stk500v2_varef_value(pgm); + else if(PDATA(pgm)->pgmtype == PGMTYPE_STK600) { + if(chan == 0) + *v = stk600_varef_0_value(pgm); + else if(chan == 1) + *v = stk600_varef_1_value(pgm); + else { + pmsg_error("invalid Varef channel %d specified\n", chan); + return -1; + } + } return 0; } @@ -3541,6 +3551,25 @@ static int stk500v2_jtag3_set_sck_period(const PROGRAMMER *pgm, double v) { return 0; } +static int stk500v2_jtag3_get_sck_period(const PROGRAMMER *pgm, double *v) { + unsigned char cmd[4]; + *v = 0; + + cmd[0] = CMD_GET_SCK; + if (stk500v2_jtag3_send(pgm, cmd, 1) < 0 || stk500v2_jtag3_recv(pgm, cmd, 4) < 2) { + pmsg_error("cannot read ISP clock speed\n"); + return -1; + } + + unsigned int sck = cmd[1] | (cmd[2] << 8); + if(!sck) { + pmsg_error("reported ISP clock speed not valid\n"); + return -1; + } + *v = 1 / (1000.0 * sck); + return 0; +} + static int stk500v2_getparm(const PROGRAMMER *pgm, unsigned char parm, unsigned char *value) { unsigned char buf[32]; @@ -3904,7 +3933,7 @@ static void stk500v2_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp } fmsg_out(fp, "%sSCK period : %.1f us\n", p, stk500v2_sck_duration_value(pgm)); if (pgm->extra_features & HAS_FOSC_ADJ) { - f = stk500v2_sck_duration_value(pgm); + f = stk500v2_fosc_value(pgm); f = f_to_kHz_MHz(f, &unit); fmsg_out(fp, "%sOscillator : %.3f %s\n", p, f, unit); } @@ -5048,6 +5077,7 @@ void stk500v2_jtagmkII_initpgm(PROGRAMMER *pgm) { pgm->page_erase = NULL; pgm->print_parms = stk500v2_print_parms; pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->get_sck_period = stk500v2_get_sck_period; pgm->perform_osccal = stk500v2_perform_osccal; pgm->setup = stk500v2_jtagmkII_setup; pgm->teardown = stk500v2_jtagmkII_teardown; @@ -5082,6 +5112,8 @@ void stk500v2_dragon_isp_initpgm(PROGRAMMER *pgm) { pgm->page_erase = NULL; pgm->print_parms = stk500v2_print_parms; pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->get_sck_period = stk500v2_get_sck_period; + pgm->perform_osccal = stk500v2_perform_osccal; pgm->setup = stk500v2_jtagmkII_setup; pgm->teardown = stk500v2_jtagmkII_teardown; pgm->page_size = 256; @@ -5113,6 +5145,7 @@ void stk500v2_dragon_pp_initpgm(PROGRAMMER *pgm) { pgm->paged_load = stk500pp_paged_load; pgm->print_parms = stk500v2_print_parms; pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->get_sck_period = stk500v2_get_sck_period; pgm->setup = stk500v2_jtagmkII_setup; pgm->teardown = stk500v2_jtagmkII_teardown; pgm->page_size = 256; @@ -5144,6 +5177,7 @@ void stk500v2_dragon_hvsp_initpgm(PROGRAMMER *pgm) { pgm->paged_load = stk500hvsp_paged_load; pgm->print_parms = stk500v2_print_parms; pgm->set_sck_period = stk500v2_set_sck_period_mk2; + pgm->get_sck_period = stk500v2_get_sck_period; pgm->setup = stk500v2_jtagmkII_setup; pgm->teardown = stk500v2_jtagmkII_teardown; pgm->page_size = 256; @@ -5177,9 +5211,13 @@ void stk600_initpgm(PROGRAMMER *pgm) { pgm->page_erase = NULL; pgm->print_parms = stk500v2_print_parms; pgm->set_vtarget = stk600_set_vtarget; + pgm->get_vtarget = stk500v2_get_vtarget; pgm->set_varef = stk600_set_varef; + pgm->get_varef = stk500v2_get_varef; pgm->set_fosc = stk600_set_fosc; + pgm->get_fosc = stk500v2_get_fosc; pgm->set_sck_period = stk600_set_sck_period; + pgm->get_sck_period = stk500v2_get_sck_period; pgm->perform_osccal = stk500v2_perform_osccal; pgm->parseextparams = stk500v2_parseextparms; pgm->setup = stk500v2_setup; @@ -5213,9 +5251,13 @@ void stk600pp_initpgm(PROGRAMMER *pgm) { pgm->paged_load = stk500pp_paged_load; pgm->print_parms = stk500v2_print_parms; pgm->set_vtarget = stk600_set_vtarget; + pgm->get_vtarget = stk500v2_get_vtarget; pgm->set_varef = stk600_set_varef; + pgm->get_varef = stk500v2_get_varef; pgm->set_fosc = stk600_set_fosc; + pgm->get_fosc = stk500v2_get_fosc; pgm->set_sck_period = stk600_set_sck_period; + pgm->get_sck_period = stk500v2_get_sck_period; pgm->parseextparams = stk500v2_parseextparms; pgm->setup = stk500v2_setup; pgm->teardown = stk500v2_teardown; @@ -5248,9 +5290,13 @@ void stk600hvsp_initpgm(PROGRAMMER *pgm) { pgm->paged_load = stk500hvsp_paged_load; pgm->print_parms = stk500v2_print_parms; pgm->set_vtarget = stk600_set_vtarget; + pgm->get_vtarget = stk500v2_get_vtarget; pgm->set_varef = stk600_set_varef; + pgm->get_varef = stk500v2_get_varef; pgm->set_fosc = stk600_set_fosc; + pgm->get_fosc = stk500v2_get_fosc; pgm->set_sck_period = stk600_set_sck_period; + pgm->get_sck_period = stk500v2_get_sck_period; pgm->parseextparams = stk500v2_parseextparms; pgm->setup = stk500v2_setup; pgm->teardown = stk500v2_teardown; @@ -5285,6 +5331,7 @@ void stk500v2_jtag3_initpgm(PROGRAMMER *pgm) { pgm->page_erase = NULL; pgm->print_parms = stk500v2_print_parms; pgm->set_sck_period = stk500v2_jtag3_set_sck_period; + pgm->get_sck_period = stk500v2_jtag3_get_sck_period; pgm->perform_osccal = stk500v2_perform_osccal; pgm->parseextparams = stk500v2_jtag3_parseextparms; pgm->setup = stk500v2_jtag3_setup; @@ -5295,5 +5342,7 @@ void stk500v2_jtag3_initpgm(PROGRAMMER *pgm) { * hardware dependent functions */ if (pgm->extra_features & HAS_VTARG_ADJ) - pgm->set_vtarget = jtag3_set_vtarget; + pgm->set_vtarget = jtag3_set_vtarget; + if (pgm->extra_features & HAS_VTARG_READ) + pgm->get_vtarget = jtag3_get_vtarget; } diff --git a/src/term.c b/src/term.c index fe9c598ae..37122ac5f 100644 --- a/src/term.c +++ b/src/term.c @@ -110,7 +110,7 @@ struct command cmd[] = { { "vtarg", cmd_vtarg, _fo(set_vtarget), "set or get the target voltage" }, { "varef", cmd_varef, _fo(set_varef), "set or get the analog reference voltage" }, { "fosc", cmd_fosc, _fo(set_fosc), "set or get the oscillator frequency" }, - { "sck", cmd_sck, _fo(set_sck_period), "set or get the SCK period" }, + { "sck", cmd_sck, _fo(set_sck_period), "set or get the SCK period or frequency" }, { "spi", cmd_spi, _fo(setpin), "enter direct SPI mode" }, { "pgm", cmd_pgm, _fo(setpin), "return to programming mode" }, { "verbose", cmd_verbose, _fo(open), "display or set -v verbosity level" }, @@ -1947,26 +1947,40 @@ static int cmd_sck(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv if (argc == 1 && pgm->get_sck_period){ if ((rc = pgm->get_sck_period(pgm, &v)) != 0) { - pmsg_error("(fosc) unable to get sck period (rc = %d)\n", rc); + pmsg_error("(fosc) unable to get SCK period (rc = %d)\n", rc); return -3; } - term_out("SCK period = %.1f us\n", v * 1e6 ); + term_out("SCK period = %.1f us\n", v * 1e6); + term_out("SCK freq = %d kHz\n", (int)(0.001/v)); return 0; } if(argc != 2 || (argc > 1 && str_eq(argv[1], "-?"))) { msg_error( "Syntax: sck \n" - "Function: set the SCK period\n" + "Function: set the SCK period in us or frequency in [kM]Hz\n" ); return -1; } + v = strtod(argv[1], &endp); - if (endp == argv[1]) { - pmsg_error("(sck) cannot parse period %s\n", argv[1]); + if ((endp == argv[1]) || v <= 0.0) { + pmsg_error("(sck) invalid bit clock period %s\n", argv[1]); + return -1; + } + if(*endp == 0 || str_caseeq(endp, "us")) // us is optional and the default + ; + else if(str_caseeq(endp, "m") || str_caseeq(endp, "mhz")) + v = 1 / v; + else if(str_caseeq(endp, "k") || str_caseeq(endp, "khz")) + v = 1e3 / v; + else if(str_caseeq(endp, "hz")) + v = 1e6 / v; + else { + pmsg_error("(sck) invalid bit clock unit %s\n", endp); return -1; } - v *= 1e-6; // Convert from microseconds to seconds + v *= 1e-6; // us to s if ((rc = pgm->set_sck_period(pgm, v)) != 0) { pmsg_error("(sck) unable to set SCK period (rc = %d)\n", rc); return -3;