Remove the "safemode" feature.
This feature has been designed with the sometimes quite flakey direct (parallel or serial port attached) bitbang programming adapters in mind that were quite common about two decades ago. With parallel ports vanishing from modern PCs almost completely, and the advent of various USB-attached low-cost programming devices, this class of programmers disappeared almost completely. Furthermore, the fuse combinations that were covered by the feature are no longer around on all recent AVR devices, so for an ever increasing number of devices, safemode already became meaningless and was turned off anyway. With the prospective version 7.x release, it's a good point in time to introduce a major change like this one.
This commit is contained in:
parent
e28e28d7c3
commit
8c6c6a14ec
5
NEWS
5
NEWS
|
@ -13,6 +13,11 @@ Changes since version 6.4:
|
||||||
- Started to add CMake (by now, parallel with autoconf/automake)
|
- Started to add CMake (by now, parallel with autoconf/automake)
|
||||||
- New-architecture devices (AVR8X mega and tiny) can access all
|
- New-architecture devices (AVR8X mega and tiny) can access all
|
||||||
fuses, and memory display shows meaningful alias names
|
fuses, and memory display shows meaningful alias names
|
||||||
|
- The "safemode" feature has been removed. The major class of
|
||||||
|
programmers it has been designed for (lowlevel bitbang
|
||||||
|
programmers on parallel or serial ports) virtually doesn't exist
|
||||||
|
anymore, and the fuse combination that was covered by it do not
|
||||||
|
match the fuses of modern AVR devices anyway.
|
||||||
|
|
||||||
* New devices supported:
|
* New devices supported:
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,6 @@ add_library(libavrdude
|
||||||
ppi.c
|
ppi.c
|
||||||
ppi.h
|
ppi.h
|
||||||
ppiwin.c
|
ppiwin.c
|
||||||
safemode.c
|
|
||||||
serbb.h
|
serbb.h
|
||||||
serbb_posix.c
|
serbb_posix.c
|
||||||
serbb_win32.c
|
serbb_win32.c
|
||||||
|
|
|
@ -148,7 +148,6 @@ libavrdude_a_SOURCES = \
|
||||||
ppi.c \
|
ppi.c \
|
||||||
ppi.h \
|
ppi.h \
|
||||||
ppiwin.c \
|
ppiwin.c \
|
||||||
safemode.c \
|
|
||||||
serbb.h \
|
serbb.h \
|
||||||
serbb_posix.c \
|
serbb_posix.c \
|
||||||
serbb_win32.c \
|
serbb_win32.c \
|
||||||
|
|
24
src/avr.c
24
src/avr.c
|
@ -791,30 +791,6 @@ 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);
|
|
||||||
|
|
||||||
return pgm->write_byte(pgm, p, mem, addr, data);
|
return pgm->write_byte(pgm, p, mem, addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -607,40 +607,11 @@ Posix systems (by now).
|
||||||
.It Fl q
|
.It Fl q
|
||||||
Disable (or quell) output of the progress bar while reading or writing
|
Disable (or quell) output of the progress bar while reading or writing
|
||||||
to the device. Specify it a second time for even quieter operation.
|
to the device. Specify it a second time for even quieter operation.
|
||||||
.It Fl s
|
|
||||||
Disable safemode prompting. When safemode discovers that one or more
|
|
||||||
fuse bits have unintentionally changed, it will prompt for
|
|
||||||
confirmation regarding whether or not it should attempt to recover the
|
|
||||||
fuse bit(s). Specifying this flag disables the prompt and assumes
|
|
||||||
that the fuse bit(s) should be recovered without asking for
|
|
||||||
confirmation first.
|
|
||||||
.It Fl t
|
.It Fl t
|
||||||
Tells
|
Tells
|
||||||
.Nm
|
.Nm
|
||||||
to enter the interactive ``terminal'' mode instead of up- or downloading
|
to enter the interactive ``terminal'' mode instead of up- or downloading
|
||||||
files. See below for a detailed description of the terminal mode.
|
files. See below for a detailed description of the terminal mode.
|
||||||
.It Fl u
|
|
||||||
Disable the safemode fuse bit checks. Safemode is enabled by default
|
|
||||||
and is intended to prevent unintentional fuse bit changes. When
|
|
||||||
enabled, safemode will issue a warning if the any fuse bits are found
|
|
||||||
to be different at program exit than they were when
|
|
||||||
.Nm
|
|
||||||
was invoked. Safemode won't alter fuse bits itself, but rather will
|
|
||||||
prompt for instructions, unless the terminal is non-interactive, in
|
|
||||||
which case safemode is disabled. See the
|
|
||||||
.Fl s
|
|
||||||
option to disable safemode prompting.
|
|
||||||
.Pp
|
|
||||||
If one of the configuration files has a line
|
|
||||||
.Dl "default_safemode = no;"
|
|
||||||
safemode is disabled by default.
|
|
||||||
The
|
|
||||||
.Fl u
|
|
||||||
option's effect is negated in that case, i. e. it
|
|
||||||
.Em enables
|
|
||||||
safemode.
|
|
||||||
.Pp
|
|
||||||
Safemode is always disabled for AVR32, Xmega and TPI devices.
|
|
||||||
.It Xo Fl U Ar memtype Ns
|
.It Xo Fl U Ar memtype Ns
|
||||||
.Ar \&: Ns Ar op Ns
|
.Ar \&: Ns Ar op Ns
|
||||||
.Ar \&: Ns Ar filename Ns
|
.Ar \&: Ns Ar filename Ns
|
||||||
|
|
|
@ -339,10 +339,6 @@ default_parallel = "@DEFAULT_PAR_PORT@";
|
||||||
default_serial = "@DEFAULT_SER_PORT@";
|
default_serial = "@DEFAULT_SER_PORT@";
|
||||||
# default_bitclock = 2.5;
|
# default_bitclock = 2.5;
|
||||||
|
|
||||||
# Turn off safemode by default
|
|
||||||
#default_safemode = no;
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# PROGRAMMER DEFINITIONS
|
# PROGRAMMER DEFINITIONS
|
||||||
#
|
#
|
||||||
|
|
|
@ -36,7 +36,6 @@ char default_programmer[MAX_STR_CONST];
|
||||||
char default_parallel[PATH_MAX];
|
char default_parallel[PATH_MAX];
|
||||||
char default_serial[PATH_MAX];
|
char default_serial[PATH_MAX];
|
||||||
double default_bitclock;
|
double default_bitclock;
|
||||||
int default_safemode;
|
|
||||||
|
|
||||||
char string_buf[MAX_STR_CONST];
|
char string_buf[MAX_STR_CONST];
|
||||||
char *string_buf_ptr;
|
char *string_buf_ptr;
|
||||||
|
|
|
@ -77,7 +77,6 @@ static int pin_name;
|
||||||
%token K_DEFAULT_BITCLOCK
|
%token K_DEFAULT_BITCLOCK
|
||||||
%token K_DEFAULT_PARALLEL
|
%token K_DEFAULT_PARALLEL
|
||||||
%token K_DEFAULT_PROGRAMMER
|
%token K_DEFAULT_PROGRAMMER
|
||||||
%token K_DEFAULT_SAFEMODE
|
|
||||||
%token K_DEFAULT_SERIAL
|
%token K_DEFAULT_SERIAL
|
||||||
%token K_DESC
|
%token K_DESC
|
||||||
%token K_FAMILY_ID
|
%token K_FAMILY_ID
|
||||||
|
@ -257,14 +256,6 @@ def :
|
||||||
K_DEFAULT_BITCLOCK TKN_EQUAL number_real TKN_SEMI {
|
K_DEFAULT_BITCLOCK TKN_EQUAL number_real TKN_SEMI {
|
||||||
default_bitclock = $3->value.number_real;
|
default_bitclock = $3->value.number_real;
|
||||||
free_token($3);
|
free_token($3);
|
||||||
} |
|
|
||||||
|
|
||||||
K_DEFAULT_SAFEMODE TKN_EQUAL yesno TKN_SEMI {
|
|
||||||
if ($3->primary == K_YES)
|
|
||||||
default_safemode = 1;
|
|
||||||
else if ($3->primary == K_NO)
|
|
||||||
default_safemode = 0;
|
|
||||||
free_token($3);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -681,32 +681,6 @@ Posix systems (by now).
|
||||||
Disable (or quell) output of the progress bar while reading or writing
|
Disable (or quell) output of the progress bar while reading or writing
|
||||||
to the device. Specify it a second time for even quieter operation.
|
to the device. Specify it a second time for even quieter operation.
|
||||||
|
|
||||||
@item -u
|
|
||||||
Disables the default behaviour of reading out the fuses three times before
|
|
||||||
programming, then verifying at the end of programming that the fuses have not
|
|
||||||
changed. If you want to change fuses you will need to specify this option,
|
|
||||||
as avrdude will see the fuses have changed (even though you wanted to) and
|
|
||||||
will change them back for your "safety". This option was designed to
|
|
||||||
prevent cases of fuse bits magically changing (usually called @emph{safemode}).
|
|
||||||
|
|
||||||
If one of the configuration files contains a line
|
|
||||||
|
|
||||||
@code{default_safemode = no;}
|
|
||||||
|
|
||||||
safemode is disabled by default.
|
|
||||||
The @option{-u} option's effect is negated in that case, i. e. it
|
|
||||||
@emph{enables} safemode.
|
|
||||||
|
|
||||||
Safemode is always disabled for AVR32, Xmega and TPI devices.
|
|
||||||
|
|
||||||
@item -s
|
|
||||||
Disable safemode prompting. When safemode discovers that one or more
|
|
||||||
fuse bits have unintentionally changed, it will prompt for
|
|
||||||
confirmation regarding whether or not it should attempt to recover the
|
|
||||||
fuse bit(s). Specifying this flag disables the prompt and assumes
|
|
||||||
that the fuse bit(s) should be recovered without asking for
|
|
||||||
confirmation first.
|
|
||||||
|
|
||||||
@item -t
|
@item -t
|
||||||
Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up-
|
Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up-
|
||||||
or downloading files. See below for a detailed description of the
|
or downloading files. See below for a detailed description of the
|
||||||
|
@ -1133,8 +1107,6 @@ Reading | ################################################## | 100% 6.83s
|
||||||
avrdude: verifying ...
|
avrdude: verifying ...
|
||||||
avrdude: 19278 bytes of flash verified
|
avrdude: 19278 bytes of flash verified
|
||||||
|
|
||||||
avrdude: safemode: Fuses OK
|
|
||||||
|
|
||||||
avrdude done. Thank you.
|
avrdude done. Thank you.
|
||||||
|
|
||||||
%
|
%
|
||||||
|
@ -1162,8 +1134,6 @@ Reading | ################################################## | 100% 46.10s
|
||||||
|
|
||||||
avrdude: writing output file "c:/diag flash.bin"
|
avrdude: writing output file "c:/diag flash.bin"
|
||||||
|
|
||||||
avrdude: safemode: Fuses OK
|
|
||||||
|
|
||||||
avrdude done. Thank you.
|
avrdude done. Thank you.
|
||||||
|
|
||||||
%
|
%
|
||||||
|
@ -1845,9 +1815,6 @@ flash pages of the application section.
|
||||||
|
|
||||||
Reading fuse and lock bits is fully supported.
|
Reading fuse and lock bits is fully supported.
|
||||||
|
|
||||||
Note that due to the inability to write the fuse bits, the safemode
|
|
||||||
functionality does not make sense for these boot loaders.
|
|
||||||
|
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@c
|
@c
|
||||||
|
@ -2021,9 +1988,6 @@ fuse, extended fuse) have no meaning whatsoever, as they have been
|
||||||
simply replaced by array of fuses: fuse0..9. Therefore you can simply
|
simply replaced by array of fuses: fuse0..9. Therefore you can simply
|
||||||
ignore this particular line of AVRDUDE output.
|
ignore this particular line of AVRDUDE output.
|
||||||
|
|
||||||
In connection to the above, @emph{safemode} has no meaning in context
|
|
||||||
of UPDI devices and should be ignored.
|
|
||||||
|
|
||||||
Currently available devices support only UPDI NVM programming model 0
|
Currently available devices support only UPDI NVM programming model 0
|
||||||
and 2, but there is also experimental implementation of model 3 - not
|
and 2, but there is also experimental implementation of model 3 - not
|
||||||
yet tested.
|
yet tested.
|
||||||
|
|
|
@ -137,7 +137,6 @@ dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; }
|
||||||
default_bitclock { yylval=NULL; return K_DEFAULT_BITCLOCK; }
|
default_bitclock { yylval=NULL; return K_DEFAULT_BITCLOCK; }
|
||||||
default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; }
|
default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; }
|
||||||
default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; }
|
default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; }
|
||||||
default_safemode { yylval=NULL; return K_DEFAULT_SAFEMODE; }
|
|
||||||
default_serial { yylval=NULL; return K_DEFAULT_SERIAL; }
|
default_serial { yylval=NULL; return K_DEFAULT_SERIAL; }
|
||||||
delay { yylval=NULL; return K_DELAY; }
|
delay { yylval=NULL; return K_DELAY; }
|
||||||
desc { yylval=NULL; return K_DESC; }
|
desc { yylval=NULL; return K_DESC; }
|
||||||
|
|
|
@ -831,30 +831,6 @@ int fileio(int op, char * filename, FILEFMT format,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* formerly safemode.h */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries);
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
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);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* formerly update.h */
|
/* formerly update.h */
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -926,7 +902,6 @@ extern char default_programmer[];
|
||||||
extern char default_parallel[];
|
extern char default_parallel[];
|
||||||
extern char default_serial[];
|
extern char default_serial[];
|
||||||
extern double default_bitclock;
|
extern double default_bitclock;
|
||||||
extern int default_safemode;
|
|
||||||
|
|
||||||
/* This name is fixed, it's only here for symmetry with
|
/* This name is fixed, it's only here for symmetry with
|
||||||
* default_parallel and default_serial. */
|
* default_parallel and default_serial. */
|
||||||
|
|
239
src/main.c
239
src/main.c
|
@ -122,9 +122,6 @@ static 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, default when running from a script.\n"
|
|
||||||
" -s Silent safemode operation, will not ask you if\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"
|
||||||
" -x <extended_param> Pass <extended_param> to programmer.\n"
|
" -x <extended_param> Pass <extended_param> to programmer.\n"
|
||||||
|
@ -349,19 +346,11 @@ 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 ispdelay; /* Specify the delay for ISP clock */
|
int ispdelay; /* Specify the delay for ISP clock */
|
||||||
int safemode; /* Enable safemode, 1=safemode on, 0=normal */
|
|
||||||
int silentsafe; /* Don't ask about fuses, 1=silent, 0=normal */
|
|
||||||
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; /* Flags for do_op() */
|
||||||
unsigned char safemode_lfuse = 0xff;
|
|
||||||
unsigned char safemode_hfuse = 0xff;
|
|
||||||
unsigned char safemode_efuse = 0xff;
|
|
||||||
unsigned char safemode_fuse = 0xff;
|
|
||||||
|
|
||||||
char * safemode_response;
|
|
||||||
int fuses_updated = 0;
|
|
||||||
#if !defined(WIN32)
|
#if !defined(WIN32)
|
||||||
char * homedir;
|
char * homedir;
|
||||||
#endif
|
#endif
|
||||||
|
@ -394,7 +383,6 @@ int main(int argc, char * argv [])
|
||||||
default_parallel[0] = 0;
|
default_parallel[0] = 0;
|
||||||
default_serial[0] = 0;
|
default_serial[0] = 0;
|
||||||
default_bitclock = 0.0;
|
default_bitclock = 0.0;
|
||||||
default_safemode = -1;
|
|
||||||
|
|
||||||
init_config();
|
init_config();
|
||||||
|
|
||||||
|
@ -434,8 +422,6 @@ int main(int argc, char * argv [])
|
||||||
baudrate = 0;
|
baudrate = 0;
|
||||||
bitclock = 0.0;
|
bitclock = 0.0;
|
||||||
ispdelay = 0;
|
ispdelay = 0;
|
||||||
safemode = 1; /* Safemode on by default */
|
|
||||||
silentsafe = 0; /* Ask by default */
|
|
||||||
is_open = 0;
|
is_open = 0;
|
||||||
logfile = NULL;
|
logfile = NULL;
|
||||||
|
|
||||||
|
@ -581,19 +567,10 @@ 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;
|
||||||
|
|
||||||
case 'u' : /* Disable safemode */
|
|
||||||
safemode = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
upd = parse_op(optarg);
|
upd = parse_op(optarg);
|
||||||
if (upd == NULL) {
|
if (upd == NULL) {
|
||||||
|
@ -975,29 +952,6 @@ int main(int argc, char * argv [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (default_safemode == 0) {
|
|
||||||
/* configuration disables safemode: revert meaning of -u */
|
|
||||||
if (safemode == 0)
|
|
||||||
/* -u was given: enable safemode */
|
|
||||||
safemode = 1;
|
|
||||||
else
|
|
||||||
/* -u not given: turn off */
|
|
||||||
safemode = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isatty(STDIN_FILENO) == 0 && silentsafe == 0)
|
|
||||||
safemode = 0; /* Turn off safemode if this isn't a terminal */
|
|
||||||
|
|
||||||
|
|
||||||
if(p->flags & AVRPART_AVR32) {
|
|
||||||
safemode = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_TPI)) {
|
|
||||||
safemode = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (avr_initmem(p) != 0)
|
if (avr_initmem(p) != 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "\n%s: failed to initialize memories\n",
|
avrdude_message(MSG_INFO, "\n%s: failed to initialize memories\n",
|
||||||
|
@ -1281,36 +1235,6 @@ int main(int argc, char * argv [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_ok && safemode == 1) {
|
|
||||||
/* If safemode is enabled, go ahead and read the current low, high,
|
|
||||||
and extended fuse bytes as needed */
|
|
||||||
|
|
||||||
rc = safemode_readfuses(&safemode_lfuse, &safemode_hfuse,
|
|
||||||
&safemode_efuse, &safemode_fuse, pgm, p);
|
|
||||||
|
|
||||||
if (rc != 0) {
|
|
||||||
|
|
||||||
//Check if the programmer just doesn't support reading
|
|
||||||
if (rc == -5)
|
|
||||||
{
|
|
||||||
avrdude_message(MSG_NOTICE, "%s: safemode: Fuse reading not supported by programmer.\n"
|
|
||||||
" Safemode disabled.\n", progname);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: To protect your AVR the programming "
|
|
||||||
"will be aborted\n",
|
|
||||||
progname);
|
|
||||||
exitrc = 1;
|
|
||||||
goto main_exit;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Save the fuses as default
|
|
||||||
safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uflags & UF_AUTO_ERASE) {
|
if (uflags & UF_AUTO_ERASE) {
|
||||||
if ((p->flags & AVRPART_HAS_PDI) && pgm->page_erase != NULL &&
|
if ((p->flags & AVRPART_HAS_PDI) && pgm->page_erase != NULL &&
|
||||||
lsize(updates) > 0) {
|
lsize(updates) > 0) {
|
||||||
|
@ -1386,169 +1310,6 @@ int main(int argc, char * argv [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Right before we exit programming mode, which will make the fuse
|
|
||||||
bits active, check to make sure they are still correct */
|
|
||||||
if (safemode == 1) {
|
|
||||||
/* If safemode is enabled, go ahead and read the current low,
|
|
||||||
* high, and extended fuse bytes as needed */
|
|
||||||
unsigned char safemodeafter_lfuse = 0xff;
|
|
||||||
unsigned char safemodeafter_hfuse = 0xff;
|
|
||||||
unsigned char safemodeafter_efuse = 0xff;
|
|
||||||
unsigned char safemodeafter_fuse = 0xff;
|
|
||||||
unsigned char failures = 0;
|
|
||||||
char yes[1] = {'y'};
|
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
|
||||||
avrdude_message(MSG_INFO, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Restore the default fuse values
|
|
||||||
safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
|
||||||
|
|
||||||
/* Try reading back fuses, make sure they are reliable to read back */
|
|
||||||
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
|
|
||||||
&safemodeafter_efuse, &safemodeafter_fuse, pgm, p) != 0) {
|
|
||||||
/* Uh-oh.. try once more to read back fuses */
|
|
||||||
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
|
|
||||||
&safemodeafter_efuse, &safemodeafter_fuse, pgm, p) != 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: Sorry, reading back fuses was unreliable. "
|
|
||||||
"I have given up and exited programming mode\n",
|
|
||||||
progname);
|
|
||||||
exitrc = 1;
|
|
||||||
goto main_exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AVRMEM * m;
|
|
||||||
|
|
||||||
/* Now check what fuses are against what they should be */
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
/* 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((int)(safemode_response[0])) == 'y') {
|
|
||||||
|
|
||||||
/* Enough chit-chat, time to program some fuses and check them */
|
|
||||||
if (safemode_writefuse (safemode_fuse, "fuse", pgm, p,
|
|
||||||
10) == 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
|
|
||||||
failures++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now check what fuses are against what they should be */
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
/* 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((int)(safemode_response[0])) == 'y') {
|
|
||||||
|
|
||||||
/* Enough chit-chat, time to program some fuses and check them */
|
|
||||||
if (safemode_writefuse (safemode_lfuse, "lfuse", pgm, p,
|
|
||||||
10) == 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
|
|
||||||
failures++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now check what fuses are against what they should be */
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* 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((int)(safemode_response[0])) == 'y') {
|
|
||||||
|
|
||||||
/* Enough chit-chat, time to program some fuses and check them */
|
|
||||||
if (safemode_writefuse(safemode_hfuse, "hfuse", pgm, p,
|
|
||||||
10) == 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
|
|
||||||
failures++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now check what fuses are against what they should be */
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* 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((int)(safemode_response[0])) == 'y') {
|
|
||||||
|
|
||||||
/* Enough chit-chat, time to program some fuses and check them */
|
|
||||||
if (safemode_writefuse (safemode_efuse, "efuse", pgm, p,
|
|
||||||
10) == 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
|
|
||||||
failures++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quell_progress < 2) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: ", progname);
|
|
||||||
if (failures == 0) {
|
|
||||||
avrdude_message(MSG_INFO, "Fuses OK (E:%02X, H:%02X, L:%02X)\n",
|
|
||||||
safemodeafter_efuse, safemodeafter_hfuse, safemodeafter_lfuse);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
avrdude_message(MSG_INFO, "Fuses not recovered, sorry\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fuses_updated) {
|
|
||||||
exitrc = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
main_exit:
|
main_exit:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
318
src/safemode.c
318
src/safemode.c
|
@ -1,318 +0,0 @@
|
||||||
/*
|
|
||||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
|
||||||
* avrdude is Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
|
||||||
*
|
|
||||||
* This file: Copyright (C) 2005-2007 Colin O'Flynn <coflynn@newae.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "ac_cfg.h"
|
|
||||||
|
|
||||||
#include "avrdude.h"
|
|
||||||
#include "libavrdude.h"
|
|
||||||
|
|
||||||
/* This value from ac_cfg.h */
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm,
|
|
||||||
AVRPART * p, int tries)
|
|
||||||
{
|
|
||||||
AVRMEM * m;
|
|
||||||
unsigned char fuseread;
|
|
||||||
int returnvalue = -1;
|
|
||||||
|
|
||||||
m = avr_locate_mem(p, fusename);
|
|
||||||
if (m == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Keep trying to write then read back the fuse values */
|
|
||||||
while (tries > 0) {
|
|
||||||
if (avr_write_byte(pgm, p, m, 0, fuse) != 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &fuseread) != 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Report information to user if needed */
|
|
||||||
avrdude_message(MSG_NOTICE, "%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 == fuseread) {
|
|
||||||
tries = 0;
|
|
||||||
returnvalue = 0;
|
|
||||||
}
|
|
||||||
tries--;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, unsigned char * fuse,
|
|
||||||
PROGRAMMER * pgm, AVRPART * p)
|
|
||||||
{
|
|
||||||
|
|
||||||
unsigned char value;
|
|
||||||
unsigned char fusegood = 0;
|
|
||||||
unsigned char allowfuseread = 1;
|
|
||||||
unsigned char safemode_lfuse;
|
|
||||||
unsigned char safemode_hfuse;
|
|
||||||
unsigned char safemode_efuse;
|
|
||||||
unsigned char safemode_fuse;
|
|
||||||
AVRMEM * m;
|
|
||||||
|
|
||||||
safemode_lfuse = *lfuse;
|
|
||||||
safemode_hfuse = *hfuse;
|
|
||||||
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 */
|
|
||||||
if(pgm->read_byte(pgm, p, m, 0, &safemode_fuse) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 1, fuse value: %x\n",progname, safemode_fuse);
|
|
||||||
if(pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 2, fuse value: %x\n",progname, value);
|
|
||||||
if (value == safemode_fuse) {
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 3, fuse value: %x\n",progname, value);
|
|
||||||
if (value == safemode_fuse)
|
|
||||||
{
|
|
||||||
fusegood = 1; /* Fuse read OK three times */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Programmer does not allow fuse reading.... no point trying anymore
|
|
||||||
if (allowfuseread == 0)
|
|
||||||
{
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fusegood == 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read fuse properly. "
|
|
||||||
"Programmer may not be reliable.\n", progname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (fusegood == 1) {
|
|
||||||
avrdude_message(MSG_NOTICE, "%s: safemode: fuse reads as %X\n", progname, safemode_fuse);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Read lfuse 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, "lfuse");
|
|
||||||
if (m != NULL) {
|
|
||||||
fusegood = 0; /* By default fuse is a failure */
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &safemode_lfuse) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 1, lfuse value: %x\n",progname, safemode_lfuse);
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 2, lfuse value: %x\n",progname, value);
|
|
||||||
if (value == safemode_lfuse) {
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 3, lfuse value: %x\n",progname, value);
|
|
||||||
if (value == safemode_lfuse){
|
|
||||||
fusegood = 1; /* Fuse read OK three times */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Programmer does not allow fuse reading.... no point trying anymore
|
|
||||||
if (allowfuseread == 0)
|
|
||||||
{
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (fusegood == 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read lfuse properly. "
|
|
||||||
"Programmer may not be reliable.\n", progname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (fusegood == 1) {
|
|
||||||
avrdude_message(MSG_NOTICE, "%s: safemode: lfuse reads as %X\n", progname, safemode_lfuse);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read hfuse 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, "hfuse");
|
|
||||||
if (m != NULL) {
|
|
||||||
fusegood = 0; /* By default fuse is a failure */
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &safemode_hfuse) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 1, hfuse value: %x\n",progname, safemode_hfuse);
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 2, hfuse value: %x\n",progname, value);
|
|
||||||
if (value == safemode_hfuse) {
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 3, hfuse value: %x\n",progname, value);
|
|
||||||
if (value == safemode_hfuse){
|
|
||||||
fusegood = 1; /* Fuse read OK three times */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Programmer does not allow fuse reading.... no point trying anymore
|
|
||||||
if (allowfuseread == 0)
|
|
||||||
{
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fusegood == 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read hfuse properly. "
|
|
||||||
"Programmer may not be reliable.\n", progname);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
else if (fusegood == 1){
|
|
||||||
avrdude_message(MSG_NOTICE, "%s: safemode: hfuse reads as %X\n", progname, safemode_hfuse);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read efuse 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, "efuse");
|
|
||||||
if (m != NULL) {
|
|
||||||
fusegood = 0; /* By default fuse is a failure */
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &safemode_efuse) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 1, efuse value: %x\n",progname, safemode_efuse);
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 2, efuse value: %x\n",progname, value);
|
|
||||||
if (value == safemode_efuse) {
|
|
||||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
|
||||||
{
|
|
||||||
allowfuseread = 0;
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: safemode read 3, efuse value: %x\n",progname, value);
|
|
||||||
if (value == safemode_efuse){
|
|
||||||
fusegood = 1; /* Fuse read OK three times */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Programmer does not allow fuse reading.... no point trying anymore
|
|
||||||
if (allowfuseread == 0)
|
|
||||||
{
|
|
||||||
return -5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fusegood == 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read efuse properly. "
|
|
||||||
"Programmer may not be reliable.\n", progname);
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
else if (fusegood == 1) {
|
|
||||||
avrdude_message(MSG_NOTICE, "%s: safemode: efuse reads as %X\n", progname, safemode_efuse);
|
|
||||||
}
|
|
||||||
|
|
||||||
*lfuse = safemode_lfuse;
|
|
||||||
*hfuse = safemode_hfuse;
|
|
||||||
*efuse = safemode_efuse;
|
|
||||||
*fuse = safemode_fuse;
|
|
||||||
|
|
||||||
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 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_hfuse = 0xff;
|
|
||||||
static unsigned char safemode_efuse = 0xff;
|
|
||||||
static unsigned char safemode_fuse = 0xff;
|
|
||||||
|
|
||||||
switch (save) {
|
|
||||||
|
|
||||||
/* Save the fuses as safemode setting */
|
|
||||||
case 1:
|
|
||||||
safemode_lfuse = *lfuse;
|
|
||||||
safemode_hfuse = *hfuse;
|
|
||||||
safemode_efuse = *efuse;
|
|
||||||
safemode_fuse = *fuse;
|
|
||||||
|
|
||||||
break;
|
|
||||||
/* Read back the fuses */
|
|
||||||
default:
|
|
||||||
*lfuse = safemode_lfuse;
|
|
||||||
*hfuse = safemode_hfuse;
|
|
||||||
*efuse = safemode_efuse;
|
|
||||||
*fuse = safemode_fuse;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue