From 334315270f37103dd03ebb91e6b2c1dcca8bb88e Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 31 May 2023 17:40:08 +0100 Subject: [PATCH 01/14] Make PROGRAMMER * and AVRPART * arguments const --- src/term.c | 105 ++++++++++++++++++++++++++--------------------------- src/term.h | 2 +- 2 files changed, 53 insertions(+), 54 deletions(-) diff --git a/src/term.c b/src/term.c index 7e59df5d..0b438491 100644 --- a/src/term.c +++ b/src/term.c @@ -60,33 +60,33 @@ struct command { char *name; - int (*func)(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); + int (*func)(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); size_t fnoff; char *desc; }; -static int cmd_dump (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_write (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_flush (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_abort (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_erase (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_config (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_sig (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_part (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_help (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_quit (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_send (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_parms (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_vtarg (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_varef (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_fosc (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_sck (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_spi (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_pgm (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); -static int cmd_quell (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]); +static int cmd_dump (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_write (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_flush (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_abort (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_erase (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_pgerase(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_config (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_sig (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_part (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_help (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_quit (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_send (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_parms (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_vtarg (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_varef (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_fosc (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_sck (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_spi (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_pgm (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_verbose(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); +static int cmd_quell (const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]); #define _fo(x) offsetof(PROGRAMMER, x) @@ -172,7 +172,7 @@ static int chardump_line(char *buffer, unsigned char *p, int n, int pad) { } -static int hexdump_buf(FILE *f, AVRMEM *m, int startaddr, unsigned char *buf, int len) { +static int hexdump_buf(const FILE *f, const AVRMEM *m, int startaddr, const unsigned char *buf, int len) { char dst1[80]; char dst2[80]; @@ -199,11 +199,11 @@ static int hexdump_buf(FILE *f, AVRMEM *m, int startaddr, unsigned char *buf, in } -static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_dump(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { static struct mem_addr_len { int addr; int len; - AVRMEM *mem; + const AVRMEM *mem; } read_mem[32]; static int i; const char *cmd = tolower(**argv) == 'd'? "dump": "read"; @@ -364,7 +364,7 @@ static size_t maxstrlen(int argc, char **argv) { } -static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_write(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if (argc < 3 || (argc > 1 && str_eq(argv[1], "-?"))) { msg_error( "Syntax: write [,] {[,]}\n" @@ -632,7 +632,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_flush(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_flush(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: flush\n" @@ -646,7 +646,7 @@ static int cmd_flush(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_abort(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_abort(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: abort\n" @@ -660,7 +660,7 @@ static int cmd_abort(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_send(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { unsigned char cmd[4], res[4]; const char *errptr; int i; @@ -713,7 +713,7 @@ static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_erase(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if (argc > 4 || argc == 3 || (argc > 1 && str_eq(argv[1], "-?"))) { msg_error( "Syntax: erase # Fill section with 0xff values\n" @@ -792,7 +792,7 @@ static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_pgerase(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc != 3 || (argc > 1 && str_eq(argv[1], "-?"))) { msg_error( "Syntax: pgerase \n" @@ -1138,7 +1138,7 @@ static void printfuse(Cfg_t *cc, int ii, Flock_t *fc, int nf, int printed, Cfg_o term_out("#\n"); } -static int cmd_config(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_config(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { Cfg_opts_t o = { 0 }; int help = 0, invalid = 0, itemac=1; @@ -1443,7 +1443,7 @@ finished: } -static int cmd_part(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_part(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: part\n" @@ -1460,7 +1460,7 @@ static int cmd_part(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_sig(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_sig(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int i; int rc; AVRMEM *m; @@ -1493,7 +1493,7 @@ static int cmd_sig(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_quit(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_quit(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: quit\n" @@ -1510,7 +1510,7 @@ static int cmd_quit(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_parms(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_parms(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: parms\n" @@ -1525,7 +1525,7 @@ static int cmd_parms(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_vtarg(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_vtarg(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int rc; double v; char *endp; @@ -1550,7 +1550,7 @@ static int cmd_vtarg(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_fosc(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int rc; double v; char *endp; @@ -1583,7 +1583,7 @@ static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_sck(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_sck(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int rc; double v; char *endp; @@ -1609,7 +1609,7 @@ static int cmd_sck(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_varef(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int rc; unsigned int chan; double v; @@ -1651,7 +1651,7 @@ static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_help(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_help(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: help\n" @@ -1677,7 +1677,7 @@ static int cmd_help(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { return 0; } -static int cmd_spi(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_spi(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: spi\n" @@ -1691,7 +1691,7 @@ static int cmd_spi(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { return 0; } -static int cmd_pgm(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_pgm(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if(argc > 1) { msg_error( "Syntax: pgm\n" @@ -1707,7 +1707,7 @@ static int cmd_pgm(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_verbose(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int nverb; const char *errptr; @@ -1739,7 +1739,7 @@ static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { } -static int cmd_quell(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int cmd_quell(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int nquell; const char *errptr; @@ -1834,7 +1834,7 @@ static char *tokenize(char *s, int *argcp, char ***argvp) { } -static int do_cmd(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) { +static int do_cmd(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int i; int hold, matches; size_t len; @@ -1877,7 +1877,7 @@ char *terminal_get_input(const char *prompt) { } -static int process_line(char *q, PROGRAMMER *pgm, struct avrpart *p) { +static int process_line(char *q, const PROGRAMMER *pgm, const AVRPART *p) { int argc, rc = 0; char **argv; @@ -1906,11 +1906,10 @@ static int process_line(char *q, PROGRAMMER *pgm, struct avrpart *p) { } - #if defined(HAVE_LIBREADLINE) -static PROGRAMMER *term_pgm; -static struct avrpart *term_p; +static const PROGRAMMER *term_pgm; +static const AVRPART *term_p; static int term_running; @@ -1991,7 +1990,7 @@ void term_gotline(char *cmdstr) { } -int terminal_mode_interactive(PROGRAMMER *pgm, struct avrpart *p) { +int terminal_mode_interactive(const PROGRAMMER *pgm, const AVRPART *p) { term_pgm = pgm; // For callback routine term_p = p; @@ -2014,7 +2013,7 @@ int terminal_mode_interactive(PROGRAMMER *pgm, struct avrpart *p) { #endif -int terminal_mode_noninteractive(PROGRAMMER *pgm, struct avrpart *p) { +int terminal_mode_noninteractive(const PROGRAMMER *pgm, const AVRPART *p) { char *cmdbuf; int rc = 0; @@ -2030,7 +2029,7 @@ int terminal_mode_noninteractive(PROGRAMMER *pgm, struct avrpart *p) { return pgm->flush_cache(pgm, p); } -int terminal_mode(PROGRAMMER *pgm, struct avrpart *p) { +int terminal_mode(const PROGRAMMER *pgm, const AVRPART *p) { #if defined(HAVE_LIBREADLINE) // GNU libreadline can also work if input is a pipe. // EditLine (NetBSD, MacOS) has issues with that, so only use it when diff --git a/src/term.h b/src/term.h index 61c4916c..09cc4a9a 100644 --- a/src/term.h +++ b/src/term.h @@ -32,7 +32,7 @@ typedef enum { WRITE_MODE_FILL = 1, } mode; -int terminal_mode(PROGRAMMER * pgm, struct avrpart * p); +int terminal_mode(const PROGRAMMER * pgm, const AVRPART * p); char * terminal_get_input(const char *prompt); void terminal_setup_update_progress(); From ffaefbf6ec68bc51633c14d87937824d304fe1f1 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 31 May 2023 17:42:11 +0100 Subject: [PATCH 02/14] Make AVRMEM * variables const --- src/term.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/term.c b/src/term.c index 0b438491..1f5721db 100644 --- a/src/term.c +++ b/src/term.c @@ -233,7 +233,7 @@ static int cmd_dump(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *arg memtype = argv[1]; else memtype = (char*)read_mem[i].mem->desc; - AVRMEM *mem = avr_locate_mem(p, memtype); + const AVRMEM *mem = avr_locate_mem(p, memtype); if (mem == NULL) { pmsg_error("(%s) %s memory type not defined for part %s\n", cmd, memtype, p->desc); return -1; @@ -419,7 +419,7 @@ static int cmd_write(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *ar int start_offset; // Which argc argument int len; // Number of bytes to write to memory char *memtype = argv[1]; // Memory name string - AVRMEM *mem = avr_locate_mem(p, memtype); + const AVRMEM *mem = avr_locate_mem(p, memtype); if (mem == NULL) { pmsg_error("(write) %s memory type not defined for part %s\n", memtype, p->desc); return -1; @@ -726,7 +726,7 @@ static int cmd_erase(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *ar if (argc > 1) { char *memtype = argv[1]; - AVRMEM *mem = avr_locate_mem(p, memtype); + const AVRMEM *mem = avr_locate_mem(p, memtype); if (mem == NULL) { pmsg_error("(erase) %s memory type not defined for part %s\n", argv[1], p->desc); return -1; @@ -752,7 +752,7 @@ static int cmd_erase(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *ar if(rc == LIBAVRDUDE_SOFTFAIL) { pmsg_info("(erase) emulating chip erase by writing 0xff to flash "); - AVRMEM *flm = avr_locate_mem(p, "flash"); + const AVRMEM *flm = avr_locate_mem(p, "flash"); if(!flm) { msg_error("but flash not defined for part %s?\n", p->desc); return -1; @@ -802,7 +802,7 @@ static int cmd_pgerase(const PROGRAMMER *pgm, const AVRPART *p, int argc, char * } char *memtype = argv[1]; - AVRMEM *mem = avr_locate_mem(p, memtype); + const AVRMEM *mem = avr_locate_mem(p, memtype); if(!mem) { pmsg_error("(pgerase) %s memory type not defined for part %s\n", memtype, p->desc); return -1; @@ -889,7 +889,7 @@ static int getfusel(const PROGRAMMER *pgm, const AVRPART *p, Fusel_t *fl, const goto back; } - AVRMEM *mem = avr_locate_mem(p, cci->memstr); + const AVRMEM *mem = avr_locate_mem(p, cci->memstr); if(!mem) { err = cache_string(tofree = str_sprintf("%s memory type not defined for part %s", cci->memstr, p->desc)); free(tofree); @@ -1251,7 +1251,7 @@ static int cmd_config(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *a cc[i].t = ct+i; const char *mt = str_starts(ct[i].memtype, "lock")? locktype: ct[i].memtype; cc[i].memstr = mt; - AVRMEM *mem = avr_locate_mem(p, mt); + const AVRMEM *mem = avr_locate_mem(p, mt); if(!mem) { pmsg_warning("(config) %s unavailable as memory %s is not defined for %s\n", ct[i].name, mt, p->desc); continue; @@ -1413,7 +1413,7 @@ static int cmd_config(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *a fl_t towrite; towrite.i = (fusel.current & ~ct[ci].mask) | (toassign<desc); ret = -1; @@ -1463,7 +1463,7 @@ static int cmd_part(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *arg static int cmd_sig(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { int i; int rc; - AVRMEM *m; + const AVRMEM *m; if(argc > 1) { msg_error( From a53b2eef19131846b4b390a84b372b1ae547958e Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 31 May 2023 17:52:30 +0100 Subject: [PATCH 03/14] Make local functions static --- src/term.c | 8 +++++--- src/term.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/term.c b/src/term.c index 1f5721db..8f011ccf 100644 --- a/src/term.c +++ b/src/term.c @@ -837,7 +837,7 @@ static int cmd_pgerase(const PROGRAMMER *pgm, const AVRPART *p, int argc, char * // Config command -const int MAX_PAD = 10; // Align value labels if difference between their lengths is less than this +static const int MAX_PAD = 10; // Align value labels if difference between their lengths is less than this typedef union { // Lock memory can be 1 or 4 bytes uint8_t b[4]; @@ -1959,7 +1959,7 @@ static int readytoread() { } // Callback processes commands whenever readline() has finished -void term_gotline(char *cmdstr) { +static void term_gotline(char *cmdstr) { if(cmdstr) { if(*cmdstr) { add_history(cmdstr); @@ -1990,7 +1990,7 @@ void term_gotline(char *cmdstr) { } -int terminal_mode_interactive(const PROGRAMMER *pgm, const AVRPART *p) { +static int terminal_mode_interactive(const PROGRAMMER *pgm, const AVRPART *p) { term_pgm = pgm; // For callback routine term_p = p; @@ -2029,6 +2029,8 @@ int terminal_mode_noninteractive(const PROGRAMMER *pgm, const AVRPART *p) { return pgm->flush_cache(pgm, p); } + +// Terminal shell that is called on avrdude -t int terminal_mode(const PROGRAMMER *pgm, const AVRPART *p) { #if defined(HAVE_LIBREADLINE) // GNU libreadline can also work if input is a pipe. diff --git a/src/term.h b/src/term.h index 09cc4a9a..f6f2efb3 100644 --- a/src/term.h +++ b/src/term.h @@ -33,6 +33,7 @@ typedef enum { } mode; int terminal_mode(const PROGRAMMER * pgm, const AVRPART * p); +int terminal_mode_noninteractive(const PROGRAMMER * pgm, const AVRPART * p); char * terminal_get_input(const char *prompt); void terminal_setup_update_progress(); From 3db6863cd3292614582c38e0e47b96a6175017d3 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 31 May 2023 18:08:43 +0100 Subject: [PATCH 04/14] Move fill mode enum from term.h to term.c --- src/term.c | 5 ++++- src/term.h | 5 ----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/term.c b/src/term.c index 8f011ccf..5b8c2f9e 100644 --- a/src/term.c +++ b/src/term.c @@ -363,6 +363,10 @@ static size_t maxstrlen(int argc, char **argv) { return max; } +typedef enum { + WRITE_MODE_STANDARD = 0, + WRITE_MODE_FILL = 1, +} Write_mode_t; static int cmd_write(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *argv[]) { if (argc < 3 || (argc > 1 && str_eq(argv[1], "-?"))) { @@ -1905,7 +1909,6 @@ static int process_line(char *q, const PROGRAMMER *pgm, const AVRPART *p) { return rc; } - #if defined(HAVE_LIBREADLINE) static const PROGRAMMER *term_pgm; diff --git a/src/term.h b/src/term.h index f6f2efb3..69a7bfda 100644 --- a/src/term.h +++ b/src/term.h @@ -27,11 +27,6 @@ extern "C" { #endif -typedef enum { - WRITE_MODE_STANDARD = 0, - WRITE_MODE_FILL = 1, -} mode; - int terminal_mode(const PROGRAMMER * pgm, const AVRPART * p); int terminal_mode_noninteractive(const PROGRAMMER * pgm, const AVRPART * p); char * terminal_get_input(const char *prompt); From 98c460268ec5fc49f21c67db643e20ab05553117 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 31 May 2023 18:16:34 +0100 Subject: [PATCH 05/14] Provide terminal_line() to process a single terminal command line --- src/term.c | 18 ++++++++++++++++++ src/term.h | 1 + 2 files changed, 19 insertions(+) diff --git a/src/term.c b/src/term.c index 5b8c2f9e..a14c2a06 100644 --- a/src/term.c +++ b/src/term.c @@ -1909,6 +1909,24 @@ static int process_line(char *q, const PROGRAMMER *pgm, const AVRPART *p) { return rc; } + +/* + * Process individual terminal line + * - Used by main's -T argument + * - The terminal manages a cache, -U does not: the caller is responsible for executing + * + pgm->flush_cache(pgm, p) between -T line and -U memory read/avrdude exit + * + pgm->reset_cache(pgm, p) between -U memory write and -T line + */ + +int terminal_line(const PROGRAMMER *pgm, const AVRPART *p, const char *line) { + char *ln = cfg_strdup(__func__, line); + int ret = process_line(ln, pgm, p); + free(ln); + + return ret; +} + + #if defined(HAVE_LIBREADLINE) static const PROGRAMMER *term_pgm; diff --git a/src/term.h b/src/term.h index 69a7bfda..1859ccf5 100644 --- a/src/term.h +++ b/src/term.h @@ -29,6 +29,7 @@ extern "C" { int terminal_mode(const PROGRAMMER * pgm, const AVRPART * p); int terminal_mode_noninteractive(const PROGRAMMER * pgm, const AVRPART * p); +int terminal_line(const PROGRAMMER *pgm, const AVRPART *p, const char *line); char * terminal_get_input(const char *prompt); void terminal_setup_update_progress(); From 1126ff16214cfa53ff9bf1ff6a7643efd674b7d8 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 31 May 2023 22:23:23 +0100 Subject: [PATCH 06/14] Implement -T cmdline to mix terminal commands with -U commands --- src/libavrdude.h | 30 ++++++++++++++++++------------ src/main.c | 27 ++++++++++++++++++++++++--- src/term.c | 1 - src/term.h | 6 ------ src/update.c | 12 ++++++++++++ 5 files changed, 54 insertions(+), 22 deletions(-) diff --git a/src/libavrdude.h b/src/libavrdude.h index e16810dd..402f4ef2 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -1051,10 +1051,11 @@ enum updateflags { typedef struct update_t { - char * memtype; - int op; - char * filename; - int format; + const char *cmdline; // -T line is stored here and takes precedence if it exists + char *memtype; // Memory name for -U + int op; // Symbolic memory operation DEVICE_... for -U + char *filename; // Filename for -U, can be - + int format; // File format FMT_... } UPDATE; typedef struct { // File reads for flash can exclude trailing 0xff, which are cut off @@ -1072,15 +1073,14 @@ typedef struct { // File reads for flash can exclude trailing 0xf extern "C" { #endif -extern UPDATE * parse_op(char * s); -extern UPDATE * dup_update(UPDATE * upd); -extern UPDATE * new_update(int op, char * memtype, int filefmt, - char * filename); +UPDATE *parse_op(char *s); +UPDATE *dup_update(UPDATE *upd); +UPDATE *new_update(int op, char *memtype, int filefmt, char *filename); +UPDATE *cmd_update(const char *cmd); extern void free_update(UPDATE * upd); -extern int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, - enum updateflags flags); - -extern int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp); +int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, + enum updateflags flags); +int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp); // Convenience functions for printing const char *update_plural(int x); @@ -1245,6 +1245,12 @@ unsigned long long int str_int(const char *str, int type, const char **errpp); int str_membuf(const char *str, int type, unsigned char *buf, int size, const char **errpp); char *str_nexttok(char *buf, const char *delim, char **next); +int terminal_mode(const PROGRAMMER *pgm, const AVRPART *p); +int terminal_mode_noninteractive(const PROGRAMMER *pgm, const AVRPART *p); +int terminal_line(const PROGRAMMER *pgm, const AVRPART *p, const char *line); +char *terminal_get_input(const char *prompt); +void terminal_setup_update_progress(); + #ifdef __cplusplus } #endif diff --git a/src/main.c b/src/main.c index ee99d1ff..6c0e7fb2 100644 --- a/src/main.c +++ b/src/main.c @@ -49,7 +49,6 @@ #include "avrdude.h" #include "libavrdude.h" #include "config.h" -#include "term.h" #include "developer_opts.h" /* Get VERSION from ac_cfg.h */ @@ -632,7 +631,8 @@ int main(int argc, char * argv []) /* * process command line arguments */ - while ((ch = getopt(argc,argv,"?Ab:B:c:C:DeE:Fi:l:np:OP:qstU:uvVx:yY:")) != -1) { + int memwrite = 0, memterminal = 0; + while ((ch = getopt(argc,argv,"?Ab:B:c:C:DeE:Fi:l:np:OP:qstT:U:uvVx:yY:")) != -1) { switch (ch) { case 'b': /* override default programmer baud rate */ @@ -772,12 +772,28 @@ int main(int argc, char * argv []) pmsg_error("\"safemode\" feature no longer supported\n"); break; + case 'T': + upd = (UPDATE *) cfg_malloc(__func__, sizeof *upd); + upd->cmdline = optarg; + if(memwrite) { // Invalidate cache if device was written to + memwrite = 0; + ladd(updates, cmd_update("abort # Reset cache")); + } + memterminal = 1; + ladd(updates, upd); + break; + case 'U': upd = parse_op(optarg); if (upd == NULL) { pmsg_error("unable to parse update operation '%s'\n", optarg); exit(1); } + if(memterminal) { // Flush cache before any device memory access + memterminal = 0; + ladd(updates, cmd_update("flush")); + } + memwrite |= upd->op == DEVICE_WRITE; ladd(updates, upd); break; @@ -815,6 +831,9 @@ int main(int argc, char * argv []) } + if(memterminal) + ladd(updates, cmd_update("flush")); + if (logfile != NULL) { FILE *newstderr = freopen(logfile, "w", stderr); if (newstderr == NULL) { @@ -1235,7 +1254,7 @@ int main(int argc, char * argv []) int doexit = 0; for (ln=lfirst(updates); ln; ln=lnext(ln)) { upd = ldata(ln); - if (upd->memtype == NULL) { + if (upd->memtype == NULL && upd->cmdline == NULL) { const char *mtype = p->prog_modes & PM_PDI? "application": "flash"; pmsg_notice2("defaulting memtype in -U %c:%s option to \"%s\"\n", (upd->op == DEVICE_READ)? 'r': (upd->op == DEVICE_WRITE)? 'w': 'v', @@ -1445,6 +1464,8 @@ int main(int argc, char * argv []) uflags &= ~UF_AUTO_ERASE; for (ln=lfirst(updates); ln; ln=lnext(ln)) { upd = ldata(ln); + if(!upd->memtype) + continue; m = avr_locate_mem(p, upd->memtype); if (m == NULL) continue; diff --git a/src/term.c b/src/term.c index a14c2a06..0e67a334 100644 --- a/src/term.c +++ b/src/term.c @@ -56,7 +56,6 @@ #include "avrdude.h" -#include "term.h" struct command { char *name; diff --git a/src/term.h b/src/term.h index 1859ccf5..45b2a385 100644 --- a/src/term.h +++ b/src/term.h @@ -27,12 +27,6 @@ extern "C" { #endif -int terminal_mode(const PROGRAMMER * pgm, const AVRPART * p); -int terminal_mode_noninteractive(const PROGRAMMER * pgm, const AVRPART * p); -int terminal_line(const PROGRAMMER *pgm, const AVRPART *p, const char *line); -char * terminal_get_input(const char *prompt); -void terminal_setup_update_progress(); - #ifdef __cplusplus } #endif diff --git a/src/update.c b/src/update.c index f6c71fcc..6d91ba69 100644 --- a/src/update.c +++ b/src/update.c @@ -126,6 +126,12 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename) return u; } +UPDATE *cmd_update(const char *cmd) { + UPDATE *u = (UPDATE *) cfg_malloc(__func__, sizeof *u); + u->cmdline = cmd; + return u; +} + void free_update(UPDATE * u) { if (u != NULL) { @@ -305,6 +311,9 @@ int update_dryrun(const AVRPART *p, UPDATE *upd) { int known, format_detect, ret = LIBAVRDUDE_SUCCESS; + if(upd->cmdline) // Todo: parse terminal command line? + return 0; + /* * Reject an update if memory name is not known amongst any part (suspect a typo) * but accept when the specific part does not have it (allow unifying i/faces) @@ -387,6 +396,9 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags int rc; Filestats fs, fs_patched; + if(upd->cmdline) + return terminal_line(pgm, p, upd->cmdline); + mem = avr_locate_mem(p, upd->memtype); if (mem == NULL) { pmsg_warning("skipping -U %s:... as memory not defined for part %s\n", upd->memtype, p->desc); From bdbe13e1f60c795196c25989c865d8c1b8c86522 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 31 May 2023 22:40:34 +0100 Subject: [PATCH 07/14] Make arguments of update.c functions const if possible --- src/libavrdude.h | 10 +++++----- src/update.c | 20 +++++++++----------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/libavrdude.h b/src/libavrdude.h index 402f4ef2..95ff950a 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -1073,12 +1073,12 @@ typedef struct { // File reads for flash can exclude trailing 0xf extern "C" { #endif -UPDATE *parse_op(char *s); -UPDATE *dup_update(UPDATE *upd); -UPDATE *new_update(int op, char *memtype, int filefmt, char *filename); +UPDATE *parse_op(const char *s); +UPDATE *dup_update(const UPDATE *upd); +UPDATE *new_update(int op, const char *memstr, int filefmt, const char *fname); UPDATE *cmd_update(const char *cmd); -extern void free_update(UPDATE * upd); -int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, +extern void free_update(UPDATE *upd); +int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updateflags flags); int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp); diff --git a/src/update.c b/src/update.c index 6d91ba69..d3b181d4 100644 --- a/src/update.c +++ b/src/update.c @@ -42,15 +42,15 @@ * flash write). This allows colons in filenames other than those for * enclosing and separating , eg, C:/some/file.hex */ -UPDATE *parse_op(char *s) { +UPDATE *parse_op(const char *s) { // Assume -U [:] first UPDATE *upd = (UPDATE *) cfg_malloc(__func__, sizeof *upd); upd->memtype = NULL; // Defaults to flash or application upd->op = DEVICE_WRITE; - char *fn = s; + const char *fn = s; // Check for :c: start in which case override defaults - char *fc = strchr(s, ':'); + const char *fc = strchr(s, ':'); if(fc && fc[1] && fc[2] == ':') { if(!strchr("rwv", fc[1])) { pmsg_error("invalid I/O mode :%c: in -U %s\n", fc[1], s); @@ -95,8 +95,7 @@ UPDATE *parse_op(char *s) { } -UPDATE * dup_update(UPDATE * upd) -{ +UPDATE *dup_update(const UPDATE *upd) { UPDATE * u; u = (UPDATE *) cfg_malloc("dup_update()", sizeof(UPDATE)); @@ -112,14 +111,13 @@ UPDATE * dup_update(UPDATE * upd) return u; } -UPDATE * new_update(int op, char * memtype, int filefmt, char * filename) -{ +UPDATE *new_update(int op, const char *memstr, int filefmt, const char *fname) { UPDATE * u; u = (UPDATE *) cfg_malloc("new_update()", sizeof(UPDATE)); - u->memtype = cfg_strdup("new_update()", memtype); - u->filename = cfg_strdup("new_update()", filename); + u->memtype = cfg_strdup("new_update()", memstr); + u->filename = cfg_strdup("new_update()", fname); u->op = op; u->format = filefmt; @@ -304,7 +302,7 @@ static void ioerror(const char *iotype, const UPDATE *upd) { msg_ext_error("\n"); } -// Basic checks to reveal serious failure before programming +// Basic checks to reveal serious failure before programming (and on autodetect set format) int update_dryrun(const AVRPART *p, UPDATE *upd) { static char **wrote; static int nfwritten; @@ -389,7 +387,7 @@ int update_dryrun(const AVRPART *p, UPDATE *upd) { } -int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags flags) { +int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updateflags flags) { AVRPART *v; AVRMEM *mem; int size; From 4a7d140b08221361fa1f976c7584640143793ece Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 31 May 2023 22:50:27 +0100 Subject: [PATCH 08/14] Move update_...() printing convenience functions to strutil.c and rename to str_...() --- src/libavrdude.h | 10 +++--- src/strutil.c | 33 +++++++++++++++++++ src/term.c | 4 +-- src/update.c | 83 +++++++++++++++--------------------------------- 4 files changed, 64 insertions(+), 66 deletions(-) diff --git a/src/libavrdude.h b/src/libavrdude.h index 95ff950a..74398df8 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -1082,12 +1082,6 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updateflags flags); int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp); -// Convenience functions for printing -const char *update_plural(int x); -const char *update_inname(const char *fn); -const char *update_outname(const char *fn); -const char *update_interval(int a, int b); - // Helper functions for dry run to determine file access int update_is_okfile(const char *fn); int update_is_writeable(const char *fn); @@ -1235,6 +1229,10 @@ char *str_uc(char *s); char *str_lcfirst(char *s); char *str_ucfirst(char *s); char *str_utoa(unsigned n, char *buf, int base); +const char *str_plural(int x); +const char *str_inname(const char *fn); +const char *str_outname(const char *fn); +const char *str_interval(int a, int b); bool is_bigendian(); void change_endian(void *p, int size); int memall(const void *p, char c, size_t n); diff --git a/src/strutil.c b/src/strutil.c index 8bd79e52..7fa8cd9a 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -298,6 +298,39 @@ char *str_utoa(unsigned n, char *buf, int base) { } +// Convenience functions for printing +const char *str_plural(int x) { + return x==1? "": "s"; +} + +const char *str_inname(const char *fn) { + return !fn? "???": strcmp(fn, "-")? fn: ""; +} + +const char *str_outname(const char *fn) { + return !fn? "???": strcmp(fn, "-")? fn: ""; +} + +// Return sth like "[0, 0x1ff]" +const char *str_interval(int a, int b) { + // Cyclic buffer for 20+ temporary interval strings each max 41 bytes at 64-bit int + static char space[20*41 + 80], *sp; + if(!sp || sp-space > (int) sizeof space - 80) + sp = space; + + char *ret = sp; + + sprintf(sp, a<16? "[%d": "[0x%x", a); + sp += strlen(sp); + sprintf(sp, b<16? ", %d]": ", 0x%x]", b); + + // Advance beyond return string in temporary ring buffer + sp += strlen(sp)+1; + + return ret; +} + + bool is_bigendian() { union {char a[2]; int16_t i;} u = {.i = 1}; return u.a[1] == 1; diff --git a/src/term.c b/src/term.c index 0e67a334..91d098a3 100644 --- a/src/term.c +++ b/src/term.c @@ -578,7 +578,7 @@ static int cmd_write(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *ar if(write_mode == WRITE_MODE_FILL) { if(recorded < len) { pmsg_warning("(write ...) can only fill %d < %d byte%s as last item has zero bytes\n", - recorded, len, update_plural(recorded)); + recorded, len, str_plural(recorded)); len = recorded; } bytes_grown = 0; @@ -588,7 +588,7 @@ static int cmd_write(const PROGRAMMER *pgm, const AVRPART *p, int argc, char *ar } pmsg_notice2("(write) writing %d byte%s starting from address 0x%02x", - len + bytes_grown, update_plural(len + bytes_grown), addr); + len + bytes_grown, str_plural(len + bytes_grown), addr); if (write_mode == WRITE_MODE_FILL && filling) msg_notice2("; remaining space filled with %s", argv[argc - 2]); msg_notice2("\v"); diff --git a/src/update.c b/src/update.c index d3b181d4..c2c6c8de 100644 --- a/src/update.c +++ b/src/update.c @@ -215,39 +215,6 @@ int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp) { } -// Convenience functions for printing -const char *update_plural(int x) { - return x==1? "": "s"; -} - -const char *update_inname(const char *fn) { - return !fn? "???": strcmp(fn, "-")? fn: ""; -} - -const char *update_outname(const char *fn) { - return !fn? "???": strcmp(fn, "-")? fn: ""; -} - -// Return sth like "[0, 0x1ff]" -const char *update_interval(int a, int b) { - // Cyclic buffer for 20+ temporary interval strings each max 41 bytes at 64-bit int - static char space[20*41 + 80], *sp; - if(!sp || sp-space > (int) sizeof space - 80) - sp = space; - - char *ret = sp; - - sprintf(sp, a<16? "[%d": "[0x%x", a); - sp += strlen(sp); - sprintf(sp, b<16? ", %d]": ", 0x%x]", b); - - // Advance beyond return string in temporary ring buffer - sp += strlen(sp)+1; - - return ret; -} - - // Helper functions for dry run to determine file access int update_is_okfile(const char *fn) { @@ -294,7 +261,7 @@ int update_is_readable(const char *fn) { static void ioerror(const char *iotype, const UPDATE *upd) { int errnocp = errno; - pmsg_ext_error("file %s is not %s: ", update_outname(upd->filename), iotype); + pmsg_ext_error("file %s is not %s: ", str_outname(upd->filename), iotype); if(errnocp) msg_ext_error("%s", strerror(errnocp)); else if(upd->filename && *upd->filename) @@ -432,11 +399,11 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat if (rc == 0) pmsg_notice("flash is empty, resulting file has no contents\n"); - pmsg_info("writing output file %s\n", update_outname(upd->filename)); + pmsg_info("writing output file %s\n", str_outname(upd->filename)); rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size); if (rc < 0) { - pmsg_error("write to file %s failed\n", update_outname(upd->filename)); + pmsg_error("write to file %s failed\n", str_outname(upd->filename)); return LIBAVRDUDE_GENERAL_FAILURE; } break; @@ -446,27 +413,27 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); if (rc < 0) { - pmsg_error("read from file %s failed\n", update_inname(upd->filename)); + pmsg_error("read from file %s failed\n", str_inname(upd->filename)); return LIBAVRDUDE_GENERAL_FAILURE; } pmsg_info("reading input file %s for %s%s\n", - update_inname(upd->filename), mem->desc, alias_mem_desc); + str_inname(upd->filename), mem->desc, alias_mem_desc); if(memstats(p, upd->memtype, rc, &fs) < 0) return LIBAVRDUDE_GENERAL_FAILURE; imsg_info("with %d byte%s in %d section%s within %s\n", - fs.nbytes, update_plural(fs.nbytes), - fs.nsections, update_plural(fs.nsections), - update_interval(fs.firstaddr, fs.lastaddr)); + fs.nbytes, str_plural(fs.nbytes), + fs.nsections, str_plural(fs.nsections), + str_interval(fs.firstaddr, fs.lastaddr)); if(mem->page_size > 1) { imsg_info("using %d page%s and %d pad byte%s", - fs.npages, update_plural(fs.npages), - fs.nfill, update_plural(fs.nfill)); + fs.npages, str_plural(fs.npages), + fs.nfill, str_plural(fs.nfill)); if(fs.ntrailing) msg_info(", cutting off %d trailing 0xff byte%s", - fs.ntrailing, update_plural(fs.ntrailing)); + fs.ntrailing, str_plural(fs.ntrailing)); msg_info("\n"); } @@ -476,7 +443,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat if(mem && !strcmp(mem->desc, "flash")) { rc = pgm->flash_readhook(pgm, p, mem, upd->filename, rc); if (rc < 0) { - pmsg_notice("readhook for file %s failed\n", update_inname(upd->filename)); + pmsg_notice("readhook for file %s failed\n", str_inname(upd->filename)); return LIBAVRDUDE_GENERAL_FAILURE; } if(memstats(p, upd->memtype, rc, &fs_patched) < 0) @@ -485,16 +452,16 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat pmsg_info("preparing flash input for device%s\n", pgm->prog_modes & PM_SPM? " bootloader": ""); imsg_notice2("with %d byte%s in %d section%s within %s\n", - fs_patched.nbytes, update_plural(fs_patched.nbytes), - fs_patched.nsections, update_plural(fs_patched.nsections), - update_interval(fs_patched.firstaddr, fs_patched.lastaddr)); + fs_patched.nbytes, str_plural(fs_patched.nbytes), + fs_patched.nsections, str_plural(fs_patched.nsections), + str_interval(fs_patched.firstaddr, fs_patched.lastaddr)); if(mem->page_size > 1) { imsg_notice2("using %d page%s and %d pad byte%s", - fs_patched.npages, update_plural(fs_patched.npages), - fs_patched.nfill, update_plural(fs_patched.nfill)); + fs_patched.npages, str_plural(fs_patched.npages), + fs_patched.nfill, str_plural(fs_patched.nfill)); if(fs_patched.ntrailing) msg_notice2(", and %d trailing 0xff byte%s", - fs_patched.ntrailing, update_plural(fs_patched.ntrailing)); + fs_patched.ntrailing, str_plural(fs_patched.ntrailing)); msg_notice2("\n"); } } @@ -504,7 +471,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat // Write the buffer contents to the selected memory type pmsg_info("writing %d byte%s %s%s ...\n", fs.nbytes, - update_plural(fs.nbytes), mem->desc, alias_mem_desc); + str_plural(fs.nbytes), mem->desc, alias_mem_desc); if (!(flags & UF_NOWRITE)) { if(mem->size > 32 || verbose > 1) @@ -522,7 +489,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat } pmsg_info("%d byte%s of %s%s written\n", fs.nbytes, - update_plural(fs.nbytes), mem->desc, alias_mem_desc); + str_plural(fs.nbytes), mem->desc, alias_mem_desc); if (!(flags & UF_VERIFY)) // Fall through for auto verify unless break; @@ -535,17 +502,17 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat int userverify = upd->op == DEVICE_VERIFY; // Explicit -U :v by user pmsg_info("verifying %s%s memory against %s\n", mem->desc, - alias_mem_desc, update_inname(upd->filename)); + alias_mem_desc, str_inname(upd->filename)); // No need to read file when fallen through from DEVICE_WRITE if (userverify) { pmsg_notice("load %s%s data from input file %s\n", mem->desc, - alias_mem_desc, update_inname(upd->filename)); + alias_mem_desc, str_inname(upd->filename)); rc = fileio(FIO_READ_FOR_VERIFY, upd->filename, upd->format, p, upd->memtype, -1); if (rc < 0) { - pmsg_error("read from file %s failed\n", update_inname(upd->filename)); + pmsg_error("read from file %s failed\n", str_inname(upd->filename)); return LIBAVRDUDE_GENERAL_FAILURE; } size = rc; @@ -562,7 +529,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat if (quell_progress < 2) { if (userverify) pmsg_notice("input file %s contains %d byte%s\n", - update_inname(upd->filename), fs.nbytes, update_plural(fs.nbytes)); + str_inname(upd->filename), fs.nbytes, str_plural(fs.nbytes)); pmsg_notice2("reading on-chip %s%s data ...\n", mem->desc, alias_mem_desc); } @@ -589,7 +556,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat } int verified = fs.nbytes+fs.ntrailing; - pmsg_info("%d byte%s of %s%s verified\n", verified, update_plural(verified), mem->desc, alias_mem_desc); + pmsg_info("%d byte%s of %s%s verified\n", verified, str_plural(verified), mem->desc, alias_mem_desc); pgm->vfy_led(pgm, OFF); avr_free_part(v); From e0e7bd7ff575e3071b2cf8398ad5bb334399ec78 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 1 Jun 2023 00:20:33 +0100 Subject: [PATCH 09/14] Document -T cmd option --- src/avrdude.1 | 18 ++++++++++++--- src/doc/avrdude.texi | 12 ++++++++-- src/main.c | 55 ++++++++++++++++++++++---------------------- 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index 8ed9e8f1..9594a07e 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -44,6 +44,7 @@ .Op Fl O .Op Fl P Ar port .Op Fl q +.Op Fl T Ar cmd .Op Fl t .Op Fl U Ar memtype:op:filename:filefmt .Op Fl v @@ -694,17 +695,28 @@ to the device. Specify it more often for even quieter operations. .It Fl s, u These options used to control the obsolete "safemode" feature which is no longer present. They are silently ignored for backwards compatibility. +.It Fl T Ar cmd +Slots a terminal command line +.Ar cmd +into the intermixed list of -T terminal commands and -U memory operations. +The terminal command line is executed when it is its turn in the mixed list. +Except for the simplest of terminal commands the argument +.Ar cmd +will most likely need to be set in quotes, see your OS shell manual for +details. .It Fl t Tells .Nm -to enter the interactive ``terminal'' mode instead of up- or downloading -files. See below for a detailed description of the terminal mode. +to enter the interactive terminal shell before up- or downloading files +via the -U option or processing other -T terminal commands, if any. See +below for a detailed description of the terminal mode. .It Xo Fl U Ar memtype Ns .Ar \&: Ns Ar op Ns .Ar \&: Ns Ar filename Ns .Op \&: Ns Ar format .Xc -Perform a memory operation as indicated. The +Perform a memory operation as indicated. Multiple -U operations are +allowed. The .Ar memtype field specifies the memory type to operate on. The available memory types are device-dependent, the actual diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index d3ac921d..c32387f6 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -757,9 +757,17 @@ to the device. Specify it a second time for even quieter operation. These options used to control the obsolete "safemode" feature which is no longer present. They are silently ignored for backwards compatibility. +@item -T @var{cmd} +Slots a terminal command line @var{cmd} into the intermixed list of +@code{-T} terminal commands and @code{-U} memory operations. The terminal +command line is executed when it is its turn in the mixed list. Except for +the simplest of terminal commands the argument @var{cmd} will most likely +need to be set in quotes, see your OS shell manual for details. + @item -t -Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up- -or downloading files. See below for a detailed description of the +Tells AVRDUDE to enter the interactive terminal shell before uploading or +downloading files via the @code{-U} option or processing other @code{-T} +terminal commands, if any. See below for a detailed description of the terminal mode. @item -U @var{memtype}:@var{op}:@var{filename}[:@var{format}] diff --git a/src/main.c b/src/main.c index 6c0e7fb2..d59f6638 100644 --- a/src/main.c +++ b/src/main.c @@ -224,34 +224,35 @@ static void usage(void) msg_error( "Usage: %s [options]\n" "Options:\n" - " -p Specify AVR device\n" - " -p / Run developer options for matched AVR devices\n" - " -b Override RS-232 baud rate\n" - " -B Specify bit clock period (us)\n" - " -C Specify location of configuration file\n" - " -c Specify programmer type\n" - " -c / Run developer options for matched programmers\n" - " -A Disable trailing-0xff removal from file and AVR read\n" - " -D Disable auto erase for flash memory; implies -A\n" - " -i ISP Clock Delay [in microseconds]\n" - " -P Specify connection port\n" - " -F Override invalid signature or initialisation check\n" - " -e Perform a chip erase\n" - " -O Perform RC oscillator calibration (see AVR053)\n" + " -p Specify AVR device\n" + " -p / Run developer options for matched AVR devices\n" + " -b Override RS-232 baud rate\n" + " -B Specify bit clock period (us)\n" + " -C Specify location of configuration file\n" + " -c Specify programmer type\n" + " -c / Run developer options for matched programmers\n" + " -A Disable trailing-0xff removal for file/AVR read\n" + " -D Disable auto erase for flash memory; implies -A\n" + " -i ISP Clock Delay [in microseconds]\n" + " -P Specify connection port\n" + " -F Override invalid signature or initial checks\n" + " -e Perform a chip erase\n" + " -O Perform RC oscillator calibration (see AVR053)\n" + " -t Enter terminal shell before processing -U/T\n" + " -T Slot terminal line into a list and run in turn\n" " -U :r|w|v:[:format]\n" - " Memory operation specification\n" - " Multiple -U options are allowed, each request\n" - " is performed in the order specified\n" - " -n Do not write to the device whilst processing -U\n" - " -V Do not automatically verify during -U\n" - " -t Enter terminal mode\n" - " -E [,] List programmer exit specifications\n" - " -x Pass to programmer, see -xhelp\n" - " -v Verbose output; -v -v for more\n" - " -q Quell progress output; -q -q for less\n" - " -l logfile Use logfile rather than stderr for diagnostics\n" - " -? Display this usage\n" - "\navrdude version %s, URL: \n", + " Memory operation specification\n" + " Multiple -U/T options are allowed; each request\n" + " is performed in the specified intermixed order\n" + " -n Do not write to the device whilst processing -U\n" + " -V Do not automatically verify during -U\n" + " -E [,] List programmer exit specifications\n" + " -x Pass to programmer, see -xhelp\n" + " -v Verbose output; -v -v for more\n" + " -q Quell progress output; -q -q for less\n" + " -l logfile Use logfile rather than stderr for diagnostics\n" + " -? Display this usage\n" + "\navrdude version %s, https://github.com/avrdudes/avrdude\n", progname, version); } From fa9370d57062665ee47c913f08865aabcba6949c Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 1 Jun 2023 01:03:21 +0100 Subject: [PATCH 10/14] Insert a paragraph for each -T/-U option in AVRDUDE's output --- src/fileio.c | 31 ++++++++++++++++++++++++++++++- src/libavrdude.h | 3 +++ src/update.c | 16 ++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/fileio.c b/src/fileio.c index 75facd55..0dcf95d5 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -130,7 +130,36 @@ char *fileio_fmtstr(FILEFMT format) { return "octal byte list"; default: return "invalid format"; - }; + } +} + +int fileio_fmtchr(FILEFMT format) { + switch (format) { + case FMT_AUTO: + return 'a'; + case FMT_SREC: + return 's'; + case FMT_IHEX: + return 'i'; + case FMT_IHXC: + return 'I'; + case FMT_RBIN: + return 'r'; + case FMT_ELF: + return 'e'; + case FMT_IMM: + return 'm'; + case FMT_BIN: + return 'b'; + case FMT_DEC: + return 'd'; + case FMT_HEX: + return 'h'; + case FMT_OCT: + return 'o'; + default: + return '?'; + } } diff --git a/src/libavrdude.h b/src/libavrdude.h index 74398df8..44ae0f7c 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -1020,6 +1020,8 @@ FILEFMT fileio_format(char c); char *fileio_fmtstr(FILEFMT format); +int fileio_fmtchr(FILEFMT format); + FILE *fileio_fopenr(const char *fname); int fileio_fmt_autodetect_fp(FILE *f); @@ -1078,6 +1080,7 @@ UPDATE *dup_update(const UPDATE *upd); UPDATE *new_update(int op, const char *memstr, int filefmt, const char *fname); UPDATE *cmd_update(const char *cmd); extern void free_update(UPDATE *upd); +char *update_str(const UPDATE *upd); int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updateflags flags); int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp); diff --git a/src/update.c b/src/update.c index c2c6c8de..bd16aa48 100644 --- a/src/update.c +++ b/src/update.c @@ -145,6 +145,15 @@ void free_update(UPDATE * u) } } +char *update_str(const UPDATE *upd) { + if(upd->cmdline) + return str_sprintf("-T %s", upd->cmdline); + return str_sprintf("-U %s:%c:%s:%c", + upd->memtype, + upd->op == DEVICE_READ? 'r': upd->op == DEVICE_WRITE? 'w': 'v', + upd->filename, + fileio_fmtchr(upd->format)); +} // Memory statistics considering holes after a file read returned size bytes int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp) { @@ -361,6 +370,13 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat int rc; Filestats fs, fs_patched; + if(!upd->cmdline || !str_eq(upd->cmdline, "abort # Reset cache")) { + char *tofree; + msg_info("\v\n"); + pmsg_info("processing %s\n", tofree = update_str(upd)); + free(tofree); + } + if(upd->cmdline) return terminal_line(pgm, p, upd->cmdline); From eee5aca79f2b835a2c013a7f37c0c7da18a6ab8b Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 1 Jun 2023 01:04:54 +0100 Subject: [PATCH 11/14] Provide an example for intermixing -T and -U options --- src/doc/avrdude.texi | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index c32387f6..0c3b33a6 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -2571,6 +2571,72 @@ avrdude done. Thank you. @end cartouche @end smallexample +@page + +@noindent +@strong{Mixing terminal commands and @code{-U} memory operations:} the +example below burns a bootloader, uses a terminal line to write +application data to flash, loads the application, configures the brownout +detection level to 2.7 V and, finally, stores the full flash as new hex +file. Note the use of different quotation marks in @code{bash} to pass the +terminal command lines as single entity to AVRDUDE. Also note the extra +@code{flush} terminal command that AVRDUDE inserted to ensure the terminal +cache and @code{-U} update operations work seamlessly. + +@smallexample +@cartouche + +$ avrdude -qc dryrun -p m328p \ + -U urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex \ + -T 'write flash 0x7000 0xc0cac01a 0xcafe "secret Coca Cola recipe"' \ + -U flash:w:cola-vending-machine.hex \ + -T "config -v bod=*2v7" \ + -U flash:r:app+data.hex:I + +avrdude: AVR device initialized and ready to accept instructions +avrdude: device signature = 0x1e950f (probably m328p) +avrdude: Note: flash memory has been specified, an erase cycle will be performed. + To disable this feature, specify the -D option. +avrdude: erasing chip + +avrdude: processing -U flash:w:urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex:i +avrdude: reading input file urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex for flash + with 368 bytes in 2 sections within [0x7e80, 0x7fff] + using 3 pages and 16 pad bytes +avrdude: writing 368 bytes flash ... +avrdude: 368 bytes of flash written +avrdude: verifying flash memory against urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex +avrdude: 368 bytes of flash verified + +avrdude: processing -T write flash 0x7000 0xc0cac01a 0xcafe "secret Coca Cola recipe" + +avrdude: processing -T flush +avrdude: synching cache to device ... done + +avrdude: processing -U flash:w:cola-vending-machine.hex:i +avrdude: reading input file cola-vending-machine.hex for flash + with 736 bytes in 1 section within [0, 0x2df] + using 6 pages and 32 pad bytes +avrdude: writing 736 bytes flash ... +avrdude: 736 bytes of flash written +avrdude: verifying flash memory against cola-vending-machine.hex +avrdude: 736 bytes of flash verified + +avrdude: processing -T config -v bod=*2v7 +config bodlevel=bod_2v7 # 5 + +avrdude: processing -T flush + +avrdude: processing -U flash:r:app+data.hex:I +avrdude: reading flash memory ... +avrdude: writing output file app+data.hex + +avrdude done. Thank you. + +@end cartouche +@end smallexample + + @page @c From b41d14a8c93231274c83a904e215dad4379bfa85 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 1 Jun 2023 01:07:43 +0100 Subject: [PATCH 12/14] Move terminal_...() functions into libavrdude.h --- src/CMakeLists.txt | 3 +-- src/Makefile.am | 5 ++--- src/term.h | 34 ---------------------------------- 3 files changed, 3 insertions(+), 39 deletions(-) delete mode 100644 src/term.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4505ef1b..c10a77eb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -228,6 +228,7 @@ add_library(libavrdude strutil.c teensy.c teensy.h + term.c tpi.h updi_constants.h updi_link.c @@ -292,8 +293,6 @@ target_link_libraries(libavrdude add_executable(avrdude main.c - term.c - term.h developer_opts.c developer_opts.h developer_opts_private.h diff --git a/src/Makefile.am b/src/Makefile.am index 5f9c97db..9ac585a5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -175,6 +175,7 @@ libavrdude_a_SOURCES = \ strutil.c \ teensy.c \ teensy.h \ + term.c \ tpi.h \ usbasp.c \ usbasp.h \ @@ -214,9 +215,7 @@ avrdude_SOURCES = \ whereami.h \ developer_opts.c \ developer_opts.h \ - developer_opts_private.h \ - term.c \ - term.h + developer_opts_private.h man_MANS = avrdude.1 diff --git a/src/term.h b/src/term.h deleted file mode 100644 index 45b2a385..00000000 --- a/src/term.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * avrdude - A Downloader/Uploader for AVR device programmers - * Copyright (C) 2000-2004 Brian S. Dean - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* $Id$ */ - -#ifndef term_h -#define term_h - -#include "libavrdude.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif From 161eb064ae16ca5f79638d411b4b46e4ac1fa039 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 1 Jun 2023 21:24:52 +0100 Subject: [PATCH 13/14] Move cache flush/reset from -T/U parsing to -U/T execution What happens is the same, just the code is crisper and clearer. --- src/doc/avrdude.texi | 12 +++--------- src/main.c | 27 ++++++++++----------------- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 0c3b33a6..ce6afba0 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -2579,16 +2579,14 @@ example below burns a bootloader, uses a terminal line to write application data to flash, loads the application, configures the brownout detection level to 2.7 V and, finally, stores the full flash as new hex file. Note the use of different quotation marks in @code{bash} to pass the -terminal command lines as single entity to AVRDUDE. Also note the extra -@code{flush} terminal command that AVRDUDE inserted to ensure the terminal -cache and @code{-U} update operations work seamlessly. +terminal command lines as single entity to AVRDUDE. @smallexample @cartouche $ avrdude -qc dryrun -p m328p \ -U urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex \ - -T 'write flash 0x7000 0xc0cac01a 0xcafe "secret Coca Cola recipe"' \ + -T 'write flash 0x7D00 0xc0cac01a 0xcafe "secret Coca Cola recipe"' \ -U flash:w:cola-vending-machine.hex \ -T "config -v bod=*2v7" \ -U flash:r:app+data.hex:I @@ -2608,9 +2606,7 @@ avrdude: 368 bytes of flash written avrdude: verifying flash memory against urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex avrdude: 368 bytes of flash verified -avrdude: processing -T write flash 0x7000 0xc0cac01a 0xcafe "secret Coca Cola recipe" - -avrdude: processing -T flush +avrdude: processing -T write flash 0x7D00 0xc0cac01a 0xcafe "secret Coca Cola recipe" avrdude: synching cache to device ... done avrdude: processing -U flash:w:cola-vending-machine.hex:i @@ -2625,8 +2621,6 @@ avrdude: 736 bytes of flash verified avrdude: processing -T config -v bod=*2v7 config bodlevel=bod_2v7 # 5 -avrdude: processing -T flush - avrdude: processing -U flash:r:app+data.hex:I avrdude: reading flash memory ... avrdude: writing output file app+data.hex diff --git a/src/main.c b/src/main.c index d59f6638..36e5cdbe 100644 --- a/src/main.c +++ b/src/main.c @@ -632,7 +632,6 @@ int main(int argc, char * argv []) /* * process command line arguments */ - int memwrite = 0, memterminal = 0; while ((ch = getopt(argc,argv,"?Ab:B:c:C:DeE:Fi:l:np:OP:qstT:U:uvVx:yY:")) != -1) { switch (ch) { @@ -774,14 +773,7 @@ int main(int argc, char * argv []) break; case 'T': - upd = (UPDATE *) cfg_malloc(__func__, sizeof *upd); - upd->cmdline = optarg; - if(memwrite) { // Invalidate cache if device was written to - memwrite = 0; - ladd(updates, cmd_update("abort # Reset cache")); - } - memterminal = 1; - ladd(updates, upd); + ladd(updates, cmd_update(optarg)); break; case 'U': @@ -790,11 +782,6 @@ int main(int argc, char * argv []) pmsg_error("unable to parse update operation '%s'\n", optarg); exit(1); } - if(memterminal) { // Flush cache before any device memory access - memterminal = 0; - ladd(updates, cmd_update("flush")); - } - memwrite |= upd->op == DEVICE_WRITE; ladd(updates, upd); break; @@ -832,9 +819,6 @@ int main(int argc, char * argv []) } - if(memterminal) - ladd(updates, cmd_update("flush")); - if (logfile != NULL) { FILE *newstderr = freopen(logfile, "w", stderr); if (newstderr == NULL) { @@ -1517,8 +1501,16 @@ int main(int argc, char * argv []) } + int wrmem = 0; for (ln=lfirst(updates); ln; ln=lnext(ln)) { upd = ldata(ln); + if(upd->cmdline && wrmem) { // Invalidate cache if device was written to + wrmem = 0; + pgm->reset_cache(pgm, p); + } else if(!upd->cmdline) { // Flush cache before any device memory access + pgm->flush_cache(pgm, p); + wrmem |= upd->op == DEVICE_WRITE; + } rc = do_op(pgm, p, upd, uflags); if (rc && rc != LIBAVRDUDE_SOFTFAIL) { exitrc = 1; @@ -1526,6 +1518,7 @@ int main(int argc, char * argv []) } else if(rc == 0 && upd->op == DEVICE_WRITE && avr_memtype_is_flash_type(upd->memtype)) ce_delayed = 0; // Redeemed chip erase promise } + pgm->flush_cache(pgm, p); main_exit: From a694217603bcdbf9c8dc90d25590d57eea91ed7e Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 2 Jun 2023 21:23:25 +0100 Subject: [PATCH 14/14] Print all -U/-T arguments as headline when processing them --- src/update.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/update.c b/src/update.c index bd16aa48..2ca33b33 100644 --- a/src/update.c +++ b/src/update.c @@ -369,13 +369,11 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat int size; int rc; Filestats fs, fs_patched; + char *tofree; - if(!upd->cmdline || !str_eq(upd->cmdline, "abort # Reset cache")) { - char *tofree; - msg_info("\v\n"); - pmsg_info("processing %s\n", tofree = update_str(upd)); - free(tofree); - } + msg_info("\v\n"); + pmsg_info("processing %s\n", tofree = update_str(upd)); + free(tofree); if(upd->cmdline) return terminal_line(pgm, p, upd->cmdline);