|
| 1 | +--- avr.c |
| 2 | ++++ avr.c |
| 3 | +@@ -1058,6 +1058,33 @@ int avr_signature(PROGRAMMER * pgm, AVRPART * p) |
| 4 | + return 0; |
| 5 | + } |
| 6 | + |
| 7 | ++uint8_t get_fuse_bitmask(AVRMEM * m) { |
| 8 | ++ uint8_t bitmask_r = 0; |
| 9 | ++ uint8_t bitmask_w = 0; |
| 10 | ++ int i, j; |
| 11 | ++ for (i=0; i<AVR_OP_MAX; i++) { |
| 12 | ++ if (m->op[i] && strcmp(avr_op_str(i),"READ") == 0) { |
| 13 | ++ for (j=7; j>=0; j--) { |
| 14 | ++ bitmask_r |= (strcmp(bittype(m->op[i]->bit[j].type), "IGNORE") != 0) << j; |
| 15 | ++ } |
| 16 | ++ } |
| 17 | ++ if (m->op[i] && strcmp(avr_op_str(i),"WRITE") == 0) { |
| 18 | ++ for (j=7; j>=0; j--) { |
| 19 | ++ bitmask_w |= (strcmp(bittype(m->op[i]->bit[j].type), "VALUE") != 0 && |
| 20 | ++ strcmp(bittype(m->op[i]->bit[j].type), "IGNORE") != 0) << j; |
| 21 | ++ } |
| 22 | ++ } |
| 23 | ++ } |
| 24 | ++ return bitmask_r & bitmask_w; |
| 25 | ++} |
| 26 | ++ |
| 27 | ++int skip_fuse_memory_masked(AVRMEM * m, unsigned char buf1, unsigned char buf2) { |
| 28 | ++ if (m->size > 1) { |
| 29 | ++ return 1; |
| 30 | ++ } |
| 31 | ++ uint8_t bitmask = get_fuse_bitmask(m); |
| 32 | ++ return ((buf1 & bitmask) != (buf2 & bitmask)); |
| 33 | ++} |
| 34 | + |
| 35 | + /* |
| 36 | + * Verify the memory buffer of p with that of v. The byte range of v, |
| 37 | +@@ -1103,7 +1130,7 @@ int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size) |
| 38 | + |
| 39 | + for (i=0; i<size; i++) { |
| 40 | + if ((b->tags[i] & TAG_ALLOCATED) != 0 && |
| 41 | +- buf1[i] != buf2[i]) { |
| 42 | ++ (buf1[i] != buf2[i]) && (skip_fuse_memory_masked(a , buf1[i], buf2[i]))) { |
| 43 | + avrdude_message(MSG_INFO, "%s: verification error, first mismatch at byte 0x%04x\n" |
| 44 | + "%s0x%02x != 0x%02x\n", |
| 45 | + progname, i, |
| 46 | +--- avrpart.c |
| 47 | ++++ avrpart.c |
| 48 | +@@ -205,7 +205,7 @@ int avr_get_output_index(OPCODE * op) |
| 49 | + } |
| 50 | + |
| 51 | + |
| 52 | +-static char * avr_op_str(int op) |
| 53 | ++char * avr_op_str(int op) |
| 54 | + { |
| 55 | + switch (op) { |
| 56 | + case AVR_OP_READ : return "READ"; break; |
| 57 | +@@ -225,7 +225,7 @@ static char * avr_op_str(int op) |
| 58 | + } |
| 59 | + |
| 60 | + |
| 61 | +-static char * bittype(int type) |
| 62 | ++char * bittype(int type) |
| 63 | + { |
| 64 | + switch (type) { |
| 65 | + case AVR_CMDBIT_IGNORE : return "IGNORE"; break; |
| 66 | +@@ -405,7 +405,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type, |
| 67 | + m->readback[1]); |
| 68 | + if (verbose > 4) { |
| 69 | + avrdude_message(MSG_TRACE2, "%s Memory Ops:\n" |
| 70 | +- "%s Oeration Inst Bit Bit Type Bitno Value\n" |
| 71 | ++ "%s Operation Inst Bit Bit Type Bitno Value\n" |
| 72 | + "%s ----------- -------- -------- ----- -----\n", |
| 73 | + prefix, prefix, prefix); |
| 74 | + for (i=0; i<AVR_OP_MAX; i++) { |
| 75 | +--- libavrdude.h |
| 76 | ++++ libavrdude.h |
| 77 | +@@ -297,6 +297,7 @@ typedef struct avrmem { |
| 78 | + |
| 79 | + unsigned char * buf; /* pointer to memory buffer */ |
| 80 | + unsigned char * tags; /* allocation tags */ |
| 81 | ++ unsigned char * mask; /* mask tags */ |
| 82 | + OPCODE * op[AVR_OP_MAX]; /* opcodes */ |
| 83 | + } AVRMEM; |
| 84 | + |
| 85 | +@@ -337,6 +338,12 @@ typedef void (*walk_avrparts_cb)(const char *name, const char *desc, |
| 86 | + void *cookie); |
| 87 | + void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie); |
| 88 | + void sort_avrparts(LISTID avrparts); |
| 89 | ++ |
| 90 | ++ |
| 91 | ++char * avr_op_str(int op); |
| 92 | ++char * bittype(int type); |
| 93 | ++uint8_t get_fuse_bitmask(AVRMEM * m); |
| 94 | ++ |
| 95 | + #ifdef __cplusplus |
| 96 | + } |
| 97 | + #endif |
| 98 | +@@ -818,7 +825,7 @@ amount of times before giving up */ |
| 99 | + int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries); |
| 100 | + |
| 101 | + /* Reads the fuses three times, checking that all readings are the same. This will ensure that the before values aren't in error! */ |
| 102 | +-int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse, PROGRAMMER * pgm, AVRPART * p); |
| 103 | ++int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse, unsigned char * efuse_mask, PROGRAMMER * pgm, AVRPART * p); |
| 104 | + |
| 105 | + /* This routine will store the current values pointed to by lfuse, hfuse, and efuse into an internal buffer in this routine |
| 106 | + when save is set to 1. When save is 0 (or not 1 really) it will copy the values from the internal buffer into the locations |
| 107 | +--- main.c |
| 108 | ++++ main.c |
| 109 | +@@ -344,6 +344,7 @@ int main(int argc, char * argv []) |
| 110 | + unsigned char safemode_lfuse = 0xff; |
| 111 | + unsigned char safemode_hfuse = 0xff; |
| 112 | + unsigned char safemode_efuse = 0xff; |
| 113 | ++ unsigned char safemode_efuse_mask = 0xff; |
| 114 | + unsigned char safemode_fuse = 0xff; |
| 115 | + |
| 116 | + char * safemode_response; |
| 117 | +@@ -1131,7 +1132,7 @@ int main(int argc, char * argv []) |
| 118 | + and extended fuse bytes as needed */ |
| 119 | + |
| 120 | + rc = safemode_readfuses(&safemode_lfuse, &safemode_hfuse, |
| 121 | +- &safemode_efuse, &safemode_fuse, pgm, p); |
| 122 | ++ &safemode_efuse, &safemode_fuse, &safemode_efuse_mask, pgm, p); |
| 123 | + |
| 124 | + if (rc != 0) { |
| 125 | + |
| 126 | +@@ -1239,6 +1240,7 @@ int main(int argc, char * argv []) |
| 127 | + unsigned char safemodeafter_lfuse = 0xff; |
| 128 | + unsigned char safemodeafter_hfuse = 0xff; |
| 129 | + unsigned char safemodeafter_efuse = 0xff; |
| 130 | ++ unsigned char safemodeafter_efuse_mask = 0xff; |
| 131 | + unsigned char safemodeafter_fuse = 0xff; |
| 132 | + unsigned char failures = 0; |
| 133 | + char yes[1] = {'y'}; |
| 134 | +@@ -1252,16 +1254,15 @@ int main(int argc, char * argv []) |
| 135 | + |
| 136 | + /* Try reading back fuses, make sure they are reliable to read back */ |
| 137 | + if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse, |
| 138 | +- &safemodeafter_efuse, &safemodeafter_fuse, pgm, p) != 0) { |
| 139 | ++ &safemodeafter_efuse, &safemodeafter_fuse, &safemodeafter_efuse_mask, pgm, p) != 0) { |
| 140 | + /* Uh-oh.. try once more to read back fuses */ |
| 141 | + if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse, |
| 142 | +- &safemodeafter_efuse, &safemodeafter_fuse, pgm, p) != 0) { |
| 143 | ++ &safemodeafter_efuse, &safemodeafter_fuse, &safemodeafter_efuse_mask, pgm, p) != 0) { |
| 144 | + avrdude_message(MSG_INFO, "%s: safemode: Sorry, reading back fuses was unreliable. " |
| 145 | + "I have given up and exited programming mode\n", |
| 146 | + progname); |
| 147 | + exitrc = 1; |
| 148 | +- goto main_exit; |
| 149 | +- } |
| 150 | ++ goto main_exit; } |
| 151 | + } |
| 152 | + |
| 153 | + /* Now check what fuses are against what they should be */ |
| 154 | +@@ -1346,7 +1347,7 @@ int main(int argc, char * argv []) |
| 155 | + } |
| 156 | + |
| 157 | + /* Now check what fuses are against what they should be */ |
| 158 | +- if (safemodeafter_efuse != safemode_efuse) { |
| 159 | ++ if ((safemodeafter_efuse & safemodeafter_efuse_mask) != (safemode_efuse & safemodeafter_efuse_mask)) { |
| 160 | + fuses_updated = 1; |
| 161 | + avrdude_message(MSG_INFO, "%s: safemode: efuse changed! Was %x, and is now %x\n", |
| 162 | + progname, safemode_efuse, safemodeafter_efuse); |
| 163 | +--- safemode.c |
| 164 | ++++ safemode.c |
| 165 | +@@ -75,7 +75,7 @@ int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, |
| 166 | + * same. This will ensure that the before values aren't in error! |
| 167 | + */ |
| 168 | + int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, |
| 169 | +- unsigned char * efuse, unsigned char * fuse, |
| 170 | ++ unsigned char * efuse, unsigned char * fuse, unsigned char * efuse_mask, |
| 171 | + PROGRAMMER * pgm, AVRPART * p) |
| 172 | + { |
| 173 | + |
| 174 | +@@ -85,12 +85,14 @@ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, |
| 175 | + unsigned char safemode_lfuse; |
| 176 | + unsigned char safemode_hfuse; |
| 177 | + unsigned char safemode_efuse; |
| 178 | ++ unsigned char safemode_efuse_mask; |
| 179 | + unsigned char safemode_fuse; |
| 180 | + AVRMEM * m; |
| 181 | + |
| 182 | + safemode_lfuse = *lfuse; |
| 183 | + safemode_hfuse = *hfuse; |
| 184 | + safemode_efuse = *efuse; |
| 185 | ++ safemode_efuse_mask = *efuse_mask; |
| 186 | + safemode_fuse = *fuse; |
| 187 | + |
| 188 | + |
| 189 | +@@ -229,8 +231,10 @@ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, |
| 190 | + /* Read efuse three times */ |
| 191 | + fusegood = 2; /* If AVR device doesn't support this fuse, don't want |
| 192 | + to generate a verify error */ |
| 193 | ++ |
| 194 | + m = avr_locate_mem(p, "efuse"); |
| 195 | + if (m != NULL) { |
| 196 | ++ safemode_efuse_mask = get_fuse_bitmask(m); |
| 197 | + fusegood = 0; /* By default fuse is a failure */ |
| 198 | + if (pgm->read_byte(pgm, p, m, 0, &safemode_efuse) != 0) |
| 199 | + { |
| 200 | +@@ -272,6 +276,7 @@ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, |
| 201 | + *lfuse = safemode_lfuse; |
| 202 | + *hfuse = safemode_hfuse; |
| 203 | + *efuse = safemode_efuse; |
| 204 | ++ *efuse_mask = safemode_efuse_mask; |
| 205 | + *fuse = safemode_fuse; |
| 206 | + |
| 207 | + return 0; |
0 commit comments