From 31bed52080e36e9e145939b15bf386698ea64b10 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 14 Jul 2024 17:59:40 +0100 Subject: [PATCH 1/6] Consider prog_modes in str_ccmcunames_signature() --- src/fileio.c | 7 +++---- src/libavrdude.h | 6 +++--- src/strutil.c | 53 ++++++++++++++++++++++++++++++++++-------------- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 3004f1f99..4a637bcab 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -352,8 +352,7 @@ static int b2ihex(const AVRPART *p, const AVRMEM *mem, const Segment *segp, Sego if(name) { fprintf(outf, " %s", name); if((str_eq(name, "sigrow") || str_eq(name, "signature")) && !nextaddr) { - char mculist[1024] = {0}; - str_mcunames_signature(buf, mculist, sizeof mculist); + const char *mculist = str_ccmcunames_signature(buf, PM_ALL); if(*mculist) fprintf(outf, " (%s)", mculist); } @@ -580,7 +579,7 @@ static int ihex2b(const char *infile, FILE *inf, const AVRPART *p, const AVRMEM if(!ovsigck && nextaddr == mulmem[MULTI_SIGROW].base && ihex.reclen >= 3) if(!avr_sig_compatible(p->signature, any->buf+nextaddr)) { pmsg_error("signature of %s incompatible with file's (%s)\n", p->desc, - str_ccmcunames_signature(any->buf+nextaddr)); + str_ccmcunames_signature(any->buf+nextaddr, PM_ALL)); imsg_error("use -F to override this check\n"); mmt_free(buffer); goto error; @@ -935,7 +934,7 @@ static int srec2b(const char *infile, FILE * inf, const AVRPART *p, if(!ovsigck && nextaddr == mulmem[MULTI_SIGROW].base && srec.reclen >= 3) if(!avr_sig_compatible(p->signature, any->buf+nextaddr)) { pmsg_error("signature of %s incompatible with file's (%s)\n", p->desc, - str_ccmcunames_signature(any->buf+nextaddr)); + str_ccmcunames_signature(any->buf+nextaddr, PM_ALL)); imsg_error("use -F to override this check\n"); mmt_free(buffer); goto error; diff --git a/src/libavrdude.h b/src/libavrdude.h index baa24b1cd..9fa9041ad 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -511,7 +511,7 @@ typedef struct avrmem { int initval; /* factory setting of fuses and lock bits */ int bitmask; /* bits used in fuses and lock bits */ int n_word_writes; /* TPI only: number words to write at a time */ - unsigned int offset; /* offset in IO memory (ATxmega) */ + unsigned int offset; /* offset in IO memory (ATxmega, UPDI, some classic memories) */ int min_write_delay; /* microseconds */ int max_write_delay; /* microseconds */ int pwroff_after_write; /* after this memory is written to, @@ -1524,8 +1524,8 @@ char *str_nexttok(char *buf, const char *delim, char **next); const char *str_ccfrq(double f, int n); int str_levenshtein(const char *str1, const char *str2, int swap, int subst, int add, int del); size_t str_weighted_damerau_levenshtein(const char *str1, const char *str2); -int str_mcunames_signature(const unsigned char *sigs, char *p, size_t n); -const char *str_ccmcunames_signature(const unsigned char *sigs); +int str_mcunames_signature(const unsigned char *sigs, int pm, char *p, size_t n); +const char *str_ccmcunames_signature(const unsigned char *sigs, int pm); int led_set(const PROGRAMMER *pgm, int led); int led_clr(const PROGRAMMER *pgm, int led); diff --git a/src/strutil.c b/src/strutil.c index 4d442f917..b281f4115 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -1330,19 +1330,40 @@ size_t str_weighted_damerau_levenshtein(const char *s1, const char *s2) { // Puts a comma-separated list of matching MCU names into array p with n chars space -int str_mcunames_signature(const unsigned char *sigs, char *p, size_t n) { - int matching = 0; - - for(size_t i=0; i < sizeof uP_table/sizeof *uP_table; i++) { - if(0 == memcmp(sigs, uP_table[i].sigs, sizeof uP_table->sigs)) { - if(matching && n > 2) - strcpy(p, ", "), n -= 2, p += 2; - size_t len = strlen(uP_table[i].name); - if(n > len) { - strcpy(p, uP_table[i].name); - n -= len; p += len; +int str_mcunames_signature(const unsigned char *sigs, int pm, char *p, size_t n) { + int matching = 0, k; + const int N = 100; + const char *matches[N]; + + if(!pm || (pm & PM_ALL) == PM_ALL) // Look up uP table when unrestricted by prog modes + for(size_t i=0; i < sizeof uP_table/sizeof *uP_table; i++) + if(0 == memcmp(sigs, uP_table[i].sigs, sizeof uP_table->sigs) && matching < N) + matches[matching++] = uP_table[i].name; + + for(LNODEID lp = lfirst(part_list); lp; lp = lnext(lp)) { + AVRPART *pp = ldata(lp); + if(0 == memcmp(sigs, pp->signature, 3) && (!pm || (pp->prog_modes & pm))) { + for(k = 0; k < matching; k++) + if(str_eq(matches[k], pp->desc)) + break; + if(k == matching && matching < N) + matches[matching++] = pp->desc; + } + } + + if(n && p) { + *p = 0; + + for(int i = 0; i < matching; i++) { + size_t len = strlen(matches[i]); + if(n > len + 2) { + if(i) { + strcpy(p, ", "); + n -= 2, p += 2; + } + strcpy(p, matches[i]); + n -= len, p += len; } - matching++; } } @@ -1350,9 +1371,11 @@ int str_mcunames_signature(const unsigned char *sigs, char *p, size_t n) { } // Returns a comma-separated list of matching MCU names in closed-circuit space -const char *str_ccmcunames_signature(const unsigned char *sigs) { - char names[1024] = {0}; - (void) str_mcunames_signature(sigs, names, sizeof names); +const char *str_ccmcunames_signature(const unsigned char *sigs, int pm) { + char names[1024]; + // If no match is found, given required prog_modes, relax the match to any prog mode + if(!str_mcunames_signature(sigs, pm, names, sizeof names) && pm && (pm & PM_ALL) != PM_ALL) + (void) str_mcunames_signature(sigs, 0, names, sizeof names); return str_ccprintf("%s", names); } From 811d01e9dbd70187f5d7458626f61bc114d8110e Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 14 Jul 2024 18:35:37 +0100 Subject: [PATCH 2/6] Check several signature offsets when trying a -p UPDI part --- src/main.c | 55 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/src/main.c b/src/main.c index 51b0cb46a..4555d3420 100644 --- a/src/main.c +++ b/src/main.c @@ -1594,7 +1594,7 @@ int main(int argc, char * argv []) if (uflags & UF_NOWRITE) { pmsg_warning("conflicting -e and -n options specified, NOT erasing chip\n"); } else { - pmsg_info("erasing chip\n"); + pmsg_info("trying to unlock the chip\n"); exitrc = avr_unlock(pgm, p); if(exitrc) goto main_exit; @@ -1619,33 +1619,48 @@ int main(int argc, char * argv []) sig = avr_locate_signature(p); if (sig == NULL) pmsg_warning("signature memory not defined for device %s\n", p->desc); + else { + const char *mculist = str_ccmcunames_signature(sig->buf, pgm->prog_modes); + if(!*mculist) { + if(p->prog_modes & PM_UPDI) { // UPDI parts have different(!) offsets for signature + int k, n = 0; // Gather list of known different signature offsets + unsigned myoff = sig->offset, offlist[10]; + for(LNODEID ln1 = lfirst(part_list); ln1; ln1 = lnext(ln1)) { + AVRMEM *m = avr_locate_signature(ldata(ln1)); + if(m && m->offset != myoff) { + for(k=0; koffset == offlist[k]) + break; + if(k == n && k < (int) (sizeof offlist/sizeof*offlist)) + offlist[n++] = m->offset; + } + } + // Now go through the list of other(!) sig offsets and try these + for(k=0; koffset = offlist[k]; + if(avr_signature(pgm, p) >= 0) + if(*(mculist = str_ccmcunames_signature(sig->buf, pgm->prog_modes))) + break; + } + sig->offset = myoff; + } + } - if (sig != NULL) { - int ff, zz; - - pmsg_info("device signature = 0x"); - ff = zz = 1; + pmsg_info("device signature ="); + int ff = 1, zz = 1; for (i=0; isize; i++) { - msg_info("%02x", sig->buf[i]); + msg_info(" %02X", sig->buf[i]); if (sig->buf[i] != 0xff) ff = 0; if (sig->buf[i] != 0x00) zz = 0; } + if(*mculist) + msg_info(" (%s)", mculist); - bool signature_matches = - sig->size == 3 && - sig->buf[0] == p->signature[0] && - sig->buf[1] == p->signature[1] && - sig->buf[2] == p->signature[2]; - - if (quell_progress < 2) { - AVRPART *part; - if((part = locate_part_by_signature_pm(part_list, sig->buf, sig->size, pgm->prog_modes)) || - (part = locate_part_by_signature(part_list, sig->buf, sig->size))) - msg_info(" (probably %s)", signature_matches? p->id: part->id); - } - if (ff || zz) { + bool signature_matches = sig->size >= 3 && !memcmp(sig->buf, p->signature, 3); + + if (ff || zz) { // All three bytes are 0xff or all three bytes are 0x00 if (++attempt < 3) { waittime *= 5; msg_info(" (retrying)\n"); From 43c915aca35b3dc51bf4dac814ba85b3dec6d03e Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 14 Jul 2024 19:13:45 +0100 Subject: [PATCH 3/6] Skip parts with all 0xff/0x00 signature --- src/strutil.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/strutil.c b/src/strutil.c index b281f4115..fe1234b75 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -1337,12 +1337,17 @@ int str_mcunames_signature(const unsigned char *sigs, int pm, char *p, size_t n) if(!pm || (pm & PM_ALL) == PM_ALL) // Look up uP table when unrestricted by prog modes for(size_t i=0; i < sizeof uP_table/sizeof *uP_table; i++) - if(0 == memcmp(sigs, uP_table[i].sigs, sizeof uP_table->sigs) && matching < N) - matches[matching++] = uP_table[i].name; + if(!is_memset(uP_table[i].sigs, 0xff, 3) && !is_memset(uP_table[i].sigs, 0, 3)) + if(0 == memcmp(sigs, uP_table[i].sigs, sizeof uP_table->sigs) && matching < N) + matches[matching++] = uP_table[i].name; for(LNODEID lp = lfirst(part_list); lp; lp = lnext(lp)) { AVRPART *pp = ldata(lp); - if(0 == memcmp(sigs, pp->signature, 3) && (!pm || (pp->prog_modes & pm))) { + if(!*pp->id || *pp->id == '.') // Skip invalid entries + continue; + if(is_memset(pp->signature, 0xff, 3) || is_memset(pp->signature, 0, 3)) + continue; + if(!memcmp(sigs, pp->signature, 3) && (!pm || (pp->prog_modes & pm))) { for(k = 0; k < matching; k++) if(str_eq(matches[k], pp->desc)) break; From 99bd83c1867b5eb94e353cce637895b11750efce Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 14 Jul 2024 19:27:04 +0100 Subject: [PATCH 4/6] Suppress overzealous compiler warnings --- src/config_gram.y | 2 +- src/fileio.c | 12 ++++++------ src/strutil.c | 5 ++--- src/update.c | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/config_gram.y b/src/config_gram.y index 11e57316d..dcfc0d688 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -383,7 +383,7 @@ part_def : if(mem_is_signature(m)) m->type &= ~MEM_IN_SIGROW; } - if(fileio_mem_offset(current_part, m) == -1U) + if(fileio_mem_offset(current_part, m) == ~0U) yywarning("revise fileio_mem_offset(), avrdude.conf entry or memory type assignment"); } diff --git a/src/fileio.c b/src/fileio.c index 4a637bcab..b63037604 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -232,22 +232,22 @@ unsigned fileio_mem_offset(const AVRPART *p, const AVRMEM *mem) { mem_is_sib(mem)? MBASE(SIGROW) + 0x1000: // Arbitrary 0x1000 offset in signature section for sib mem_is_userrow(mem)? MBASE(USERROW): mem_is_bootrow(mem)? MBASE(BOOTROW): - -1U; + ~0U; - if(location == -1U) + if(location == ~0U) pmsg_error("unable to locate %s's %s in multi-memory address space\n", p->desc, mem->desc); else if(location >= ANY_MEM_SIZE || location + mem->size > ANY_MEM_SIZE) { // Overflow pmsg_error("%s's %s location [0x%06x, 0x%06x] outside flat address space [0, 0x%06x]\n", p->desc, mem->desc, location, location + mem->size-1, ANY_MEM_SIZE-1); - location = -1U; + location = ~0U; } else if(location <= MEND(FLASH) && location + mem->size > MEND(FLASH)+1) { pmsg_error("%s's %s location [0x%06x, 0x%06x] straddles flash section boundary 0x%06x\n", p->desc, mem->desc, location, location + mem->size-1, MEND(FLASH)+1); - location = -1U; + location = ~0U; } else if(location > MEND(FLASH) && location/0x10000 != (location + mem->size-1)/0x10000) { pmsg_error("%s's %s memory location [0x%06x, 0x%06x] straddles memory section boundary 0x%02x0000\n", p->desc, mem->desc, location, location + mem->size-1, 1+location/0x10000); - location = -1U; + location = ~0U; } return location; @@ -465,7 +465,7 @@ static int any2mem(const AVRPART *p, const AVRMEM *mem, const Segment *segp, // Compute location for multi-memory file input unsigned location = maxsize > MEND(FLASH)+1? fileio_mem_offset(p, mem): 0; - if(location == -1U) + if(location == ~0U) return -1; unsigned ret = 0; diff --git a/src/strutil.c b/src/strutil.c index fe1234b75..9fcd158fe 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -1331,9 +1331,8 @@ size_t str_weighted_damerau_levenshtein(const char *s1, const char *s2) { // Puts a comma-separated list of matching MCU names into array p with n chars space int str_mcunames_signature(const unsigned char *sigs, int pm, char *p, size_t n) { - int matching = 0, k; - const int N = 100; - const char *matches[N]; + const char *matches[100]; + int matching = 0, k, N = sizeof matches/sizeof*matches; if(!pm || (pm & PM_ALL) == PM_ALL) // Look up uP table when unrestricted by prog modes for(size_t i=0; i < sizeof uP_table/sizeof *uP_table; i++) diff --git a/src/update.c b/src/update.c index 9a5637a73..3b1bcb897 100644 --- a/src/update.c +++ b/src/update.c @@ -721,7 +721,7 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, const UPDATE *upd, enum updat continue; } unsigned off = fileio_mem_offset(p, m); - if(off == -1U) { + if(off == ~0U) { pmsg_warning("cannot map %s to flat address space, skipping ...\n", m_name); rwvproblem = 1; continue; From e4c67c2c6e43d32839b06ce31a15d6d0a2a938f4 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 15 Jul 2024 15:56:36 +0100 Subject: [PATCH 5/6] Skip stump parts and all 0xff/0x00 signatures in locate_part_by_signature() --- src/avrpart.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/avrpart.c b/src/avrpart.c index 38f38a97d..0de5303dc 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -1071,12 +1071,16 @@ AVRPART *locate_part_by_avr910_devcode(const LISTID parts, int devcode) { return NULL; } +// Return pointer to first part that has signature sig (unless all 0xff or all 0x00); NULL if no match AVRPART *locate_part_by_signature_pm(const LISTID parts, unsigned char *sig, int sigsize, int prog_modes) { if(parts && sigsize == 3) { for(LNODEID ln=lfirst(parts); ln; ln=lnext(ln)) { AVRPART *p = ldata(ln); - if(memcmp(p->signature, sig, 3) == 0 && p->prog_modes & prog_modes) - return p; + if(!*p->id || *p->id == '.') // Skip stump entries + continue; + if(!is_memset(p->signature, 0xff, 3) && !is_memset(p->signature, 0, 3)) + if(!memcmp(p->signature, sig, 3) && p->prog_modes & prog_modes) + return p; } } return NULL; From f3caabf264b8833f1eb0e9f988d03c188230bd14 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 15 Jul 2024 15:57:53 +0100 Subject: [PATCH 6/6] Make dryrun vector tables more realistic --- src/dryrun.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/dryrun.c b/src/dryrun.c index e5c3bbaff..2e8918bb7 100644 --- a/src/dryrun.c +++ b/src/dryrun.c @@ -298,14 +298,22 @@ static int flashlayout(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *fl // Write a vector table to flash addr and return number of bytes written static int putvectortable(const AVRPART *p, const AVRMEM *flm, int addr) { int vecsz = flm->size <= 8192? 2: 4, ret = p->n_interrupts * vecsz; + int app = (ret + vecsz - 2)/2; // Distance to application in words - for(int i = 0; i < ret; i += vecsz) { // First store rjmps - flm->buf[addr + i] = 255-i/2; - flm->buf[addr + i + 1] = 0xcf; // rjmp .-2, rjmp .-6, ... + for(int i = 0; i < ret; i += vecsz) { // First store rjmps to after table + flm->buf[addr + i] = app; + flm->buf[addr + i + 1] = 0xc0 + (app>>8); // rjmp app, rjmp app, ... + app -= vecsz/2; } + for(int i=0; i < vecsz; i++) // Leave one vector gap + flm->buf[addr + ret++] = ' '; + + flm->buf[addr + ret++] = 0xff; // Put endless lopp as application + flm->buf[addr + ret++] = 0xcf; + // Then round up to multiples of 32 while(ret%32) - flm->buf[ret++] = ' '; + flm->buf[addr + ret++] = ' '; return ret; }