diff --git a/src/arduino.c b/src/arduino.c index dbaafef2..f7b60246 100644 --- a/src/arduino.c +++ b/src/arduino.c @@ -130,4 +130,6 @@ void arduino_initpgm(PROGRAMMER * pgm) pgm->read_sig_bytes = arduino_read_sig_bytes; pgm->open = arduino_open; pgm->close = arduino_close; + + disable_trailing_ff_removal(); /* so that arduino bootloader can ignore chip erase */ } diff --git a/src/avr.c b/src/avr.c index 17f85f34..7f91e9a1 100644 --- a/src/avr.c +++ b/src/avr.c @@ -278,10 +278,28 @@ int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, * value. This is useful for determining where to stop when dealing * with "flash" memory, since writing 0xff to flash is typically a * no-op. Always return an even number since flash is word addressed. + * Only apply this optimisation on flash-type memory. */ int avr_mem_hiaddr(AVRMEM * mem) { int i, n; + static int disableffopt; + + /* calling once with NULL disables any future trailing-0xff optimisation */ + if(!mem) { + disableffopt = 1; + return 0; + } + + if(disableffopt) + return mem->size; + + /* if the memory is not a flash-type memory do not remove trailing 0xff */ + if(strcasecmp(mem->desc, "flash") && + strcasecmp(mem->desc, "application") && + strcasecmp(mem->desc, "apptable") && + strcasecmp(mem->desc, "boot")) + return mem->size; /* return the highest non-0xff address regardless of how much memory was read */ @@ -416,15 +434,8 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, nread++; report_progress(nread, npages, NULL); } - if (!failure) { - if (strcasecmp(mem->desc, "flash") == 0 || - strcasecmp(mem->desc, "application") == 0 || - strcasecmp(mem->desc, "apptable") == 0 || - strcasecmp(mem->desc, "boot") == 0) - return avr_mem_hiaddr(mem); - else - return mem->size; - } + if (!failure) + return avr_mem_hiaddr(mem); /* else: fall back to byte-at-a-time write, for historical reasons */ } @@ -454,13 +465,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, report_progress(i, mem->size, NULL); } - if (strcasecmp(mem->desc, "flash") == 0 || - strcasecmp(mem->desc, "application") == 0 || - strcasecmp(mem->desc, "apptable") == 0 || - strcasecmp(mem->desc, "boot") == 0) - return avr_mem_hiaddr(mem); - else - return i; + return avr_mem_hiaddr(mem); } diff --git a/src/avrdude.1 b/src/avrdude.1 index 81834d30..c4fc850f 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -18,7 +18,7 @@ .\" .\" $Id$ .\" -.Dd November 22, 2021 +.Dd July 12, 2022 .Os .Dt AVRDUDE 1 .Sh NAME @@ -31,6 +31,7 @@ .Op Fl B Ar bitclock .Op Fl c Ar programmer-id .Op Fl C Ar config-file +.Op Fl A .Op Fl D .Op Fl e .Oo Fl E Ar exitspec Ns @@ -102,7 +103,7 @@ available (like almost all embedded Linux boards) you can do without any additional hardware - just connect them to the MOSI, MISO, RESET and SCK pins on the AVR and use the linuxgpio programmer type. It bitbangs the lines using the Linux sysfs GPIO interface. Of course, care should -be taken about voltage level compatibility. Also, although not strictrly +be taken about voltage level compatibility. Also, although not strictly required, it is strongly advisable to protect the GPIO pins from overcurrent situations in some way. The simplest would be to just put some resistors in series or better yet use a 3-state buffer driver like @@ -253,7 +254,7 @@ The Teensy bootloader is supported for all AVR boards. As the bootloader does not support reading from flash memory, use the .Fl V -option to prevent AVRDUDE from verifing the flash memory. +option to prevent AVRDUDE from verifying the flash memory. See the section on .Em extended parameters for Teensy specific options. @@ -376,6 +377,20 @@ files. This can be used to add entries to the configuration without patching your system wide configuration file. It can be used several times, the files are read in same order as given on the command line. +.It Fl A +Disable the automatic removal of trailing-0xFF sequences in file +input that is to be programmed to flash and in AVR reads from +flash memory. Normally, trailing 0xFFs can be discarded, as flash +programming requires the memory be erased to 0xFF beforehand. +.Fl A +should be used when the programmer hardware, or bootloader +software for that matter, does not carry out chip erase and +instead handles the memory erase on a page level. The popular +Arduino bootloader exhibits this behaviour; for this reason +.Fl A +is engaged by default when specifying +. Fl c +arduino. .It Fl D Disable auto erase for flash. When the .Fl U @@ -389,6 +404,10 @@ use page erase before writing each page so no explicit chip erase is required. Note however that any page not affected by the current operation will retain its previous contents. +Setting +.Fl D +implies +.Fl A. .It Fl e Causes a chip erase to be executed. This will reset the contents of the flash ROM and EEPROM to the value diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 92cf4df4..d99b0a85 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -321,13 +321,13 @@ via a serial link (@url{https://github.com/ElTangas/jtag2updi}). The Micronucleus bootloader is supported for both protocol version V1 and V2. As the bootloader does not support reading from flash memory, -use the @code{-V} option to prevent AVRDUDE from verifing the flash memory. +use the @code{-V} option to prevent AVRDUDE from verifying the flash memory. See the section on @emph{extended parameters} below for Micronucleus specific options. The Teensy bootloader is supported for all AVR boards. As the bootloader does not support reading from flash memory, -use the @code{-V} option to prevent AVRDUDE from verifing the flash memory. +use the @code{-V} option to prevent AVRDUDE from verifying the flash memory. See the section on @emph{extended parameters} below for Teensy specific options. @@ -495,6 +495,16 @@ without patching your system wide configuration file. It can be used several times, the files are read in same order as given on the command line. +@item -A +Disable the automatic removal of trailing-0xFF sequences in file +input that is to be programmed to flash and in AVR reads from +flash memory. Normally, trailing 0xFFs can be discarded, as flash +programming requires the memory be erased to 0xFF beforehand. -A +should be used when the programmer hardware, or bootloader +software for that matter, does not carry out chip erase and +instead handles the memory erase on a page level. The popular +Arduino bootloader exhibits this behaviour; for this reason -A is +engaged by default when specifying -c arduino. @item -D Disable auto erase for flash. When the -U option with flash memory is @@ -506,6 +516,7 @@ use page erase before writing each page so no explicit chip erase is required. Note however that any page not affected by the current operation will retain its previous contents. +Setting -D implies -A. @item -e Causes a chip erase to be executed. This will reset the contents of the diff --git a/src/fileio.c b/src/fileio.c index 7c021ce4..1c81682d 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1446,16 +1446,17 @@ static int fmt_autodetect(char * fname) -int fileio(int op, char * filename, FILEFMT format, +int fileio(int oprwv, char * filename, FILEFMT format, struct avrpart * p, char * memtype, int size) { - int rc; + int op, rc; FILE * f; char * fname; struct fioparms fio; AVRMEM * mem; int using_stdio; + op = oprwv == FIO_READ_FOR_VERIFY? FIO_READ: oprwv; mem = avr_locate_mem(p, memtype); if (mem == NULL) { avrdude_message(MSG_INFO, "fileio(): memory type \"%s\" not configured for device \"%s\"\n", @@ -1585,18 +1586,14 @@ int fileio(int op, char * filename, FILEFMT format, return -1; } - if (rc > 0) { - if ((op == FIO_READ) && (strcasecmp(mem->desc, "flash") == 0 || - strcasecmp(mem->desc, "application") == 0 || - strcasecmp(mem->desc, "apptable") == 0 || - strcasecmp(mem->desc, "boot") == 0)) { - /* - * if we are reading flash, just mark the size as being the - * highest non-0xff byte - */ - rc = avr_mem_hiaddr(mem); - } + /* on reading flash other than for verify set the size to location of highest non-0xff byte */ + if (rc > 0 && oprwv == FIO_READ) { + int hiaddr = avr_mem_hiaddr(mem); + + if(hiaddr < rc) /* if trailing-0xff not disabled */ + rc = hiaddr; } + if (format != FMT_IMM && !using_stdio) { fclose(f); } diff --git a/src/libavrdude.h b/src/libavrdude.h index 46789f4f..7088b108 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -797,6 +797,7 @@ int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles); int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles); +#define disable_trailing_ff_removal() avr_mem_hiaddr(NULL) int avr_mem_hiaddr(AVRMEM * mem); int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p); @@ -835,7 +836,8 @@ struct fioparms { enum { FIO_READ, - FIO_WRITE + FIO_WRITE, + FIO_READ_FOR_VERIFY, }; #ifdef __cplusplus @@ -844,7 +846,7 @@ extern "C" { char * fmtstr(FILEFMT format); -int fileio(int op, char * filename, FILEFMT format, +int fileio(int oprwv, char * filename, FILEFMT format, struct avrpart * p, char * memtype, int size); #ifdef __cplusplus diff --git a/src/main.c b/src/main.c index 5b0a6e38..1d00ae67 100644 --- a/src/main.c +++ b/src/main.c @@ -110,7 +110,8 @@ static void usage(void) " -B <bitclock> Specify JTAG/STK500v2 bit clock period (us).\n" " -C <config-file> Specify location of configuration file.\n" " -c <programmer> Specify programmer type.\n" - " -D Disable auto erase for flash memory\n" + " -A Disable trailing-0xff removal from file and AVR read.\n" + " -D Disable auto erase for flash memory; implies -A.\n" " -i <delay> ISP Clock Delay [in microseconds]\n" " -P <port> Specify connection port.\n" " -F Override invalid signature check.\n" @@ -442,7 +443,7 @@ int main(int argc, char * argv []) /* * process command line arguments */ - while ((ch = getopt(argc,argv,"?b:B:c:C:DeE:Fi:l:np:OP:qstU:uvVx:yY:")) != -1) { + while ((ch = getopt(argc,argv,"?Ab:B:c:C:DeE:Fi:l:np:OP:qstU:uvVx:yY:")) != -1) { switch (ch) { case 'b': /* override default programmer baud rate */ @@ -528,6 +529,10 @@ int main(int argc, char * argv []) case 'D': /* disable auto erase */ uflags &= ~UF_AUTO_ERASE; + /* fall through */ + + case 'A': /* explicit disabling of trailing-0xff removal */ + disable_trailing_ff_removal(); break; case 'e': /* perform a chip erase */ diff --git a/src/update.c b/src/update.c index 15002549..d3c208fc 100644 --- a/src/update.c +++ b/src/update.c @@ -341,7 +341,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f progname, mem->desc, alias_mem_desc, upd->filename); } - rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); + rc = fileio(FIO_READ_FOR_VERIFY, upd->filename, upd->format, p, upd->memtype, -1); if (rc < 0) { avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n", progname, upd->filename);