This is Colin O'Flynn's mega patch for updating safemode support:
* add support for parts with just 'fuse' memory * if any fuse memories are altered, reflect those changes in the post-programming safemode check so that safemode no longer complains about fuses which were intentionally altered; this eliminates the need to completely disable safemode using -u in order to program fuses. * provide -s option which will not ask to restore fuses, it will just do it Submitted by: Colin O'Flynn <coflynn@newae.com> git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@519 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
3fd20e7edd
commit
c941cf8ab4
26
avr.c
26
avr.c
|
@ -33,6 +33,7 @@
|
||||||
#include "lists.h"
|
#include "lists.h"
|
||||||
#include "pindefs.h"
|
#include "pindefs.h"
|
||||||
#include "ppi.h"
|
#include "ppi.h"
|
||||||
|
#include "safemode.h"
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
|
|
||||||
|
@ -479,6 +480,30 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
unsigned long addr, unsigned char data)
|
unsigned long addr, unsigned char data)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
unsigned char safemode_lfuse;
|
||||||
|
unsigned char safemode_hfuse;
|
||||||
|
unsigned char safemode_efuse;
|
||||||
|
unsigned char safemode_fuse;
|
||||||
|
|
||||||
|
/* If we write the fuses, then we need to tell safemode that they *should* change */
|
||||||
|
safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
||||||
|
|
||||||
|
if (strcmp(mem->desc, "fuse")==0) {
|
||||||
|
safemode_fuse = data;
|
||||||
|
}
|
||||||
|
if (strcmp(mem->desc, "lfuse")==0) {
|
||||||
|
safemode_lfuse = data;
|
||||||
|
}
|
||||||
|
if (strcmp(mem->desc, "hfuse")==0) {
|
||||||
|
safemode_hfuse = data;
|
||||||
|
}
|
||||||
|
if (strcmp(mem->desc, "efuse")==0) {
|
||||||
|
safemode_efuse = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (pgm->write_byte) {
|
if (pgm->write_byte) {
|
||||||
|
@ -592,6 +617,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
||||||
pgm->err_led(pgm, ON);
|
pgm->err_led(pgm, ON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
194
main.c
194
main.c
|
@ -114,9 +114,9 @@ void usage(void)
|
||||||
" is performed in the order specified.\n"
|
" is performed in the order specified.\n"
|
||||||
" -n Do not write anything to the device.\n"
|
" -n Do not write anything to the device.\n"
|
||||||
" -V Do not verify.\n"
|
" -V Do not verify.\n"
|
||||||
" -u Disable safemode, you need this option if you\n"
|
" -u Disable safemode, default when running from a script.\n"
|
||||||
" want to change fuse bits. Otherwise they will be\n"
|
" -s Silent safemode operation, will not ask you if\n"
|
||||||
" recovered if they change\n"
|
" fuses should be changed back.\n"
|
||||||
" -t Enter terminal mode.\n"
|
" -t Enter terminal mode.\n"
|
||||||
" -E <exitspec>[,<exitspec>] List programmer exit specifications.\n"
|
" -E <exitspec>[,<exitspec>] List programmer exit specifications.\n"
|
||||||
" -y Count # erase cycles in EEPROM.\n"
|
" -y Count # erase cycles in EEPROM.\n"
|
||||||
|
@ -729,9 +729,13 @@ int main(int argc, char * argv [])
|
||||||
int baudrate; /* override default programmer baud rate */
|
int baudrate; /* override default programmer baud rate */
|
||||||
double bitclock; /* Specify programmer bit clock (JTAG ICE) */
|
double bitclock; /* Specify programmer bit clock (JTAG ICE) */
|
||||||
int safemode; /* Enable safemode, 1=safemode on, 0=normal */
|
int safemode; /* Enable safemode, 1=safemode on, 0=normal */
|
||||||
|
int silentsafe; /* Don't ask about fuses, 1=silent, 0=normal */
|
||||||
unsigned char safemode_lfuse = 0xff;
|
unsigned char safemode_lfuse = 0xff;
|
||||||
unsigned char safemode_hfuse = 0xff;
|
unsigned char safemode_hfuse = 0xff;
|
||||||
unsigned char safemode_efuse = 0xff;
|
unsigned char safemode_efuse = 0xff;
|
||||||
|
unsigned char safemode_fuse = 0xff;
|
||||||
|
|
||||||
|
char * safemode_response;
|
||||||
int fuses_specified = 0;
|
int fuses_specified = 0;
|
||||||
int fuses_updated = 0;
|
int fuses_updated = 0;
|
||||||
#if !defined(WIN32NATIVE)
|
#if !defined(WIN32NATIVE)
|
||||||
|
@ -781,7 +785,12 @@ int main(int argc, char * argv [])
|
||||||
set_cycles = -1;
|
set_cycles = -1;
|
||||||
baudrate = 0;
|
baudrate = 0;
|
||||||
bitclock = 0.0;
|
bitclock = 0.0;
|
||||||
safemode = 1; /* Safemode enabled by default */
|
safemode = 1; /* Safemode on by default */
|
||||||
|
silentsafe = 0; /* Ask by default */
|
||||||
|
|
||||||
|
if (isatty(STDIN_FILENO) == 0)
|
||||||
|
safemode = 0; /* Turn off safemode if this isn't a terminal */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(WIN32NATIVE)
|
#if defined(WIN32NATIVE)
|
||||||
|
@ -826,7 +835,7 @@ int main(int argc, char * argv [])
|
||||||
/*
|
/*
|
||||||
* process command line arguments
|
* process command line arguments
|
||||||
*/
|
*/
|
||||||
while ((ch = getopt(argc,argv,"?b:c:C:DeE:Fnp:P:qtU:uvVyY:")) != -1) {
|
while ((ch = getopt(argc,argv,"?b:c:C:DeE:Fnp:P:qtU:suvVyY:")) != -1) {
|
||||||
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'b': /* override default programmer baud rate */
|
case 'b': /* override default programmer baud rate */
|
||||||
|
@ -888,6 +897,11 @@ int main(int argc, char * argv [])
|
||||||
quell_progress++ ;
|
quell_progress++ ;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's' : /* Silent safemode */
|
||||||
|
silentsafe = 1;
|
||||||
|
safemode = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 't': /* enter terminal mode */
|
case 't': /* enter terminal mode */
|
||||||
terminal = 1;
|
terminal = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -1271,17 +1285,11 @@ int main(int argc, char * argv [])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (safemode == 1) {
|
if (safemode == 1) {
|
||||||
AVRMEM * m;
|
|
||||||
|
|
||||||
/* If safemode is enabled, go ahead and read the current low, high,
|
/* If safemode is enabled, go ahead and read the current low, high,
|
||||||
and extended fuse bytes as needed */
|
and extended fuse bytes as needed */
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (safemode_readfuses(&safemode_lfuse, &safemode_hfuse,
|
if (safemode_readfuses(&safemode_lfuse, &safemode_hfuse,
|
||||||
&safemode_efuse, pgm, p, verbose) != 0) {
|
&safemode_efuse, &safemode_fuse, pgm, p, verbose) != 0) {
|
||||||
fprintf(stderr, "%s: safemode: To protect your AVR the programming "
|
fprintf(stderr, "%s: safemode: To protect your AVR the programming "
|
||||||
"will be aborted\n",
|
"will be aborted\n",
|
||||||
progname);
|
progname);
|
||||||
|
@ -1289,36 +1297,8 @@ int main(int argc, char * argv [])
|
||||||
goto main_exit;
|
goto main_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Save the fuses as default
|
//Save the fuses as default
|
||||||
safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse);
|
safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
||||||
|
|
||||||
|
|
||||||
/* Check if user is attempting to write fuse bytes */
|
|
||||||
for (ln=lfirst(updates); ln; ln=lnext(ln)) {
|
|
||||||
upd = ldata(ln);
|
|
||||||
m = avr_locate_mem(p, upd->memtype);
|
|
||||||
if (m == NULL)
|
|
||||||
continue;
|
|
||||||
if (((strcasecmp(m->desc, "lfuse") == 0) ||
|
|
||||||
(strcasecmp(m->desc, "hfuse") == 0) ||
|
|
||||||
(strcasecmp(m->desc, "efuse") == 0)) && (upd->op == DEVICE_WRITE)) {
|
|
||||||
fuses_specified = 1;
|
|
||||||
fprintf(stderr,
|
|
||||||
"%s: NOTE: FUSE memory has been specified, and safemode is ON\n"
|
|
||||||
"%s: This will not allow you to change the fuse bits.\n"
|
|
||||||
"%s: To disable this feature, specify the -u option.\n",
|
|
||||||
progname, progname, progname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1403,13 +1383,6 @@ int main(int argc, char * argv [])
|
||||||
|
|
||||||
|
|
||||||
if (terminal) {
|
if (terminal) {
|
||||||
|
|
||||||
/* Warn user if safemode is on */
|
|
||||||
if (safemode > 0) {
|
|
||||||
fprintf(stderr, "%s: safemode is enabled, you will NOT be "
|
|
||||||
"able to change the fuse bits. Use -u option to disable\n",
|
|
||||||
progname);
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* terminal mode
|
* terminal mode
|
||||||
*/
|
*/
|
||||||
|
@ -1434,21 +1407,23 @@ int main(int argc, char * argv [])
|
||||||
unsigned char safemodeafter_lfuse = 0xff;
|
unsigned char safemodeafter_lfuse = 0xff;
|
||||||
unsigned char safemodeafter_hfuse = 0xff;
|
unsigned char safemodeafter_hfuse = 0xff;
|
||||||
unsigned char safemodeafter_efuse = 0xff;
|
unsigned char safemodeafter_efuse = 0xff;
|
||||||
|
unsigned char safemodeafter_fuse = 0xff;
|
||||||
unsigned char failures = 0;
|
unsigned char failures = 0;
|
||||||
|
char yes[1] = {'y'};
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
if (quell_progress < 2) {
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Restore the default fuse values
|
//Restore the default fuse values
|
||||||
safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse);
|
safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
||||||
|
|
||||||
/* Try reading back fuses, make sure they are reliable to read back */
|
/* Try reading back fuses, make sure they are reliable to read back */
|
||||||
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
|
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
|
||||||
&safemodeafter_efuse, pgm, p, verbose) != 0) {
|
&safemodeafter_efuse, &safemode_fuse, pgm, p, verbose) != 0) {
|
||||||
/* Uh-oh.. try once more to read back fuses */
|
/* Uh-oh.. try once more to read back fuses */
|
||||||
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
|
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
|
||||||
&safemodeafter_efuse, pgm, p, verbose) != 0) {
|
&safemodeafter_efuse, &safemodeafter_fuse, pgm, p, verbose) != 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: safemode: Sorry, reading back fuses was unreliable. "
|
"%s: safemode: Sorry, reading back fuses was unreliable. "
|
||||||
"I have given up and exited programming mode\n",
|
"I have given up and exited programming mode\n",
|
||||||
|
@ -1458,55 +1433,110 @@ int main(int argc, char * argv [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now check what fuses are against what they should be */
|
||||||
|
if (safemodeafter_fuse != safemode_fuse) {
|
||||||
|
fuses_updated = 1;
|
||||||
|
fprintf(stderr, "%s: safemode: fuse changed! Was %x, and is now %x\n",
|
||||||
|
progname, safemode_fuse, safemodeafter_fuse);
|
||||||
|
|
||||||
|
|
||||||
|
/* Ask user - should we change them */
|
||||||
|
|
||||||
|
if (silentsafe == 0)
|
||||||
|
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
|
||||||
|
else
|
||||||
|
safemode_response = yes;
|
||||||
|
|
||||||
|
if (tolower(safemode_response[0]) == 'y') {
|
||||||
|
|
||||||
|
/* Enough chit-chat, time to program some fuses and check them */
|
||||||
|
if (safemode_writefuse (safemode_fuse, "fuse", pgm, p,
|
||||||
|
10, verbose) == 0) {
|
||||||
|
fprintf(stderr, "%s: safemode: and is now rescued\n", progname);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "%s: and COULD NOT be changed\n", progname);
|
||||||
|
failures++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Now check what fuses are against what they should be */
|
/* Now check what fuses are against what they should be */
|
||||||
if (safemodeafter_lfuse != safemode_lfuse) {
|
if (safemodeafter_lfuse != safemode_lfuse) {
|
||||||
fuses_updated = 1;
|
fuses_updated = 1;
|
||||||
fprintf(stderr, "%s: safemode: lfuse changed! Read as %x, was %x\n",
|
fprintf(stderr, "%s: safemode: lfuse changed! Was %x, and is now %x\n",
|
||||||
progname, safemodeafter_lfuse, safemode_lfuse);
|
progname, safemode_lfuse, safemodeafter_lfuse);
|
||||||
|
|
||||||
/* Enough chit-chat, time to program some fuses and check them */
|
|
||||||
if (safemode_writefuse (safemode_lfuse, "lfuse", pgm, p,
|
/* Ask user - should we change them */
|
||||||
10, verbose) == 0) {
|
|
||||||
fprintf(stderr, "%s: safemode: and is now rescued\n", progname);
|
if (silentsafe == 0)
|
||||||
}
|
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
|
||||||
else {
|
else
|
||||||
fprintf(stderr, "%s: and COULD NOT be changed\n", progname);
|
safemode_response = yes;
|
||||||
failures++;
|
|
||||||
|
if (tolower(safemode_response[0]) == 'y') {
|
||||||
|
|
||||||
|
/* Enough chit-chat, time to program some fuses and check them */
|
||||||
|
if (safemode_writefuse (safemode_lfuse, "lfuse", pgm, p,
|
||||||
|
10, verbose) == 0) {
|
||||||
|
fprintf(stderr, "%s: safemode: and is now rescued\n", progname);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "%s: and COULD NOT be changed\n", progname);
|
||||||
|
failures++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now check what fuses are against what they should be */
|
/* Now check what fuses are against what they should be */
|
||||||
if (safemodeafter_hfuse != safemode_hfuse) {
|
if (safemodeafter_hfuse != safemode_hfuse) {
|
||||||
fuses_updated = 1;
|
fuses_updated = 1;
|
||||||
fprintf(stderr, "%s: safemode: hfuse changed! Read as %x, was %x\n",
|
fprintf(stderr, "%s: safemode: hfuse changed! Was %x, and is now %x\n",
|
||||||
progname, safemodeafter_hfuse, safemode_hfuse);
|
progname, safemode_hfuse, safemodeafter_hfuse);
|
||||||
|
|
||||||
/* Enough chit-chat, time to program some fuses and check them */
|
/* Ask user - should we change them */
|
||||||
if (safemode_writefuse(safemode_hfuse, "hfuse", pgm, p,
|
if (silentsafe == 0)
|
||||||
10, verbose) == 0) {
|
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
|
||||||
fprintf(stderr, "%s: safemode: and is now rescued\n", progname);
|
else
|
||||||
}
|
safemode_response = yes;
|
||||||
else {
|
if (tolower(safemode_response[0]) == 'y') {
|
||||||
fprintf(stderr, "%s: and COULD NOT be changed\n", progname);
|
|
||||||
failures++;
|
/* Enough chit-chat, time to program some fuses and check them */
|
||||||
|
if (safemode_writefuse(safemode_hfuse, "hfuse", pgm, p,
|
||||||
|
10, verbose) == 0) {
|
||||||
|
fprintf(stderr, "%s: safemode: and is now rescued\n", progname);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "%s: and COULD NOT be changed\n", progname);
|
||||||
|
failures++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now check what fuses are against what they should be */
|
/* Now check what fuses are against what they should be */
|
||||||
if (safemodeafter_efuse != safemode_efuse) {
|
if (safemodeafter_efuse != safemode_efuse) {
|
||||||
fuses_updated = 1;
|
fuses_updated = 1;
|
||||||
fprintf(stderr, "%s: safemode: efuse changed! Read as %x, was %x\n",
|
fprintf(stderr, "%s: safemode: efuse changed! Was %x, and is now %x\n",
|
||||||
progname, safemodeafter_efuse, safemode_efuse);
|
progname, safemode_efuse, safemodeafter_efuse);
|
||||||
|
|
||||||
/* Enough chit-chat, time to program some fuses and check them */
|
/* Ask user - should we change them */
|
||||||
if (safemode_writefuse (safemode_efuse, "efuse", pgm, p,
|
if (silentsafe == 0)
|
||||||
10, verbose) == 0) {
|
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
|
||||||
fprintf(stderr, "%s: safemode: and is now rescued\n", progname);
|
else
|
||||||
}
|
safemode_response = yes;
|
||||||
else {
|
if (tolower(safemode_response[0]) == 'y') {
|
||||||
fprintf(stderr, "%s: and COULD NOT be changed\n", progname);
|
|
||||||
failures++;
|
/* Enough chit-chat, time to program some fuses and check them */
|
||||||
}
|
if (safemode_writefuse (safemode_efuse, "efuse", pgm, p,
|
||||||
|
10, verbose) == 0) {
|
||||||
|
fprintf(stderr, "%s: safemode: and is now rescued\n", progname);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "%s: and COULD NOT be changed\n", progname);
|
||||||
|
failures++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
if (quell_progress < 2) {
|
||||||
|
|
74
safemode.c
74
safemode.c
|
@ -30,9 +30,13 @@
|
||||||
/* This value from ac_cfg.h */
|
/* This value from ac_cfg.h */
|
||||||
char * progname = PACKAGE_NAME;
|
char * progname = PACKAGE_NAME;
|
||||||
|
|
||||||
/* Writes the specified fuse in fusename (can be "lfuse", "hfuse", or "efuse") and verifies it. Will try up to tries
|
/*
|
||||||
amount of times before giving up */
|
* Writes the specified fuse in fusename (can be "lfuse", "hfuse", or
|
||||||
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries, int verbose)
|
* "efuse") and verifies it. Will try up to tries amount of times
|
||||||
|
* before giving up
|
||||||
|
*/
|
||||||
|
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm,
|
||||||
|
AVRPART * p, int tries, int verbose)
|
||||||
{
|
{
|
||||||
AVRMEM * m;
|
AVRMEM * m;
|
||||||
unsigned char fuseread;
|
unsigned char fuseread;
|
||||||
|
@ -50,8 +54,9 @@ int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, A
|
||||||
|
|
||||||
/* Report information to user if needed */
|
/* Report information to user if needed */
|
||||||
if (verbose > 0) {
|
if (verbose > 0) {
|
||||||
fprintf(stderr, "%s: safemode: Wrote %s to %x, read as %x. %d attempts left\n",
|
fprintf(stderr,
|
||||||
progname, fusename, fuse, fuseread, tries-1);
|
"%s: safemode: Wrote %s to %x, read as %x. %d attempts left\n",
|
||||||
|
progname, fusename, fuse, fuseread, tries-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If fuse wrote OK, no need to keep going */
|
/* If fuse wrote OK, no need to keep going */
|
||||||
|
@ -65,8 +70,13 @@ int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, A
|
||||||
return returnvalue;
|
return returnvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reads the fuses three times, checking that all readings are the same. This will ensure that the before values aren't in error! */
|
/*
|
||||||
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, PROGRAMMER * pgm, AVRPART * p, int verbose)
|
* Reads the fuses three times, checking that all readings are the
|
||||||
|
* same. This will ensure that the before values aren't in error!
|
||||||
|
*/
|
||||||
|
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse,
|
||||||
|
unsigned char * efuse, unsigned char * fuse,
|
||||||
|
PROGRAMMER * pgm, AVRPART * p, int verbose)
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned char value;
|
unsigned char value;
|
||||||
|
@ -74,11 +84,41 @@ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned c
|
||||||
unsigned char safemode_lfuse;
|
unsigned char safemode_lfuse;
|
||||||
unsigned char safemode_hfuse;
|
unsigned char safemode_hfuse;
|
||||||
unsigned char safemode_efuse;
|
unsigned char safemode_efuse;
|
||||||
|
unsigned char safemode_fuse;
|
||||||
AVRMEM * m;
|
AVRMEM * m;
|
||||||
|
|
||||||
safemode_lfuse = *lfuse;
|
safemode_lfuse = *lfuse;
|
||||||
safemode_hfuse = *hfuse;
|
safemode_hfuse = *hfuse;
|
||||||
safemode_efuse = *efuse;
|
safemode_efuse = *efuse;
|
||||||
|
safemode_fuse = *fuse;
|
||||||
|
|
||||||
|
|
||||||
|
/* Read fuse three times */
|
||||||
|
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
||||||
|
to generate a verify error */
|
||||||
|
m = avr_locate_mem(p, "fuse");
|
||||||
|
if (m != NULL) {
|
||||||
|
fusegood = 0; /* By default fuse is a failure */
|
||||||
|
avr_read_byte(pgm, p, m, 0, &safemode_fuse);
|
||||||
|
avr_read_byte(pgm, p, m, 0, &value);
|
||||||
|
if (value == safemode_fuse) {
|
||||||
|
avr_read_byte(pgm, p, m, 0, &value);
|
||||||
|
if (value == safemode_fuse){
|
||||||
|
fusegood = 1; /* Fuse read OK three times */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fusegood == 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: safemode: Verify error - unable to read fuse properly. "
|
||||||
|
"Programmer may not be reliable.\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if ((fusegood == 1) && (verbose > 0)) {
|
||||||
|
printf("%s: safemode: fuse reads as %X\n", progname, safemode_fuse);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Read lfuse three times */
|
/* Read lfuse three times */
|
||||||
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
||||||
|
@ -161,20 +201,28 @@ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned c
|
||||||
*lfuse = safemode_lfuse;
|
*lfuse = safemode_lfuse;
|
||||||
*hfuse = safemode_hfuse;
|
*hfuse = safemode_hfuse;
|
||||||
*efuse = safemode_efuse;
|
*efuse = safemode_efuse;
|
||||||
|
*fuse = safemode_fuse;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This routine will store the current values pointed to by lfuse, hfuse, and efuse into an internal buffer in this routine
|
/*
|
||||||
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
|
* This routine will store the current values pointed to by lfuse,
|
||||||
pointed to be lfuse, hfuse, and efuse. This allows you to change the fuse bits if needed from another routine (ie: have it so
|
* hfuse, and efuse into an internal buffer in this routine when save
|
||||||
if user requests fuse bits are changed, the requested value is now verified */
|
* is set to 1. When save is 0 (or not 1 really) it will copy the
|
||||||
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse)
|
* values from the internal buffer into the locations pointed to be
|
||||||
|
* lfuse, hfuse, and efuse. This allows you to change the fuse bits if
|
||||||
|
* needed from another routine (ie: have it so if user requests fuse
|
||||||
|
* bits are changed, the requested value is now verified
|
||||||
|
*/
|
||||||
|
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse,
|
||||||
|
unsigned char * efuse, unsigned char * fuse)
|
||||||
{
|
{
|
||||||
static unsigned char safemode_lfuse = 0xff;
|
static unsigned char safemode_lfuse = 0xff;
|
||||||
static unsigned char safemode_hfuse = 0xff;
|
static unsigned char safemode_hfuse = 0xff;
|
||||||
static unsigned char safemode_efuse = 0xff;
|
static unsigned char safemode_efuse = 0xff;
|
||||||
|
static unsigned char safemode_fuse = 0xff;
|
||||||
|
|
||||||
switch (save) {
|
switch (save) {
|
||||||
|
|
||||||
|
@ -183,6 +231,7 @@ int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, u
|
||||||
safemode_lfuse = *lfuse;
|
safemode_lfuse = *lfuse;
|
||||||
safemode_hfuse = *hfuse;
|
safemode_hfuse = *hfuse;
|
||||||
safemode_efuse = *efuse;
|
safemode_efuse = *efuse;
|
||||||
|
safemode_fuse = *fuse;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
/* Read back the fuses */
|
/* Read back the fuses */
|
||||||
|
@ -190,6 +239,7 @@ int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, u
|
||||||
*lfuse = safemode_lfuse;
|
*lfuse = safemode_lfuse;
|
||||||
*hfuse = safemode_hfuse;
|
*hfuse = safemode_hfuse;
|
||||||
*efuse = safemode_efuse;
|
*efuse = safemode_efuse;
|
||||||
|
*fuse = safemode_fuse;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,12 @@ amount of times before giving up */
|
||||||
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries, int verbose);
|
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries, int verbose);
|
||||||
|
|
||||||
/* Reads the fuses three times, checking that all readings are the same. This will ensure that the before values aren't in error! */
|
/* Reads the fuses three times, checking that all readings are the same. This will ensure that the before values aren't in error! */
|
||||||
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, PROGRAMMER * pgm, AVRPART * p, int verbose);
|
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse, PROGRAMMER * pgm, AVRPART * p, int verbose);
|
||||||
|
|
||||||
/* This routine will store the current values pointed to by lfuse, hfuse, and efuse into an internal buffer in this routine
|
/* This routine will store the current values pointed to by lfuse, hfuse, and efuse into an internal buffer in this routine
|
||||||
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
|
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
|
||||||
pointed to be lfuse, hfuse, and efuse. This allows you to change the fuse bits if needed from another routine (ie: have it so
|
pointed to be lfuse, hfuse, and efuse. This allows you to change the fuse bits if needed from another routine (ie: have it so
|
||||||
if user requests fuse bits are changed, the requested value is now verified */
|
if user requests fuse bits are changed, the requested value is now verified */
|
||||||
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse);
|
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse);
|
||||||
|
|
||||||
#endif //__safemode_h
|
#endif //__safemode_h
|
||||||
|
|
Loading…
Reference in New Issue