Merge pull request #1373 from stefanrueger/terminal

Implement -T cmd to mix terminal commands with -U commands
This commit is contained in:
Stefan Rueger
2023-06-04 22:05:48 +01:00
committed by GitHub
11 changed files with 369 additions and 238 deletions

View File

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

View File

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

View File

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

View File

@@ -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}]
@@ -2563,6 +2571,66 @@ 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.
@smallexample
@cartouche
$ avrdude -qc dryrun -p m328p \
-U urboot_m328p_1s_autobaud_uart0_pr_ee_ce.hex \
-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
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 0x7D00 0xc0cac01a 0xcafe "secret Coca Cola recipe"
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 -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

View File

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

View File

@@ -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);
@@ -1051,10 +1053,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,21 +1075,15 @@ 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);
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);
// 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);
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);
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);
// Helper functions for dry run to determine file access
int update_is_okfile(const char *fn);
@@ -1235,6 +1232,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);
@@ -1245,6 +1246,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

View File

@@ -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 */
@@ -225,34 +224,35 @@ static void usage(void)
msg_error(
"Usage: %s [options]\n"
"Options:\n"
" -p <partno> Specify AVR device\n"
" -p <wildcard>/<flags> Run developer options for matched AVR devices\n"
" -b <baudrate> Override RS-232 baud rate\n"
" -B <bitclock> Specify bit clock period (us)\n"
" -C <config-file> Specify location of configuration file\n"
" -c <programmer> Specify programmer type\n"
" -c <wildcard>/<flags> 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 <delay> ISP Clock Delay [in microseconds]\n"
" -P <port> 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 <partno> Specify AVR device\n"
" -p <wildcard>/<flags> Run developer options for matched AVR devices\n"
" -b <baudrate> Override RS-232 baud rate\n"
" -B <bitclock> Specify bit clock period (us)\n"
" -C <config-file> Specify location of configuration file\n"
" -c <programmer> Specify programmer type\n"
" -c <wildcard>/<flags> 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 <delay> ISP Clock Delay [in microseconds]\n"
" -P <port> 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 <terminal cmd line> Slot terminal line into a list and run in turn\n"
" -U <memtype>:r|w|v:<filename>[: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 <exitspec>[,<exitspec>] List programmer exit specifications\n"
" -x <extended_param> Pass <extended_param> 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: <https://github.com/avrdudes/avrdude>\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 <exitsp>[,<exitsp>] List programmer exit specifications\n"
" -x <extended_param> Pass <extended_param> 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);
}
@@ -632,7 +632,7 @@ 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) {
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,6 +772,10 @@ int main(int argc, char * argv [])
pmsg_error("\"safemode\" feature no longer supported\n");
break;
case 'T':
ladd(updates, cmd_update(optarg));
break;
case 'U':
upd = parse_op(optarg);
if (upd == NULL) {
@@ -1235,7 +1239,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 +1449,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;
@@ -1495,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;
@@ -1504,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:

View File

@@ -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: "<stdin>";
}
const char *str_outname(const char *fn) {
return !fn? "???": strcmp(fn, "-")? fn: "<stdout>";
}
// 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;

View File

@@ -56,37 +56,36 @@
#include "avrdude.h"
#include "term.h"
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 +171,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 +198,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";
@@ -233,7 +232,7 @@ static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
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;
@@ -363,8 +362,12 @@ 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(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 <mem> <addr> <data>[,] {<data>[,]}\n"
@@ -419,7 +422,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
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;
@@ -575,7 +578,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
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;
@@ -585,7 +588,7 @@ static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
}
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");
@@ -632,7 +635,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 +649,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 +663,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 +716,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 <mem> <addr> <len> # Fill section with 0xff values\n"
@@ -726,7 +729,7 @@ static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
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 +755,7 @@ static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
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;
@@ -792,7 +795,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 <mem> <addr>\n"
@@ -802,7 +805,7 @@ static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
}
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;
@@ -837,7 +840,7 @@ static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
// 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];
@@ -889,7 +892,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);
@@ -1138,7 +1141,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;
@@ -1251,7 +1254,7 @@ static int cmd_config(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
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 +1416,7 @@ static int cmd_config(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
fl_t towrite;
towrite.i = (fusel.current & ~ct[ci].mask) | (toassign<<ct[ci].lsh);
AVRMEM *mem = avr_locate_mem(p, cc[ci].memstr);
const AVRMEM *mem = avr_locate_mem(p, cc[ci].memstr);
if(!mem) {
pmsg_error("(config) %s memory type not defined for part %s\n", cc[ci].memstr, p->desc);
ret = -1;
@@ -1443,7 +1446,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,10 +1463,10 @@ 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;
const AVRMEM *m;
if(argc > 1) {
msg_error(
@@ -1493,7 +1496,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 +1513,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 +1528,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 +1553,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 +1586,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 +1612,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 +1654,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 +1680,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 +1694,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 +1710,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 +1742,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 +1837,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 +1880,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 +1909,27 @@ static int process_line(char *q, PROGRAMMER *pgm, struct avrpart *p) {
}
/*
* 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 PROGRAMMER *term_pgm;
static struct avrpart *term_p;
static const PROGRAMMER *term_pgm;
static const AVRPART *term_p;
static int term_running;
@@ -1960,7 +1979,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);
@@ -1991,7 +2010,7 @@ void term_gotline(char *cmdstr) {
}
int terminal_mode_interactive(PROGRAMMER *pgm, struct avrpart *p) {
static int terminal_mode_interactive(const PROGRAMMER *pgm, const AVRPART *p) {
term_pgm = pgm; // For callback routine
term_p = p;
@@ -2014,7 +2033,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 +2049,9 @@ int terminal_mode_noninteractive(PROGRAMMER *pgm, struct avrpart *p) {
return pgm->flush_cache(pgm, p);
}
int terminal_mode(PROGRAMMER *pgm, struct avrpart *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.
// EditLine (NetBSD, MacOS) has issues with that, so only use it when

View File

@@ -1,43 +0,0 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/* $Id$ */
#ifndef term_h
#define term_h
#include "libavrdude.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
WRITE_MODE_STANDARD = 0,
WRITE_MODE_FILL = 1,
} mode;
int terminal_mode(PROGRAMMER * pgm, struct avrpart * p);
char * terminal_get_input(const char *prompt);
void terminal_setup_update_progress();
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -42,15 +42,15 @@
* flash write). This allows colons in filenames other than those for
* enclosing <op> and separating <fmt>, eg, C:/some/file.hex
*/
UPDATE *parse_op(char *s) {
UPDATE *parse_op(const char *s) {
// Assume -U <file>[:<fmt>] 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 <memory>: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,20 +111,25 @@ 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;
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) {
@@ -141,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) {
@@ -211,39 +224,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: "<stdin>";
}
const char *update_outname(const char *fn) {
return !fn? "???": strcmp(fn, "-")? fn: "<stdout>";
}
// 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) {
@@ -290,7 +270,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)
@@ -298,13 +278,16 @@ 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;
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)
@@ -380,12 +363,20 @@ 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;
int rc;
Filestats fs, fs_patched;
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);
mem = avr_locate_mem(p, upd->memtype);
if (mem == NULL) {
@@ -422,11 +413,11 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags
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;
@@ -436,27 +427,27 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags
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");
}
@@ -466,7 +457,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags
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)
@@ -475,16 +466,16 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags
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");
}
}
@@ -494,7 +485,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags
// 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)
@@ -512,7 +503,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags
}
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;
@@ -525,17 +516,17 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags
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;
@@ -552,7 +543,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags
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);
}
@@ -579,7 +570,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags
}
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);