Merge pull request #1053 from stefanrueger/main
Enable stdin verification and display correct number of bytes written/verified
This commit is contained in:
commit
5f01d900f5
48
src/avr.c
48
src/avr.c
|
@ -1220,7 +1220,55 @@ int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Typical order in which memories show in avrdude.conf, runtime adds unknown ones (if any)
|
||||||
|
const char *avr_mem_order[100] = {
|
||||||
|
"eeprom", "flash", "application", "apptable",
|
||||||
|
"boot", "lfuse", "hfuse", "efuse",
|
||||||
|
"fuse", "fuse0", "wdtcfg", "fuse1",
|
||||||
|
"bodcfg", "fuse2", "osccfg", "fuse3",
|
||||||
|
"fuse4", "tcd0cfg", "fuse5", "syscfg0",
|
||||||
|
"fuse6", "syscfg1", "fuse7", "append",
|
||||||
|
"codesize", "fuse8", "fuse9", "bootend",
|
||||||
|
"bootsize", "fuses", "lock", "lockbits",
|
||||||
|
"tempsense", "signature", "prodsig", "sernum",
|
||||||
|
"calibration", "osccal16", "osccal20", "osc16err",
|
||||||
|
"osc20err", "usersig", "userrow", "data",
|
||||||
|
};
|
||||||
|
|
||||||
|
void avr_add_mem_order(const char *str) {
|
||||||
|
for(size_t i=0; i < sizeof avr_mem_order/sizeof *avr_mem_order; i++) {
|
||||||
|
if(avr_mem_order[i] && !strcmp(avr_mem_order[i], str))
|
||||||
|
return;
|
||||||
|
if(!avr_mem_order[i]) {
|
||||||
|
avr_mem_order[i] = strdup(str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
avrdude_message(MSG_INFO,
|
||||||
|
"%s: avr_mem_order[] under-dimensioned in avr.c; increase and recompile\n",
|
||||||
|
progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int avr_mem_is_known(const char *str) {
|
||||||
|
if(str && *str)
|
||||||
|
for(size_t i=0; i < sizeof avr_mem_order/sizeof *avr_mem_order; i++)
|
||||||
|
if(avr_mem_order[i] && !strcmp(avr_mem_order[i], str))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int avr_mem_might_be_known(const char *str) {
|
||||||
|
if(str && *str)
|
||||||
|
for(size_t i=0; i < sizeof avr_mem_order/sizeof *avr_mem_order; i++)
|
||||||
|
if(avr_mem_order[i] && !strncmp(avr_mem_order[i], str, strlen(str)))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1320,6 +1320,7 @@ part_parm :
|
||||||
mem->desc[AVR_MEMDESCLEN-1] = 0;
|
mem->desc[AVR_MEMDESCLEN-1] = 0;
|
||||||
ladd(current_part->mem, mem);
|
ladd(current_part->mem, mem);
|
||||||
}
|
}
|
||||||
|
avr_add_mem_order($2->value.string);
|
||||||
current_mem = mem;
|
current_mem = mem;
|
||||||
free_token($2);
|
free_token($2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,35 +280,6 @@ static void dev_stack_out(bool tsv, AVRPART *p, const char *name, unsigned char
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// order in which memories are processed, runtime adds unknown ones (but there shouldn't be any)
|
|
||||||
static const char *mem_order[100] = {
|
|
||||||
"eeprom", "flash", "application", "apptable",
|
|
||||||
"boot", "lfuse", "hfuse", "efuse",
|
|
||||||
"fuse", "fuse0", "wdtcfg", "fuse1",
|
|
||||||
"bodcfg", "fuse2", "osccfg", "fuse3",
|
|
||||||
"fuse4", "tcd0cfg", "fuse5", "syscfg0",
|
|
||||||
"fuse6", "syscfg1", "fuse7", "append",
|
|
||||||
"codesize", "fuse8", "fuse9", "bootend",
|
|
||||||
"bootsize", "fuses", "lock", "lockbits",
|
|
||||||
"tempsense", "signature", "prodsig", "sernum",
|
|
||||||
"calibration", "osccal16", "osccal20", "osc16err",
|
|
||||||
"osc20err", "usersig", "userrow", "data",
|
|
||||||
};
|
|
||||||
|
|
||||||
static void add_mem_order(const char *str) {
|
|
||||||
for(size_t i=0; i < sizeof mem_order/sizeof *mem_order; i++) {
|
|
||||||
if(mem_order[i] && !strcmp(mem_order[i], str))
|
|
||||||
return;
|
|
||||||
if(!mem_order[i]) {
|
|
||||||
mem_order[i] = strdup(str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dev_info("%s: mem_order[] under-dimensioned in developer_opts.c; increase and recompile\n", progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int intcmp(int a, int b) {
|
static int intcmp(int a, int b) {
|
||||||
return a-b;
|
return a-b;
|
||||||
}
|
}
|
||||||
|
@ -410,8 +381,8 @@ static int avrpart_deep_copy(AVRPARTdeep *d, AVRPART *p) {
|
||||||
|
|
||||||
// fill in all memories we got in defined order
|
// fill in all memories we got in defined order
|
||||||
di = 0;
|
di = 0;
|
||||||
for(size_t mi=0; mi < sizeof mem_order/sizeof *mem_order && mem_order[mi]; mi++) {
|
for(size_t mi=0; mi < sizeof avr_mem_order/sizeof *avr_mem_order && avr_mem_order[mi]; mi++) {
|
||||||
m = p->mem? avr_locate_mem(p, mem_order[mi]): NULL;
|
m = p->mem? avr_locate_mem(p, avr_mem_order[mi]): NULL;
|
||||||
if(m) {
|
if(m) {
|
||||||
if(di >= sizeof d->mems/sizeof *d->mems) {
|
if(di >= sizeof d->mems/sizeof *d->mems) {
|
||||||
avrdude_message(MSG_INFO, "%s: ran out of mems[] space, increase size in AVRMEMdeep of developer_opts.c and recompile\n", progname);
|
avrdude_message(MSG_INFO, "%s: ran out of mems[] space, increase size in AVRMEMdeep of developer_opts.c and recompile\n", progname);
|
||||||
|
@ -566,11 +537,11 @@ static void dev_part_strct(AVRPART *p, bool tsv, AVRPART *base) {
|
||||||
if(!base || opcodecmp(p->op[i], base->op[i], i))
|
if(!base || opcodecmp(p->op[i], base->op[i], i))
|
||||||
dev_part_strct_entry(tsv, ".ptop", p->desc, "part", opcodename(i), opcode2str(p->op[i], i, !tsv));
|
dev_part_strct_entry(tsv, ".ptop", p->desc, "part", opcodename(i), opcode2str(p->op[i], i, !tsv));
|
||||||
|
|
||||||
for(size_t mi=0; mi < sizeof mem_order/sizeof *mem_order && mem_order[mi]; mi++) {
|
for(size_t mi=0; mi < sizeof avr_mem_order/sizeof *avr_mem_order && avr_mem_order[mi]; mi++) {
|
||||||
AVRMEM *m, *bm;
|
AVRMEM *m, *bm;
|
||||||
|
|
||||||
m = p->mem? avr_locate_mem(p, mem_order[mi]): NULL;
|
m = p->mem? avr_locate_mem(p, avr_mem_order[mi]): NULL;
|
||||||
bm = base && base->mem? avr_locate_mem(base, mem_order[mi]): NULL;
|
bm = base && base->mem? avr_locate_mem(base, avr_mem_order[mi]): NULL;
|
||||||
|
|
||||||
if(!m && bm && !tsv)
|
if(!m && bm && !tsv)
|
||||||
dev_info("\n memory \"%s\" = NULL;\n", bm->desc);
|
dev_info("\n memory \"%s\" = NULL;\n", bm->desc);
|
||||||
|
@ -694,12 +665,12 @@ void dev_output_part_defs(char *partdesc) {
|
||||||
AVRPART *p = ldata(ln1);
|
AVRPART *p = ldata(ln1);
|
||||||
if(p->mem)
|
if(p->mem)
|
||||||
for(LNODEID lnm=lfirst(p->mem); lnm; lnm=lnext(lnm))
|
for(LNODEID lnm=lfirst(p->mem); lnm; lnm=lnext(lnm))
|
||||||
add_mem_order(((AVRMEM *) ldata(lnm))->desc);
|
avr_add_mem_order(((AVRMEM *) ldata(lnm))->desc);
|
||||||
|
|
||||||
// same for aliased memories (though probably not needed)
|
// same for aliased memories (though probably not needed)
|
||||||
if(p->mem_alias)
|
if(p->mem_alias)
|
||||||
for(LNODEID lnm=lfirst(p->mem_alias); lnm; lnm=lnext(lnm))
|
for(LNODEID lnm=lfirst(p->mem_alias); lnm; lnm=lnext(lnm))
|
||||||
add_mem_order(((AVRMEM_ALIAS *) ldata(lnm))->desc);
|
avr_add_mem_order(((AVRMEM_ALIAS *) ldata(lnm))->desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
nprinted = dev_nprinted;
|
nprinted = dev_nprinted;
|
||||||
|
|
|
@ -783,6 +783,7 @@ void sort_programmers(LISTID programmers);
|
||||||
typedef void (*FP_UpdateProgress)(int percent, double etime, char *hdr);
|
typedef void (*FP_UpdateProgress)(int percent, double etime, char *hdr);
|
||||||
|
|
||||||
extern struct avrpart parts[];
|
extern struct avrpart parts[];
|
||||||
|
extern const char *avr_mem_order[100];
|
||||||
|
|
||||||
extern FP_UpdateProgress update_progress;
|
extern FP_UpdateProgress update_progress;
|
||||||
|
|
||||||
|
@ -818,6 +819,11 @@ int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles);
|
||||||
|
|
||||||
int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles);
|
int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles);
|
||||||
|
|
||||||
|
void avr_add_mem_order(const char *str);
|
||||||
|
|
||||||
|
int avr_mem_is_known(const char *str);
|
||||||
|
int avr_mem_might_be_known(const char *str);
|
||||||
|
|
||||||
#define disable_trailing_ff_removal() avr_mem_hiaddr(NULL)
|
#define disable_trailing_ff_removal() avr_mem_hiaddr(NULL)
|
||||||
int avr_mem_hiaddr(AVRMEM * mem);
|
int avr_mem_hiaddr(AVRMEM * mem);
|
||||||
|
|
||||||
|
@ -888,6 +894,7 @@ enum updateflags {
|
||||||
UF_NONE = 0,
|
UF_NONE = 0,
|
||||||
UF_NOWRITE = 1,
|
UF_NOWRITE = 1,
|
||||||
UF_AUTO_ERASE = 2,
|
UF_AUTO_ERASE = 2,
|
||||||
|
UF_VERIFY = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -898,6 +905,17 @@ typedef struct update_t {
|
||||||
int format;
|
int format;
|
||||||
} UPDATE;
|
} UPDATE;
|
||||||
|
|
||||||
|
typedef struct { // File reads for flash can exclude trailing 0xff, which are cut off
|
||||||
|
int nbytes, // Number of bytes set including 0xff but excluding cut off, trailing 0xff
|
||||||
|
nsections, // Number of consecutive sections in source excluding cut off, trailing 0xff
|
||||||
|
npages, // Number of memory pages needed excluding pages solely with trailing 0xff
|
||||||
|
nfill, // Number of fill bytes to make up full pages that are needed
|
||||||
|
ntrailing, // Number of trailing 0xff in source
|
||||||
|
firstaddr, // First address set in [0, mem->size-1]
|
||||||
|
lastaddr; // Highest address set by input file
|
||||||
|
} Filestats;
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -910,6 +928,14 @@ extern void free_update(UPDATE * upd);
|
||||||
extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
|
extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
|
||||||
enum updateflags flags);
|
enum updateflags flags);
|
||||||
|
|
||||||
|
extern int memstats(struct avrpart *p, char *memtype, int size, Filestats *fsp);
|
||||||
|
|
||||||
|
// Convenience functions for printing
|
||||||
|
const char *plural(int x);
|
||||||
|
const char *inname(const char *fn);
|
||||||
|
const char *outname(const char *fn);
|
||||||
|
const char *interval(int a, int b);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
23
src/main.c
23
src/main.c
|
@ -237,7 +237,7 @@ static void cleanup_main(void)
|
||||||
static void replace_backslashes(char *s)
|
static void replace_backslashes(char *s)
|
||||||
{
|
{
|
||||||
// Replace all backslashes with forward slashes
|
// Replace all backslashes with forward slashes
|
||||||
for (int i = 0; i < strlen(s); i++) {
|
for (size_t i = 0; i < strlen(s); i++) {
|
||||||
if (s[i] == '\\') {
|
if (s[i] == '\\') {
|
||||||
s[i] = '/';
|
s[i] = '/';
|
||||||
}
|
}
|
||||||
|
@ -267,7 +267,6 @@ int main(int argc, char * argv [])
|
||||||
int calibrate; /* 1=calibrate RC oscillator, 0=don't */
|
int calibrate; /* 1=calibrate RC oscillator, 0=don't */
|
||||||
char * port; /* device port (/dev/xxx) */
|
char * port; /* device port (/dev/xxx) */
|
||||||
int terminal; /* 1=enter terminal mode, 0=don't */
|
int terminal; /* 1=enter terminal mode, 0=don't */
|
||||||
int verify; /* perform a verify operation */
|
|
||||||
char * exitspecs; /* exit specs string from command line */
|
char * exitspecs; /* exit specs string from command line */
|
||||||
char * programmer; /* programmer id */
|
char * programmer; /* programmer id */
|
||||||
char * partdesc; /* part id */
|
char * partdesc; /* part id */
|
||||||
|
@ -284,7 +283,7 @@ int main(int argc, char * argv [])
|
||||||
int init_ok; /* Device initialization worked well */
|
int init_ok; /* Device initialization worked well */
|
||||||
int is_open; /* Device open succeeded */
|
int is_open; /* Device open succeeded */
|
||||||
char * logfile; /* Use logfile rather than stderr for diagnostics */
|
char * logfile; /* Use logfile rather than stderr for diagnostics */
|
||||||
enum updateflags uflags = UF_AUTO_ERASE; /* Flags for do_op() */
|
enum updateflags uflags = UF_AUTO_ERASE | UF_VERIFY; /* Flags for do_op() */
|
||||||
|
|
||||||
#if !defined(WIN32)
|
#if !defined(WIN32)
|
||||||
char * homedir;
|
char * homedir;
|
||||||
|
@ -349,7 +348,6 @@ int main(int argc, char * argv [])
|
||||||
p = NULL;
|
p = NULL;
|
||||||
ovsigck = 0;
|
ovsigck = 0;
|
||||||
terminal = 0;
|
terminal = 0;
|
||||||
verify = 1; /* on by default */
|
|
||||||
quell_progress = 0;
|
quell_progress = 0;
|
||||||
exitspecs = NULL;
|
exitspecs = NULL;
|
||||||
pgm = NULL;
|
pgm = NULL;
|
||||||
|
@ -525,12 +523,6 @@ int main(int argc, char * argv [])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
ladd(updates, upd);
|
ladd(updates, upd);
|
||||||
|
|
||||||
if (verify && upd->op == DEVICE_WRITE) {
|
|
||||||
upd = dup_update(upd);
|
|
||||||
upd->op = DEVICE_VERIFY;
|
|
||||||
ladd(updates, upd);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
|
@ -538,7 +530,7 @@ int main(int argc, char * argv [])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
verify = 0;
|
uflags &= ~UF_VERIFY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
|
@ -759,6 +751,7 @@ int main(int argc, char * argv [])
|
||||||
bitclock = default_bitclock;
|
bitclock = default_bitclock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE, "\n");
|
avrdude_message(MSG_NOTICE, "\n");
|
||||||
|
|
||||||
// developer option -p <wildcard>/[*codws] prints various aspects of part descriptions and exits
|
// developer option -p <wildcard>/[*codws] prints various aspects of part descriptions and exits
|
||||||
|
@ -926,6 +919,12 @@ int main(int argc, char * argv [])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!avr_mem_might_be_known(upd->memtype)) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: unknown memory type %s\n", progname, upd->memtype);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
// TODO: check whether filename other than "-" is readable/writable
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1251,7 +1250,7 @@ int main(int argc, char * argv [])
|
||||||
for (ln=lfirst(updates); ln; ln=lnext(ln)) {
|
for (ln=lfirst(updates); ln; ln=lnext(ln)) {
|
||||||
upd = ldata(ln);
|
upd = ldata(ln);
|
||||||
rc = do_op(pgm, p, upd, uflags);
|
rc = do_op(pgm, p, upd, uflags);
|
||||||
if (rc) {
|
if (rc && rc != LIBAVRDUDE_SOFTFAIL) {
|
||||||
exitrc = 1;
|
exitrc = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
330
src/update.c
330
src/update.c
|
@ -45,7 +45,7 @@ UPDATE * parse_op(char * s)
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
p = s;
|
p = s;
|
||||||
while ((i < (sizeof(buf)-1) && *p && (*p != ':')))
|
while (i < (int) sizeof(buf)-1 && *p && *p != ':')
|
||||||
buf[i++] = *p++;
|
buf[i++] = *p++;
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
|
|
||||||
|
@ -214,18 +214,124 @@ void free_update(UPDATE * u)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Memory statistics considering holes after a file read returned size bytes
|
||||||
|
int memstats(struct avrpart *p, char *memtype, int size, Filestats *fsp) {
|
||||||
|
Filestats ret = { 0 };
|
||||||
|
AVRMEM *mem = avr_locate_mem(p, memtype);
|
||||||
|
|
||||||
|
if(!mem) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: %s %s undefined\n",
|
||||||
|
progname, p->desc, memtype);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!mem->buf || !mem->tags) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: %s %s is not set\n",
|
||||||
|
progname, p->desc, memtype);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pgsize = mem->page_size;
|
||||||
|
if(pgsize < 1)
|
||||||
|
pgsize = 1;
|
||||||
|
|
||||||
|
if(size < 0 || size > mem->size) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: memstats() size %d at odds with %s %s size %d\n",
|
||||||
|
progname, size, p->desc, memtype, mem->size);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.lastaddr = -1;
|
||||||
|
int firstset = 0, insection = 0;
|
||||||
|
// Scan all memory
|
||||||
|
for(int addr = 0; addr < mem->size; ) {
|
||||||
|
int pageset = 0;
|
||||||
|
// Go page by page
|
||||||
|
for(int pgi = 0; pgi < pgsize; pgi++, addr++) {
|
||||||
|
if(mem->tags[addr] & TAG_ALLOCATED) {
|
||||||
|
if(!firstset) {
|
||||||
|
firstset = 1;
|
||||||
|
ret.firstaddr = addr;
|
||||||
|
}
|
||||||
|
ret.lastaddr = addr;
|
||||||
|
// size can be smaller than tags suggest owing to flash trailing-0xff
|
||||||
|
if(addr < size) {
|
||||||
|
ret.nbytes++;
|
||||||
|
if(!pageset) {
|
||||||
|
pageset = 1;
|
||||||
|
ret.nfill += pgi;
|
||||||
|
ret.npages++;
|
||||||
|
}
|
||||||
|
if(!insection) {
|
||||||
|
insection = 1;
|
||||||
|
ret.nsections++;
|
||||||
|
}
|
||||||
|
} else { // Now beyond size returned by input file read
|
||||||
|
ret.ntrailing++;
|
||||||
|
if(pageset)
|
||||||
|
ret.nfill++;
|
||||||
|
}
|
||||||
|
} else { // In a hole or beyond input file
|
||||||
|
insection = 0;
|
||||||
|
if(pageset)
|
||||||
|
ret.nfill++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fsp)
|
||||||
|
*fsp = ret;
|
||||||
|
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Convenience functions for printing
|
||||||
|
const char *plural(int x) {
|
||||||
|
return x==1? "": "s";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *inname(const char *fn) {
|
||||||
|
return !fn? "???": strcmp(fn, "-")? fn: "<stdin>";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *outname(const char *fn) {
|
||||||
|
return !fn? "???": strcmp(fn, "-")? fn: "<stdout>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return sth like "[0, 0x1ff]"
|
||||||
|
const char *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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags flags)
|
int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags flags)
|
||||||
{
|
{
|
||||||
struct avrpart * v;
|
struct avrpart * v;
|
||||||
AVRMEM * mem;
|
AVRMEM * mem;
|
||||||
int size, vsize;
|
int size;
|
||||||
int rc;
|
int rc;
|
||||||
|
Filestats fs;
|
||||||
|
|
||||||
mem = avr_locate_mem(p, upd->memtype);
|
mem = avr_locate_mem(p, upd->memtype);
|
||||||
if (mem == NULL) {
|
if (mem == NULL) {
|
||||||
avrdude_message(MSG_INFO, "\"%s\" memory type not defined for part \"%s\"\n",
|
avrdude_message(MSG_INFO, "%s: skipping -U %s:... as memory not defined for part %s\n",
|
||||||
upd->memtype, p->desc);
|
progname, upd->memtype, p->desc);
|
||||||
return -1;
|
return LIBAVRDUDE_SOFTFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVRMEM_ALIAS * alias_mem = avr_find_memalias(p, mem);
|
AVRMEM_ALIAS * alias_mem = avr_find_memalias(p, mem);
|
||||||
|
@ -235,167 +341,189 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
||||||
strcat(alias_mem_desc, alias_mem->desc);
|
strcat(alias_mem_desc, alias_mem->desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upd->op == DEVICE_READ) {
|
switch (upd->op) {
|
||||||
/*
|
case DEVICE_READ:
|
||||||
* read out the specified device memory and write it to a file
|
// Read out the specified device memory and write it to a file
|
||||||
*/
|
|
||||||
if (upd->format == FMT_IMM) {
|
if (upd->format == FMT_IMM) {
|
||||||
avrdude_message(MSG_INFO,
|
avrdude_message(MSG_INFO,
|
||||||
"%s: Invalid file format 'immediate' for output\n",
|
"%s: Invalid file format 'immediate' for output\n", progname);
|
||||||
progname, upd->filename);
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if (quell_progress < 2) {
|
if (quell_progress < 2)
|
||||||
avrdude_message(MSG_INFO, "%s: reading %s%s memory:\n",
|
avrdude_message(MSG_INFO, "%s: reading %s%s memory ...\n",
|
||||||
progname, mem->desc, alias_mem_desc);
|
progname, mem->desc, alias_mem_desc);
|
||||||
}
|
|
||||||
report_progress(0,1,"Reading");
|
report_progress(0, 1, "Reading");
|
||||||
rc = avr_read(pgm, p, upd->memtype, 0);
|
rc = avr_read(pgm, p, upd->memtype, 0);
|
||||||
|
report_progress(1, 1, NULL);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: failed to read all of %s%s memory, rc=%d\n",
|
avrdude_message(MSG_INFO, "%s: failed to read all of %s%s memory, rc=%d\n",
|
||||||
progname, mem->desc, alias_mem_desc, rc);
|
progname, mem->desc, alias_mem_desc, rc);
|
||||||
return -1;
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
report_progress(1,1,NULL);
|
|
||||||
size = rc;
|
size = rc;
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
if (quell_progress < 2) {
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
avrdude_message(MSG_INFO, "%s: Flash is empty, resulting file has no contents.\n",
|
avrdude_message(MSG_INFO, "%s: flash is empty, resulting file has no contents\n",
|
||||||
progname);
|
progname);
|
||||||
avrdude_message(MSG_INFO, "%s: writing output file \"%s\"\n",
|
avrdude_message(MSG_INFO, "%s: writing output file %s\n",
|
||||||
progname,
|
progname, outname(upd->filename));
|
||||||
strcmp(upd->filename, "-")==0 ? "<stdout>" : upd->filename);
|
|
||||||
}
|
}
|
||||||
rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size);
|
rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: write to file '%s' failed\n",
|
avrdude_message(MSG_INFO, "%s: write to file %s failed\n",
|
||||||
progname, upd->filename);
|
progname, outname(upd->filename));
|
||||||
return -1;
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (upd->op == DEVICE_WRITE) {
|
|
||||||
/*
|
|
||||||
* write the selected device memory using data from a file; first
|
|
||||||
* read the data from the specified file
|
|
||||||
*/
|
|
||||||
if (quell_progress < 2) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: reading input file \"%s\"\n",
|
|
||||||
progname,
|
|
||||||
strcmp(upd->filename, "-")==0 ? "<stdin>" : upd->filename);
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEVICE_WRITE:
|
||||||
|
// Write the selected device memory using data from a file
|
||||||
|
|
||||||
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1);
|
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1);
|
||||||
|
if (quell_progress < 2)
|
||||||
|
avrdude_message(MSG_INFO, "%s: reading input file %s for %s%s\n",
|
||||||
|
progname, inname(upd->filename), mem->desc, alias_mem_desc);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
|
avrdude_message(MSG_INFO, "%s: read from file %s failed\n",
|
||||||
progname, upd->filename);
|
progname, inname(upd->filename));
|
||||||
return -1;
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
size = rc;
|
size = rc;
|
||||||
|
|
||||||
/*
|
if(memstats(p, upd->memtype, size, &fs) < 0)
|
||||||
* write the buffer contents to the selected memory type
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
*/
|
|
||||||
if (quell_progress < 2) {
|
if(quell_progress < 2) {
|
||||||
avrdude_message(MSG_INFO, "%s: writing %s%s (%d bytes):\n",
|
int level = fs.nsections > 1 || fs.firstaddr > 0 || fs.ntrailing? MSG_INFO: MSG_NOTICE;
|
||||||
progname, mem->desc, alias_mem_desc, size);
|
|
||||||
}
|
avrdude_message(level, "%*s with %d byte%s in %d section%s within %s\n",
|
||||||
|
(int) strlen(progname)+1, "",
|
||||||
|
fs.nbytes, plural(fs.nbytes),
|
||||||
|
fs.nsections, plural(fs.nsections),
|
||||||
|
interval(fs.firstaddr, fs.lastaddr));
|
||||||
|
if(mem->page_size > 1) {
|
||||||
|
avrdude_message(level, "%*s using %d page%s and %d pad byte%s",
|
||||||
|
(int) strlen(progname)+1, "",
|
||||||
|
fs.npages, plural(fs.npages),
|
||||||
|
fs.nfill, plural(fs.nfill));
|
||||||
|
if(fs.ntrailing)
|
||||||
|
avrdude_message(level, ", cutting off %d trailing 0xff byte%s",
|
||||||
|
fs.ntrailing, plural(fs.ntrailing));
|
||||||
|
avrdude_message(level, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the buffer contents to the selected memory type
|
||||||
|
if (quell_progress < 2)
|
||||||
|
avrdude_message(MSG_INFO, "%s: writing %d byte%s %s%s ...\n",
|
||||||
|
progname, fs.nbytes, plural(fs.nbytes), mem->desc, alias_mem_desc);
|
||||||
|
|
||||||
if (!(flags & UF_NOWRITE)) {
|
if (!(flags & UF_NOWRITE)) {
|
||||||
report_progress(0,1,"Writing");
|
report_progress(0, 1, "Writing");
|
||||||
rc = avr_write(pgm, p, upd->memtype, size, (flags & UF_AUTO_ERASE) != 0);
|
rc = avr_write(pgm, p, upd->memtype, size, (flags & UF_AUTO_ERASE) != 0);
|
||||||
report_progress(1,1,NULL);
|
report_progress(1, 1, NULL);
|
||||||
}
|
} else {
|
||||||
else {
|
// Test mode: write to stdout in intel hex rather than to the chip
|
||||||
/*
|
|
||||||
* test mode, don't actually write to the chip, output the buffer
|
|
||||||
* to stdout in intel hex instead
|
|
||||||
*/
|
|
||||||
rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size);
|
rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: failed to write %s%s memory, rc=%d\n",
|
avrdude_message(MSG_INFO, "%s: failed to write %s%s memory, rc=%d\n",
|
||||||
progname, mem->desc, alias_mem_desc, rc);
|
progname, mem->desc, alias_mem_desc, rc);
|
||||||
return -1;
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
vsize = rc;
|
if (quell_progress < 2)
|
||||||
|
avrdude_message(MSG_INFO, "%s: %d byte%s of %s%s written\n",
|
||||||
|
progname, fs.nbytes, plural(fs.nbytes), mem->desc, alias_mem_desc);
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
// Fall through for (default) auto verify, ie, unless -V was specified
|
||||||
avrdude_message(MSG_INFO, "%s: %d bytes of %s%s written\n", progname,
|
if (!(flags & UF_VERIFY))
|
||||||
vsize, mem->desc, alias_mem_desc);
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
case DEVICE_VERIFY:
|
||||||
else if (upd->op == DEVICE_VERIFY) {
|
// Verify that the in memory file is the same as what is on the chip
|
||||||
/*
|
|
||||||
* verify that the in memory file (p->mem[AVR_M_FLASH|AVR_M_EEPROM])
|
|
||||||
* is the same as what is on the chip
|
|
||||||
*/
|
|
||||||
pgm->vfy_led(pgm, ON);
|
pgm->vfy_led(pgm, ON);
|
||||||
|
|
||||||
|
int userverify = upd->op == DEVICE_VERIFY; // Explicit -U :v by user
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
if (quell_progress < 2) {
|
||||||
avrdude_message(MSG_INFO, "%s: verifying %s%s memory against %s:\n",
|
avrdude_message(MSG_INFO, "%s: verifying %s%s memory against %s\n",
|
||||||
progname, mem->desc, alias_mem_desc, upd->filename);
|
progname, mem->desc, alias_mem_desc, inname(upd->filename));
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: load data %s%s data from input file %s:\n",
|
if (userverify)
|
||||||
progname, mem->desc, alias_mem_desc, upd->filename);
|
avrdude_message(MSG_NOTICE, "%s: load %s%s data from input file %s\n",
|
||||||
|
progname, mem->desc, alias_mem_desc, inname(upd->filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = fileio(FIO_READ_FOR_VERIFY, upd->filename, upd->format, p, upd->memtype, -1);
|
// No need to read file when fallen through from DEVICE_WRITE
|
||||||
if (rc < 0) {
|
if (userverify) {
|
||||||
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
|
rc = fileio(FIO_READ_FOR_VERIFY, upd->filename, upd->format, p, upd->memtype, -1);
|
||||||
progname, upd->filename);
|
|
||||||
return -1;
|
if (rc < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: read from file %s failed\n",
|
||||||
|
progname, inname(upd->filename));
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
size = rc;
|
||||||
|
|
||||||
|
if(memstats(p, upd->memtype, size, &fs) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
} else {
|
||||||
|
// Correct size of last read to include potentially cut off, trailing 0xff (flash)
|
||||||
|
size = fs.lastaddr+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = avr_dup_part(p);
|
v = avr_dup_part(p);
|
||||||
size = rc;
|
|
||||||
if (quell_progress < 2) {
|
if (quell_progress < 2) {
|
||||||
avrdude_message(MSG_NOTICE2, "%s: input file %s contains %d bytes\n",
|
if (userverify)
|
||||||
progname, upd->filename, size);
|
avrdude_message(MSG_NOTICE, "%s: input file %s contains %d byte%s\n",
|
||||||
avrdude_message(MSG_NOTICE2, "%s: reading on-chip %s%s data:\n",
|
progname, inname(upd->filename), fs.nbytes, plural(fs.nbytes));
|
||||||
progname, mem->desc, alias_mem_desc);
|
avrdude_message(MSG_NOTICE2, "%s: reading on-chip %s%s data ...\n",
|
||||||
|
progname, mem->desc, alias_mem_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
report_progress (0,1,"Reading");
|
report_progress (0,1,"Reading");
|
||||||
rc = avr_read(pgm, p, upd->memtype, v);
|
rc = avr_read(pgm, p, upd->memtype, v);
|
||||||
|
report_progress (1,1,NULL);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: failed to read all of %s%s memory, rc=%d\n",
|
avrdude_message(MSG_INFO, "%s: failed to read all of %s%s memory, rc=%d\n",
|
||||||
progname, mem->desc, alias_mem_desc, rc);
|
progname, mem->desc, alias_mem_desc, rc);
|
||||||
pgm->err_led(pgm, ON);
|
pgm->err_led(pgm, ON);
|
||||||
avr_free_part(v);
|
avr_free_part(v);
|
||||||
return -1;
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
report_progress (1,1,NULL);
|
|
||||||
|
|
||||||
|
if (quell_progress < 2)
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: verifying ...\n", progname);
|
avrdude_message(MSG_NOTICE2, "%s: verifying ...\n", progname);
|
||||||
}
|
|
||||||
rc = avr_verify(p, v, upd->memtype, size);
|
rc = avr_verify(p, v, upd->memtype, size);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: verification error; content mismatch\n",
|
avrdude_message(MSG_INFO, "%s: verification error; content mismatch\n",
|
||||||
progname);
|
progname);
|
||||||
pgm->err_led(pgm, ON);
|
pgm->err_led(pgm, ON);
|
||||||
avr_free_part(v);
|
avr_free_part(v);
|
||||||
return -1;
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
if (quell_progress < 2) {
|
||||||
avrdude_message(MSG_INFO, "%s: %d bytes of %s%s verified\n",
|
int verified = fs.nbytes+fs.ntrailing;
|
||||||
progname, rc, mem->desc, alias_mem_desc);
|
avrdude_message(MSG_INFO, "%s: %d byte%s of %s%s verified\n",
|
||||||
|
progname, verified, plural(verified), mem->desc, alias_mem_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
pgm->vfy_led(pgm, OFF);
|
pgm->vfy_led(pgm, OFF);
|
||||||
avr_free_part(v);
|
avr_free_part(v);
|
||||||
}
|
break;
|
||||||
else {
|
|
||||||
|
default:
|
||||||
avrdude_message(MSG_INFO, "%s: invalid update operation (%d) requested\n",
|
avrdude_message(MSG_INFO, "%s: invalid update operation (%d) requested\n",
|
||||||
progname, upd->op);
|
progname, upd->op);
|
||||||
return -1;
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return LIBAVRDUDE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue