From 1f3f2ccbdcdbfd3f19664687ce8de4ac8e4864bb Mon Sep 17 00:00:00 2001 From: MCUdude Date: Sun, 16 Apr 2023 19:33:22 +0200 Subject: [PATCH 01/33] Add support for HAS_FOSC_ADJ in avrdude.conf --- src/config.c | 1 + src/developer_opts.c | 2 ++ src/lexer.l | 2 +- src/libavrdude.h | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 7bf83095..2800ed0f 100644 --- a/src/config.c +++ b/src/config.c @@ -352,6 +352,7 @@ TOKEN *new_constant(const char *con) { !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("HAS_FOSC_ADJ", con)? HAS_FOSC_ADJ: !strcmp("pseudo", con)? 2: !strcmp("yes", con) || !strcmp("true", con)? 1: !strcmp("no", con) || !strcmp("false", con)? 0: diff --git a/src/developer_opts.c b/src/developer_opts.c index 83070ea5..1db1d38d 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -256,6 +256,8 @@ 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"); return mode + (mode[1] == 0? 0: 4); } diff --git a/src/lexer.l b/src/lexer.l index 5a568ae6..ac0e7db2 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -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) | yes|no|pseudo | true|false ) { /* Constants */ yylval = new_constant(yytext); return TKN_NUMBER; diff --git a/src/libavrdude.h b/src/libavrdude.h index 01105bc0..1ef6381f 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -215,6 +215,7 @@ typedef struct opcode { #define HAS_VTARG_SWITCH 2 #define HAS_VTARG_ADJ 4 #define HAS_VTARG_READ 8 +#define HAS_FOSC_ADJ 16 #define AVR_FAMILYIDLEN 7 #define AVR_SIBLEN 16 From 5c85a5a2fb0eea9291f184be6a1e6fe06a136a36 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 19:36:19 +0200 Subject: [PATCH 02/33] Add HAS_AREF_ADJ --- src/avrdude.conf.in | 13 ++++++++++--- src/config.c | 1 + src/developer_opts.c | 2 ++ src/lexer.l | 2 +- src/libavrdude.h | 1 + 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 8e22d75d..d0f52c4f 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -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; ; @@ -1333,6 +1338,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 +1351,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 +1364,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 +1377,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 +1390,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; ; diff --git a/src/config.c b/src/config.c index 2800ed0f..0f7dada1 100644 --- a/src/config.c +++ b/src/config.c @@ -353,6 +353,7 @@ TOKEN *new_constant(const char *con) { !strcmp("HAS_VTARG_ADJ", con)? HAS_VTARG_ADJ: !strcmp("HAS_VTARG_READ", con)? HAS_VTARG_READ: !strcmp("HAS_FOSC_ADJ", con)? HAS_FOSC_ADJ: + !strcmp("HAS_AREF_ADJ", con)? HAS_AREF_ADJ: !strcmp("pseudo", con)? 2: !strcmp("yes", con) || !strcmp("true", con)? 1: !strcmp("no", con) || !strcmp("false", con)? 0: diff --git a/src/developer_opts.c b/src/developer_opts.c index 1db1d38d..f9b6a802 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -258,6 +258,8 @@ static char *extra_features_str(int m) { strcat(mode, " | HAS_VTARG_READ"); if(m & HAS_FOSC_ADJ) strcat(mode, " | HAS_FOSC_ADJ"); + if(m & HAS_AREF_ADJ) + strcat(mode, " | HAS_AREF_ADJ"); return mode + (mode[1] == 0? 0: 4); } diff --git a/src/lexer.l b/src/lexer.l index ac0e7db2..be736885 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -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|FOSC_ADJ) | + HAS_(SUFFER|VTARG_SWITCH|VTARG_ADJ|VTARG_READ|FOSC_ADJ|AREF_ADJ) | yes|no|pseudo | true|false ) { /* Constants */ yylval = new_constant(yytext); return TKN_NUMBER; diff --git a/src/libavrdude.h b/src/libavrdude.h index c75f60b8..c7934701 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -216,6 +216,7 @@ typedef struct opcode { #define HAS_VTARG_ADJ 4 #define HAS_VTARG_READ 8 #define HAS_FOSC_ADJ 16 +#define HAS_AREF_ADJ 32 #define AVR_FAMILYIDLEN 7 #define AVR_SIBLEN 16 From e67963bf26cc8a718a974e485d8cc5fd96a2105e Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 19:37:10 +0200 Subject: [PATCH 03/33] Add comments --- src/jtag3.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/jtag3.c b/src/jtag3.c index cb9541e4..92606409 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -3100,6 +3100,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; } @@ -3134,6 +3137,9 @@ void jtag3_dw_initpgm(PROGRAMMER *pgm) { 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; } @@ -3170,6 +3176,9 @@ void jtag3_pdi_initpgm(PROGRAMMER *pgm) { 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; } @@ -3209,6 +3218,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; } From e0f5c552b715cb665e7a0f7cc8fd7f47d8e180bc Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 19:38:55 +0200 Subject: [PATCH 04/33] make set_vtarget, set_varef and set_fosc hardware dependent based on data from avrdude.conf --- src/stk500.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/stk500.c b/src/stk500.c index 6984fb1f..f9114444 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -1300,11 +1300,18 @@ 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->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_AREF_ADJ) + pgm->set_varef = stk500_set_varef; + if (pgm->extra_features & HAS_FOSC_ADJ) + pgm->set_fosc = stk500_set_fosc; } From 50df3a6303409e140e2d5687c1f7be0ca355c16a Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 19:39:26 +0200 Subject: [PATCH 05/33] Fix formatting --- src/stk500v2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/stk500v2.c b/src/stk500v2.c index 9766a7ec..6f6fcefc 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -4280,14 +4280,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"; From e9492b564b8211e7b91e73ace4d6c9a9bf2442ed Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 19:40:09 +0200 Subject: [PATCH 06/33] make stk500v2 set_vtarget, set_varef and set_fosc hardware dependent based on data from avrdude.conf --- src/stk500v2.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/stk500v2.c b/src/stk500v2.c index 6f6fcefc..21d35977 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -4317,14 +4317,21 @@ 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->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_AREF_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 +4359,20 @@ 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->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_AREF_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 +4400,20 @@ 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->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_AREF_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"; From 1078cd656f56004a1c190df6b869ae685ccb9f5b Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 19:40:47 +0200 Subject: [PATCH 07/33] Add non-supported functionality from AVR Dragon --- src/stk500v2.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/stk500v2.c b/src/stk500v2.c index 21d35977..e40cef0f 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -4508,9 +4508,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; @@ -4542,9 +4539,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; From 73469a5e3aef43d067a4d4ac893f6c2e63ce6c60 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 19:41:03 +0200 Subject: [PATCH 08/33] Add comment --- src/stk500v2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/stk500v2.c b/src/stk500v2.c index e40cef0f..d1015c0b 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -4684,6 +4684,9 @@ void stk500v2_jtag3_initpgm(PROGRAMMER *pgm) { 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; } From 7b5867943d167220f600e541cd2942b4c78fa3a9 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 22:16:17 +0200 Subject: [PATCH 09/33] Fix typo --- src/avrdude.conf.in | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index d0f52c4f..0dc7e528 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -1289,7 +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; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_AREF_ADJ; connection_type = serial; ; @@ -1338,7 +1338,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; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_AREF_ADJ; connection_type = serial; ; @@ -1351,7 +1351,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; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_AREF_ADJ; connection_type = serial; ; @@ -1364,7 +1364,7 @@ programmer desc = "Atmel STK600"; type = "stk600"; prog_modes = PM_TPI | PM_ISP | PM_PDI; - extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_AREF_ADJ; connection_type = usb; ; @@ -1377,7 +1377,7 @@ programmer desc = "Atmel STK600 in parallel programming mode"; type = "stk600pp"; prog_modes = PM_HVPP; - extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_AREF_ADJ; connection_type = usb; ; @@ -1390,7 +1390,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 | HAS_FOSC_ADJ | HAS_VAREF_ADJ; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_AREF_ADJ; connection_type = usb; ; From a8b263f1f08676c4bdff3e45344aa85f11d68a88 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 22:18:04 +0200 Subject: [PATCH 10/33] Add -xvtarg to jtag3.c --- src/jtag3.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/jtag3.c b/src/jtag3.c index 92606409..a91c716c 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -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 *); }; @@ -1144,6 +1149,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 +1553,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; + } + // 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); From 723da383b47329475d14c2c1af7026c2a69e93c2 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 22:18:54 +0200 Subject: [PATCH 11/33] pgm->parseextparams is an optional function --- src/jtag3.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/jtag3.c b/src/jtag3.c index a91c716c..4ec066e4 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -3180,6 +3180,7 @@ 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; @@ -3219,6 +3220,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->parseextparams = jtag3_parseextparms; pgm->setup = jtag3_setup; pgm->teardown = jtag3_teardown; pgm->page_size = 256; @@ -3240,7 +3242,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; @@ -3259,6 +3260,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; @@ -3298,6 +3300,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; From 44a6b101ce1908f2a9098ba61ce1717456a00f00 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 22:31:17 +0200 Subject: [PATCH 12/33] Only print programmer-to-target spesific data when... pgm->display is called --- src/jtag3.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 4ec066e4..9f2b08e7 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -1104,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", @@ -2544,7 +2544,8 @@ 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); + jtag3_print_parms1(pgm, progbuf, stderr); free(resp); } @@ -2833,8 +2834,6 @@ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) { return -1; free(resp); - jtag3_print_parms1(pgm, progbuf, stderr); - return 0; } From d53f034ac6553e26f458e7c1f75865b538c3f4d4 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Mon, 17 Apr 2023 23:44:34 +0200 Subject: [PATCH 13/33] Attempt to fix programmer info --- src/jtag3.c | 69 ++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 9f2b08e7..080244d2 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -1114,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 @@ -2545,7 +2548,6 @@ void jtag3_display(const PROGRAMMER *pgm, const char *p) { 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\n", p, sn); - jtag3_print_parms1(pgm, progbuf, stderr); free(resp); } @@ -2554,6 +2556,39 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { unsigned char prog_mode[2]; unsigned char buf[3]; + // 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)); + } + } + if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) return; msg_info("%sVtarget : %.2f V\n", p, b2_to_u16(buf)/1000.0); @@ -2629,38 +2664,6 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { } } - // 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"); } From a02948e2cf045f7f0e49bea61dac37c00e3710bb Mon Sep 17 00:00:00 2001 From: MCUdude Date: Tue, 18 Apr 2023 00:00:49 +0200 Subject: [PATCH 14/33] Last apptempt at trying to fix programmer info in verbose mode --- src/jtag3.c | 14 ++++++----- src/stk500v2.c | 53 ++++++++++++++++++++++++++++++++++++++++-- src/stk500v2_private.h | 5 ++++ 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 080244d2..015845eb 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2556,8 +2556,12 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { unsigned char prog_mode[2]; unsigned char buf[3]; + if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) + return; + msg_info("%sVtarget : %.2f V\n", p, b2_to_u16(buf)/1000.0); + // Print clocks if programmer typ is not TPI - if (strcmp(pgm->type, "JTAGICE3_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; @@ -2589,10 +2593,6 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { } } - if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) - return; - msg_info("%sVtarget : %.2f V\n", p, b2_to_u16(buf)/1000.0); - // Print features unique to the Power Debugger for(LNODEID ln=lfirst(pgm->id); ln; ln=lnext(ln)) { if(str_starts(ldata(ln), "powerdebugger")) { @@ -2663,7 +2663,6 @@ void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp) { break; } } - fmsg_out(fp, "\n"); } @@ -2813,6 +2812,9 @@ static int jtag3_initialize_tpi(const PROGRAMMER *pgm, const AVRPART *p) { unsigned char* resp; int status; + if (verbose && quell_progress < 2) + jtag3_print_parms1(pgm, progbuf, stderr); + pmsg_notice2("jtag3_initialize_tpi() start\n"); cmd[0] = XPRG_CMD_ENTER_PROGMODE; diff --git a/src/stk500v2.c b/src/stk500v2.c index d1015c0b..c5b7daa2 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -377,6 +377,13 @@ 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 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"); @@ -1350,6 +1357,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); /* @@ -1619,6 +1646,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); @@ -3206,7 +3256,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); @@ -3301,7 +3350,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); } diff --git a/src/stk500v2_private.h b/src/stk500v2_private.h index b58cc5b4..f2c27b44 100644 --- a/src/stk500v2_private.h +++ b/src/stk500v2_private.h @@ -280,6 +280,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; + const AVRPART *lastpart; /* Start address of Xmega boot area */ From 15e53a50b2d9889e747fce9382d1243eb82d9c33 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Tue, 18 Apr 2023 00:02:45 +0200 Subject: [PATCH 15/33] add -xvtarg to jtag3 TPI programmers Currently, only the Power Debugger can supply voltage to a TPI device --- src/jtag3.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/jtag3.c b/src/jtag3.c index 015845eb..c77c3ba1 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -2812,6 +2812,26 @@ 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); From d0bd9543c8eccfa7671b7f5593f35af0813a745a Mon Sep 17 00:00:00 2001 From: MCUdude Date: Tue, 18 Apr 2023 23:00:45 +0200 Subject: [PATCH 16/33] Add -xvtarg to stk500/v2 --- src/stk500.c | 37 +++++++++++++++++++----- src/stk500.h | 5 ++++ src/stk500v2.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 109 insertions(+), 9 deletions(-) diff --git a/src/stk500.c b/src/stk500.c index f9114444..c0bbf285 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -570,11 +570,34 @@ 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; + } + // 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)); @@ -966,7 +989,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 +1305,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; @@ -1301,6 +1323,7 @@ void stk500_initpgm(PROGRAMMER *pgm) { pgm->paged_load = stk500_paged_load; pgm->print_parms = stk500_print_parms; pgm->set_sck_period = stk500_set_sck_period; + pgm->parseextparams = stk500_parseextparms; pgm->setup = stk500_setup; pgm->teardown = stk500_teardown; pgm->page_size = 256; diff --git a/src/stk500.h b/src/stk500.h index 3d28b064..d133a696 100644 --- a/src/stk500.h +++ b/src/stk500.h @@ -42,6 +42,11 @@ 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; }; #define PDATA(pgm) ((struct pdata *)(pgm->cookie)) diff --git a/src/stk500v2.c b/src/stk500v2.c index c5b7daa2..49b1b0ec 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -1230,6 +1230,21 @@ 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; + } + } + /* * Examine the avrpart's memory definitions, and initialize the page * caches. For devices/memory that are not page oriented, treat @@ -1442,6 +1457,21 @@ 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; + } + } + /* * Examine the avrpart's memory definitions, and initialize the page * caches. For devices/memory that are not page oriented, treat @@ -1590,6 +1620,43 @@ 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; + } + // Get target voltage + else if(str_eq(extended_param, "vtarg")) + PDATA(pgm)->vtarg_get = true; + else + break; + continue; + } + } + + 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; @@ -2975,7 +3042,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) { @@ -4368,6 +4434,7 @@ void stk500v2_initpgm(PROGRAMMER *pgm) { pgm->print_parms = stk500v2_print_parms; 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; @@ -4409,6 +4476,7 @@ void stk500pp_initpgm(PROGRAMMER *pgm) { pgm->paged_load = stk500pp_paged_load; pgm->print_parms = stk500v2_print_parms; pgm->set_sck_period = stk500v2_set_sck_period; + pgm->parseextparams = stk500v2_parseextparms; pgm->setup = stk500v2_setup; pgm->teardown = stk500v2_teardown; pgm->page_size = 256; @@ -4450,6 +4518,7 @@ void stk500hvsp_initpgm(PROGRAMMER *pgm) { pgm->paged_load = stk500hvsp_paged_load; pgm->print_parms = stk500v2_print_parms; pgm->set_sck_period = stk500v2_set_sck_period; + pgm->parseextparams = stk500v2_parseextparms; pgm->setup = stk500v2_setup; pgm->teardown = stk500v2_teardown; pgm->page_size = 256; @@ -4626,6 +4695,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; @@ -4660,6 +4730,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; @@ -4694,6 +4765,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; @@ -4708,7 +4780,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; @@ -4729,6 +4800,7 @@ 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; From 4733b6b1c721bec09c16250c386099256352c910 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Tue, 18 Apr 2023 23:47:46 +0200 Subject: [PATCH 17/33] Fix -xvtarg for stk500v1 programmers --- src/avrdude.conf.in | 1 + src/stk500.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 0dc7e528..1c7009c7 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -1302,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_AREF_ADJ; connection_type = serial; ; diff --git a/src/stk500.c b/src/stk500.c index c0bbf285..72f2f53c 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -557,6 +557,21 @@ 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; + } + } + return pgm->program_enable(pgm, p); } From dfd850843965694595109dffe54848d135d6532d Mon Sep 17 00:00:00 2001 From: MCUdude Date: Wed, 19 Apr 2023 08:25:37 +0200 Subject: [PATCH 18/33] Rename HAS_AREF_ADJ to HAS_VAREF_ADJ --- src/avrdude.conf.in | 14 +++++++------- src/config.c | 2 +- src/developer_opts.c | 4 ++-- src/lexer.l | 2 +- src/libavrdude.h | 2 +- src/stk500.c | 2 +- src/stk500v2.c | 6 +++--- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 1c7009c7..1e2a6a31 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -1289,7 +1289,7 @@ programmer desc = "Atmel STK500"; type = "stk500generic"; prog_modes = PM_ISP; - extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_AREF_ADJ; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ; connection_type = serial; ; @@ -1302,7 +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_AREF_ADJ; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ; connection_type = serial; ; @@ -1339,7 +1339,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_AREF_ADJ; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ; connection_type = serial; ; @@ -1352,7 +1352,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_AREF_ADJ; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ; connection_type = serial; ; @@ -1365,7 +1365,7 @@ programmer desc = "Atmel STK600"; type = "stk600"; prog_modes = PM_TPI | PM_ISP | PM_PDI; - extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_AREF_ADJ; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ; connection_type = usb; ; @@ -1378,7 +1378,7 @@ programmer desc = "Atmel STK600 in parallel programming mode"; type = "stk600pp"; prog_modes = PM_HVPP; - extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_AREF_ADJ; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ; connection_type = usb; ; @@ -1391,7 +1391,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 | HAS_FOSC_ADJ | HAS_AREF_ADJ; + extra_features = HAS_VTARG_ADJ | HAS_VTARG_READ | HAS_FOSC_ADJ | HAS_VAREF_ADJ; connection_type = usb; ; diff --git a/src/config.c b/src/config.c index 0f7dada1..9534de96 100644 --- a/src/config.c +++ b/src/config.c @@ -353,7 +353,7 @@ TOKEN *new_constant(const char *con) { !strcmp("HAS_VTARG_ADJ", con)? HAS_VTARG_ADJ: !strcmp("HAS_VTARG_READ", con)? HAS_VTARG_READ: !strcmp("HAS_FOSC_ADJ", con)? HAS_FOSC_ADJ: - !strcmp("HAS_AREF_ADJ", con)? HAS_AREF_ADJ: + !strcmp("HAS_VAREF_ADJ", con)? HAS_VAREF_ADJ: !strcmp("pseudo", con)? 2: !strcmp("yes", con) || !strcmp("true", con)? 1: !strcmp("no", con) || !strcmp("false", con)? 0: diff --git a/src/developer_opts.c b/src/developer_opts.c index f9b6a802..7066cef0 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -258,8 +258,8 @@ static char *extra_features_str(int m) { strcat(mode, " | HAS_VTARG_READ"); if(m & HAS_FOSC_ADJ) strcat(mode, " | HAS_FOSC_ADJ"); - if(m & HAS_AREF_ADJ) - strcat(mode, " | HAS_AREF_ADJ"); + if(m & HAS_VAREF_ADJ) + strcat(mode, " | HAS_VAREF_ADJ"); return mode + (mode[1] == 0? 0: 4); } diff --git a/src/lexer.l b/src/lexer.l index be736885..b92154ac 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -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|FOSC_ADJ|AREF_ADJ) | + 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; diff --git a/src/libavrdude.h b/src/libavrdude.h index c7934701..e03a2cd5 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -216,7 +216,7 @@ typedef struct opcode { #define HAS_VTARG_ADJ 4 #define HAS_VTARG_READ 8 #define HAS_FOSC_ADJ 16 -#define HAS_AREF_ADJ 32 +#define HAS_VAREF_ADJ 32 #define AVR_FAMILYIDLEN 7 #define AVR_SIBLEN 16 diff --git a/src/stk500.c b/src/stk500.c index 72f2f53c..5e15ae9b 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -1348,7 +1348,7 @@ void stk500_initpgm(PROGRAMMER *pgm) { */ if (pgm->extra_features & HAS_VTARG_ADJ) pgm->set_vtarget = stk500_set_vtarget; - if (pgm->extra_features & HAS_AREF_ADJ) + 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; diff --git a/src/stk500v2.c b/src/stk500v2.c index 49b1b0ec..026ef956 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -4444,7 +4444,7 @@ void stk500v2_initpgm(PROGRAMMER *pgm) { */ if (pgm->extra_features & HAS_VTARG_ADJ) pgm->set_vtarget = stk500v2_set_vtarget; - if (pgm->extra_features & HAS_AREF_ADJ) + 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; @@ -4486,7 +4486,7 @@ void stk500pp_initpgm(PROGRAMMER *pgm) { */ if (pgm->extra_features & HAS_VTARG_ADJ) pgm->set_vtarget = stk500v2_set_vtarget; - if (pgm->extra_features & HAS_AREF_ADJ) + 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; @@ -4528,7 +4528,7 @@ void stk500hvsp_initpgm(PROGRAMMER *pgm) { */ if (pgm->extra_features & HAS_VTARG_ADJ) pgm->set_vtarget = stk500v2_set_vtarget; - if (pgm->extra_features & HAS_AREF_ADJ) + 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; From dde83a224e74ebcc2d5c3fdb5559a65cd01ed017 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Wed, 19 Apr 2023 11:16:47 +0200 Subject: [PATCH 19/33] Handle invalid vtarg arguments --- src/jtag3.c | 8 ++++---- src/stk500.c | 8 ++++---- src/stk500v2.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index c77c3ba1..2c0cf47e 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -1569,13 +1569,13 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) { break; } PDATA(pgm)->vtarg_set = true; + continue; } // Get target voltage - else if(str_eq(extended_param, "vtarg")) + else if(str_eq(extended_param, "vtarg")) { PDATA(pgm)->vtarg_get = true; - else - break; - continue; + continue; + } } } diff --git a/src/stk500.c b/src/stk500.c index 5e15ae9b..02047f10 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -604,13 +604,13 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) break; } PDATA(pgm)->vtarg_set = true; + continue; } // Get target voltage - else if(str_eq(extended_param, "vtarg")) + else if(str_eq(extended_param, "vtarg")) { PDATA(pgm)->vtarg_get = true; - else - break; - continue; + continue; + } } } diff --git a/src/stk500v2.c b/src/stk500v2.c index 026ef956..ad75c4b0 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -1641,13 +1641,13 @@ static int stk500v2_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) break; } PDATA(pgm)->vtarg_set = true; + continue; } // Get target voltage - else if(str_eq(extended_param, "vtarg")) + else if(str_eq(extended_param, "vtarg")) { PDATA(pgm)->vtarg_get = true; - else - break; - continue; + continue; + } } } From 0e426cc34a14f44b6c381b2cf56d715777945088 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Wed, 19 Apr 2023 11:30:29 +0200 Subject: [PATCH 20/33] Add -xvaref support This makes it possible to adjust the analog reference voltage on STK500v1, STK500v2 and STK600 --- src/stk500.c | 50 +++++++++++++++++++ src/stk500.h | 5 ++ src/stk500v2.c | 110 +++++++++++++++++++++++++++++++++++++++++ src/stk500v2_private.h | 6 +++ 4 files changed, 171 insertions(+) diff --git a/src/stk500.c b/src/stk500.c index 02047f10..e56815e5 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -572,6 +572,23 @@ static int stk500_initialize(const PROGRAMMER *pgm, const AVRPART *p) { } } + // 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; + } + + } + return pgm->program_enable(pgm, p); } @@ -614,6 +631,39 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) } } + else if (str_starts(extended_param, "varef")) { + if (pgm->extra_features & HAS_VAREF_ADJ) { + int sscanf_success; + 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_eq(extended_param, "help")) { char *prg = (char *)ldata(lfirst(pgm->id)); msg_error("%s -c %s extended options:\n", progname, prg); diff --git a/src/stk500.h b/src/stk500.h index d133a696..3e1d70ba 100644 --- a/src/stk500.h +++ b/src/stk500.h @@ -47,6 +47,11 @@ struct pdata { 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; }; #define PDATA(pgm) ((struct pdata *)(pgm->cookie)) diff --git a/src/stk500v2.c b/src/stk500v2.c index ad75c4b0..b26bb3dd 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -1245,6 +1245,37 @@ static int stk500v2_initialize(const PROGRAMMER *pgm, const AVRPART *p) { } } + // 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; + } + } + } + /* * Examine the avrpart's memory definitions, and initialize the page * caches. For devices/memory that are not page oriented, treat @@ -1472,6 +1503,37 @@ static int stk500hv_initialize(const PROGRAMMER *pgm, const AVRPART *p, enum hvm } } + // 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; + } + } + } + /* * Examine the avrpart's memory definitions, and initialize the page * caches. For devices/memory that are not page oriented, treat @@ -1651,6 +1713,54 @@ static int stk500v2_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) } } + else if (str_starts(extended_param, "varef")) { + if (pgm->extra_features & HAS_VAREF_ADJ) { + int sscanf_success; + 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; + } + } + } + pmsg_error("invalid extended parameter '%s'\n", extended_param); rv = -1; } diff --git a/src/stk500v2_private.h b/src/stk500v2_private.h index f2c27b44..c4475723 100644 --- a/src/stk500v2_private.h +++ b/src/stk500v2_private.h @@ -285,6 +285,12 @@ struct pdata 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; + const AVRPART *lastpart; /* Start address of Xmega boot area */ From caa779cb8ad9203869ba81230dfcc5521d2ce61e Mon Sep 17 00:00:00 2001 From: MCUdude Date: Wed, 19 Apr 2023 21:07:27 +0200 Subject: [PATCH 21/33] Add extra_features to native stk500v2 --- src/avrdude.conf.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 1e2a6a31..89be2a2d 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -1327,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; ; From fe7f8298f5ccfa1a6d2821eff24490598df2f969 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Wed, 19 Apr 2023 21:21:51 +0200 Subject: [PATCH 22/33] Add -xfosc --- src/stk500.c | 86 +++++++++++++++++- src/stk500.h | 5 ++ src/stk500v2.c | 199 ++++++++++++++++++++++++++++++++++++++--- src/stk500v2_private.h | 5 ++ 4 files changed, 280 insertions(+), 15 deletions(-) diff --git a/src/stk500.c b/src/stk500.c index e56815e5..bd1b1cfa 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -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); @@ -586,7 +598,42 @@ static int stk500_initialize(const PROGRAMMER *pgm, const AVRPART *p) { 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; + 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); @@ -664,6 +711,43 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) } } + 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); diff --git a/src/stk500.h b/src/stk500.h index 3e1d70ba..fa7818f6 100644 --- a/src/stk500.h +++ b/src/stk500.h @@ -52,6 +52,11 @@ struct pdata { 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)) diff --git a/src/stk500v2.c b/src/stk500v2.c index b26bb3dd..fd69d021 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -384,6 +384,21 @@ u16_to_b2(unsigned char *b, unsigned short l) 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"); @@ -1276,6 +1291,63 @@ static int stk500v2_initialize(const PROGRAMMER *pgm, const AVRPART *p) { } } + // 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; + 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 @@ -1534,6 +1606,82 @@ static int stk500hv_initialize(const PROGRAMMER *pgm, const AVRPART *p, enum hvm } } + // 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; + 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; + } + } + } + +/* +static int stk600_set_fosc(const PROGRAMMER *pgm, double v) { + unsigned int oct, dac; + + oct = 1.443 * log(v / 1039.0); + dac = 2048 - (2078.0 * pow(2, (double)(10 + oct))) / v; + + return stk500v2_setparm2(pgm, PARAM2_CLOCK_CONF, (oct << 12) | (dac << 2)); +} + + stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf); + oct = (clock_conf & 0xf000) >> 12u; + dac = (clock_conf & 0x0ffc) >> 2u; + f = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0); + f = f_to_kHz_MHz(f, &unit); + fmsg_out(fp, "%sOscillator : %.3f %s\n", + p, f, unit); +*/ + /* * Examine the avrpart's memory definitions, and initialize the page * caches. For devices/memory that are not page oriented, treat @@ -1761,6 +1909,43 @@ static int stk500v2_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) } } + 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; + } + } + } + pmsg_error("invalid extended parameter '%s'\n", extended_param); rv = -1; } @@ -3439,20 +3624,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 diff --git a/src/stk500v2_private.h b/src/stk500v2_private.h index c4475723..c160d866 100644 --- a/src/stk500v2_private.h +++ b/src/stk500v2_private.h @@ -291,6 +291,11 @@ struct pdata 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 */ From 0e0124ceecce8f86f127a7d059e01b44aa56fb94 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Wed, 19 Apr 2023 22:10:54 +0200 Subject: [PATCH 23/33] Add -xvtarg, -xvaref and -xfosc to -xhelp --- src/jtag3.c | 4 ++++ src/stk500.c | 16 ++++++++++++++-- src/stk500v2.c | 52 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/jtag3.c b/src/jtag3.c index 2c0cf47e..3669a783 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -1592,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= Set on-board target supply voltage\n"); + } msg_error (" -xhelp Show this help menu and exit\n"); exit(0); } diff --git a/src/stk500.c b/src/stk500.c index bd1b1cfa..c03cece0 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -751,8 +751,20 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) 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= Specify no. connection retry attempts\n"); - msg_error(" -xhelp Show this help menu and exit\n"); + msg_error(" -xattempts= Specify no. connection retry attempts\n"); + if (pgm->extra_features & HAS_VTARG_ADJ) { + msg_error(" -xvtarg Read target supply voltage\n"); + msg_error(" -xvtarg= Set target supply voltage\n"); + } + if (pgm->extra_features & HAS_VAREF_ADJ) { + msg_error(" -xvaref Read analog reference voltage\n"); + msg_error(" -xvaref= Set analog reference voltage\n"); + } + if (pgm->extra_features & HAS_FOSC_ADJ) { + msg_error(" -xfosc Read oscillator clock frequency\n"); + msg_error(" -xfosc=[M|k]|off Set oscillator clock frequency\n"); + } + msg_error(" -xhelp Show this help menu and exit\n"); exit(0); } diff --git a/src/stk500v2.c b/src/stk500v2.c index fd69d021..d298e658 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -1663,25 +1663,6 @@ static int stk500hv_initialize(const PROGRAMMER *pgm, const AVRPART *p, enum hvm } } -/* -static int stk600_set_fosc(const PROGRAMMER *pgm, double v) { - unsigned int oct, dac; - - oct = 1.443 * log(v / 1039.0); - dac = 2048 - (2078.0 * pow(2, (double)(10 + oct))) / v; - - return stk500v2_setparm2(pgm, PARAM2_CLOCK_CONF, (oct << 12) | (dac << 2)); -} - - stk500v2_getparm2(pgm, PARAM2_CLOCK_CONF, &clock_conf); - oct = (clock_conf & 0xf000) >> 12u; - dac = (clock_conf & 0x0ffc) >> 2u; - f = pow(2, (double)oct) * 2078.0 / (2 - (double)dac / 1024.0); - f = f_to_kHz_MHz(f, &unit); - fmsg_out(fp, "%sOscillator : %.3f %s\n", - p, f, unit); -*/ - /* * Examine the avrpart's memory definitions, and initialize the page * caches. For devices/memory that are not page oriented, treat @@ -1946,6 +1927,35 @@ static int stk500v2_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) } } + 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= 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= 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= Set channel 0 analog reference voltage\n"); + msg_error(" -xvaref0= Alias for -xvaref=\n"); + msg_error(" -xvaref1= 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=[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; } @@ -2040,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= Set on-board target supply voltage\n"); + } msg_error (" -xhelp Show this help menu and exit\n"); exit(0); } From 28870323e3cb9dc5b7618a56c6d9fcb7b0ae07b7 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Fri, 21 Apr 2023 12:30:27 +0200 Subject: [PATCH 24/33] Always initialize f_get --- src/stk500.c | 2 +- src/stk500v2.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stk500.c b/src/stk500.c index c03cece0..461d1627 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -606,7 +606,7 @@ static int stk500_initialize(const PROGRAMMER *pgm, const AVRPART *p) { unsigned int osc_pscale; unsigned int osc_cmatch; const char *unit_get = {"Hz"}; - double f_get; + 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) { diff --git a/src/stk500v2.c b/src/stk500v2.c index d298e658..6f39b446 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -1298,7 +1298,7 @@ static int stk500v2_initialize(const PROGRAMMER *pgm, const AVRPART *p) { unsigned char osc_pscale; unsigned char osc_cmatch; const char *unit_get = {"Hz"}; - double f_get; + double f_get = 0.0; stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale); stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch); if(osc_pscale) { @@ -1613,7 +1613,7 @@ static int stk500hv_initialize(const PROGRAMMER *pgm, const AVRPART *p, enum hvm unsigned char osc_pscale; unsigned char osc_cmatch; const char *unit_get = {"Hz"}; - double f_get; + double f_get = 0.0; stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale); stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch); if(osc_pscale) { From d980e58c7a8bb9e73228276d1e1d4fab488a074a Mon Sep 17 00:00:00 2001 From: MCUdude Date: Fri, 21 Apr 2023 12:30:37 +0200 Subject: [PATCH 25/33] replace strcmp with str_eq --- src/config.c | 56 ++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/config.c b/src/config.c index 9534de96..9f40ee9f 100644 --- a/src/config.c +++ b/src/config.c @@ -335,28 +335,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("HAS_FOSC_ADJ", con)? HAS_FOSC_ADJ: - !strcmp("HAS_VAREF_ADJ", con)? HAS_VAREF_ADJ: - !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) { @@ -496,7 +496,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) @@ -521,7 +521,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; } @@ -564,7 +564,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; @@ -572,7 +572,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) @@ -832,9 +832,9 @@ char *cfg_escape(const char *s) { static int cmp_comp(const void *v1, const void *v2) { const Component_t *c1 = v1, *c2 = v2; - int ret = strcmp(c1->name, c2->name); + int ret = str_eq(c1->name, c2->name); - return ret? ret: c1->strct - c2->strct; + return ret? c1->strct - c2->strct: ret; } Component_t *cfg_comp_search(const char *name, int strct) { From b0ca8b6d75ac143923a7cb5def54e940e52754c9 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Fri, 21 Apr 2023 14:03:33 +0200 Subject: [PATCH 26/33] Fix comment that didn't line up with the others --- src/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 9f40ee9f..b8a42e0f 100644 --- a/src/config.c +++ b/src/config.c @@ -564,7 +564,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(str_eq(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; From 7a1c245b1accf025dec3c4bd69b91cab9a3f94c5 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Fri, 21 Apr 2023 14:06:33 +0200 Subject: [PATCH 27/33] Revert strcmp->str_eq replacement I screwed up here and didn't realize the importance of the negative return value here --- src/config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.c b/src/config.c index b8a42e0f..505c7cdf 100644 --- a/src/config.c +++ b/src/config.c @@ -832,9 +832,9 @@ char *cfg_escape(const char *s) { static int cmp_comp(const void *v1, const void *v2) { const Component_t *c1 = v1, *c2 = v2; - int ret = str_eq(c1->name, c2->name); + int ret = strcmp(c1->name, c2->name); - return ret? c1->strct - c2->strct: ret; + return ret? ret: c1->strct - c2->strct; } Component_t *cfg_comp_search(const char *name, int strct) { From 0e7702b03af529add981a2c38ef008357cce3934 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Fri, 21 Apr 2023 19:54:16 +0200 Subject: [PATCH 28/33] Initialize sscanf_success to zero --- src/stk500.c | 2 +- src/stk500v2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stk500.c b/src/stk500.c index 461d1627..d45a6ef7 100644 --- a/src/stk500.c +++ b/src/stk500.c @@ -680,7 +680,7 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) else if (str_starts(extended_param, "varef")) { if (pgm->extra_features & HAS_VAREF_ADJ) { - int sscanf_success; + int sscanf_success = 0; double varef_set_val = 0; // Get new analog reference voltage for channel 0 if (str_starts(extended_param, "varef=")) { diff --git a/src/stk500v2.c b/src/stk500v2.c index 6f39b446..acd76744 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -1844,7 +1844,7 @@ static int stk500v2_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) else if (str_starts(extended_param, "varef")) { if (pgm->extra_features & HAS_VAREF_ADJ) { - int sscanf_success; + int sscanf_success = 0; double varef_set_val = 0; // Get new analog reference voltage for channel 0 if (str_starts(extended_param, "varef=")) { From ba64553620a842e51ee74aa28534a794d7f94acc Mon Sep 17 00:00:00 2001 From: MCUdude Date: Fri, 21 Apr 2023 21:07:35 +0200 Subject: [PATCH 29/33] Add missing .El --- src/avrdude.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/avrdude.1 b/src/avrdude.1 index 2db8fd80..65495b87 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -1559,6 +1559,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 From 765d63ddec483f2dc82672ffe8e71049aa8a2928 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Fri, 21 Apr 2023 23:44:24 +0200 Subject: [PATCH 30/33] Update avrdude.1 --- src/avrdude.1 | 71 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index 65495b87..cff3fdc5 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -1181,14 +1181,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 @@ -1224,6 +1230,49 @@ 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. +.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 @@ -1530,14 +1579,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 From 7c4d5fa9d11df0582279d6438013d163588b3b45 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Sun, 23 Apr 2023 11:53:59 +0200 Subject: [PATCH 31/33] Add missing -xhelp --- src/avrdude.1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/avrdude.1 b/src/avrdude.1 index cff3fdc5..a842ad61 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -1237,6 +1237,8 @@ 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 @@ -1305,6 +1307,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 From cb96dc39b61124c6abaaa15f162b3d49237657c3 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Sun, 23 Apr 2023 11:56:22 +0200 Subject: [PATCH 32/33] Update avrdude.texi --- src/doc/avrdude.texi | 62 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 37935a5c..a5aa8f92 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -937,14 +937,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. @@ -985,6 +990,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 accepts 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 From 46b44a9fe19eb8cbbf6275d2025c7cd5c69c2b85 Mon Sep 17 00:00:00 2001 From: MCUdude Date: Sun, 23 Apr 2023 21:47:57 +0200 Subject: [PATCH 33/33] Fix grammar --- src/doc/avrdude.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index a5aa8f92..32d9ae29 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1007,7 +1007,7 @@ Show help menu and exit. @item STK500 @item STK600 -The STK500 and STK600 boards accepts the following extended parameters: +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.