Submitted by Martino Facchin:

patch #9110: Let reserved fuse bits to be read as *don't care*
* avr.c (compare_memory_masked): New function
* libavrdude.h: declare compare_memory_masked(); also, insist on C99
so <stdint.h> is required now
* main.c: Use compare_memory_masked() in safemode comparisons

C99 / stdint.h has basically already been required before, as types
like uint8_t are in use in a number of other locations throughout the
source.



git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1470 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Joerg Wunsch 2021-11-12 22:02:29 +00:00
parent 10df0ff15a
commit db7249bf57
5 changed files with 73 additions and 15 deletions

View File

@ -1,3 +1,12 @@
2021-11-12 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Martino Facchin:
patch #9110: Let reserved fuse bits to be read as *don't care*
* avr.c (compare_memory_masked): New function
* libavrdude.h: declare compare_memory_masked(); also, insist on C99
so <stdint.h> is required now
* main.c: Use compare_memory_masked() in safemode comparisons
2021-11-11 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Joseph Coffland:

1
NEWS
View File

@ -104,6 +104,7 @@ Current:
patch #9697: Add iseavrprog support
patch #10017: uspasp / tpi: Automatically clear configuration byte (fuse) before writing it
patch #8957: Allow reading prodsig memory from stk500v2 on xmega devices
patch #9110: Let reserved fuse bits to be read as *don't care*
* Internals:
- New avrdude.conf keyword "family_id", used to verify SIB attributes

53
avr.c
View File

@ -1063,6 +1063,30 @@ int avr_signature(PROGRAMMER * pgm, AVRPART * p)
return 0;
}
static uint8_t get_fuse_bitmask(AVRMEM * m) {
uint8_t bitmask_r = 0;
uint8_t bitmask_w = 0;
int i;
if (!m || m->size > 1) {
// not a fuse, compare bytes directly
return 0xFF;
}
// For fuses, only compare bytes that are actually written *and* read.
for (i = 0; i < 32; i++) {
if (m->op[AVR_OP_WRITE]->bit[i].type == AVR_CMDBIT_INPUT)
bitmask_w |= (1 << m->op[AVR_OP_WRITE]->bit[i].bitno);
if (m->op[AVR_OP_READ]->bit[i].type == AVR_CMDBIT_OUTPUT)
bitmask_r |= (1 << m->op[AVR_OP_READ]->bit[i].bitno);
}
return bitmask_r & bitmask_w;
}
int compare_memory_masked(AVRMEM * m, uint8_t b1, uint8_t b2) {
uint8_t bitmask = get_fuse_bitmask(m);
return (b1 & bitmask) != (b2 & bitmask);
}
/*
* Verify the memory buffer of p with that of v. The byte range of v,
@ -1109,11 +1133,30 @@ int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size)
for (i=0; i<size; i++) {
if ((b->tags[i] & TAG_ALLOCATED) != 0 &&
buf1[i] != buf2[i]) {
avrdude_message(MSG_INFO, "%s: verification error, first mismatch at byte 0x%04x\n"
"%s0x%02x != 0x%02x\n",
progname, i,
progbuf, buf1[i], buf2[i]);
return -1;
uint8_t bitmask = get_fuse_bitmask(a);
if((buf1[i] & bitmask) != (buf2[i] & bitmask)) {
// Mismatch is not just in unused bits
avrdude_message(MSG_INFO, "%s: verification error, first mismatch at byte 0x%04x\n"
"%s0x%02x != 0x%02x\n",
progname, i,
progbuf, buf1[i], buf2[i]);
return -1;
} else {
// Mismatch is only in unused bits
if ((buf1[i] | bitmask) != 0xff) {
// Programmer returned unused bits as 0, must be the part/programmer
avrdude_message(MSG_INFO, "%s: WARNING: ignoring mismatch in unused bits of \"%s\"\n"
"%s(0x%02x != 0x%02x). To prevent this warning fix the part\n"
"%sor programmer definition in the config file.\n",
progname, memtype, progbuf, buf1[i], buf2[i], progbuf);
} else {
// Programmer returned unused bits as 1, must be the user
avrdude_message(MSG_INFO, "%s: WARNING: ignoring mismatch in unused bits of \"%s\"\n"
"%s(0x%02x != 0x%02x). To prevent this warning set unused bits\n"
"%sto 1 when writing (double check with your datasheet first).\n",
progname, memtype, progbuf, buf1[i], buf2[i], progbuf);
}
}
}
}

View File

@ -33,11 +33,7 @@
#include <stdint.h>
typedef uint32_t pinmask_t;
#else
#if UINT_MAX >= 0xFFFFFFFF
typedef unsigned int pinmask_t;
#else
typedef unsigned long pinmask_t;
#endif
#error Need a C99 capable compiler
#endif
@ -342,6 +338,9 @@ typedef void (*walk_avrparts_cb)(const char *name, const char *desc,
void *cookie);
void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie);
void sort_avrparts(LISTID avrparts);
int compare_memory_masked(AVRMEM * m, uint8_t buf1, uint8_t buf2);
#ifdef __cplusplus
}
#endif

16
main.c
View File

@ -1300,8 +1300,11 @@ int main(int argc, char * argv [])
}
}
AVRMEM * m;
/* Now check what fuses are against what they should be */
if (safemodeafter_fuse != safemode_fuse) {
m = avr_locate_mem(p, "fuse");
if (compare_memory_masked(m, safemodeafter_fuse, safemode_fuse)) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: fuse changed! Was %x, and is now %x\n",
progname, safemode_fuse, safemodeafter_fuse);
@ -1329,7 +1332,8 @@ int main(int argc, char * argv [])
}
/* Now check what fuses are against what they should be */
if (safemodeafter_lfuse != safemode_lfuse) {
m = avr_locate_mem(p, "lfuse");
if (compare_memory_masked(m, safemodeafter_lfuse, safemode_lfuse)) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: lfuse changed! Was %x, and is now %x\n",
progname, safemode_lfuse, safemodeafter_lfuse);
@ -1357,7 +1361,8 @@ int main(int argc, char * argv [])
}
/* Now check what fuses are against what they should be */
if (safemodeafter_hfuse != safemode_hfuse) {
m = avr_locate_mem(p, "hfuse");
if (compare_memory_masked(m, safemodeafter_hfuse, safemode_hfuse)) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: hfuse changed! Was %x, and is now %x\n",
progname, safemode_hfuse, safemodeafter_hfuse);
@ -1382,7 +1387,8 @@ int main(int argc, char * argv [])
}
/* Now check what fuses are against what they should be */
if (safemodeafter_efuse != safemode_efuse) {
m = avr_locate_mem(p, "efuse");
if (compare_memory_masked(m, safemodeafter_efuse, safemode_efuse)) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: efuse changed! Was %x, and is now %x\n",
progname, safemode_efuse, safemodeafter_efuse);
@ -1410,7 +1416,7 @@ int main(int argc, char * argv [])
avrdude_message(MSG_INFO, "%s: safemode: ", progname);
if (failures == 0) {
avrdude_message(MSG_INFO, "Fuses OK (E:%02X, H:%02X, L:%02X)\n",
safemode_efuse, safemode_hfuse, safemode_lfuse);
safemodeafter_efuse, safemodeafter_hfuse, safemodeafter_lfuse);
}
else {
avrdude_message(MSG_INFO, "Fuses not recovered, sorry\n");