From ed38456f83ac84ab1f3facc52de83f4e58a78f18 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 15 Apr 2022 20:46:40 +0100 Subject: [PATCH 01/11] Piggy-back 'Do not remove trailing 0xff' onto option -D --- src/avr.c | 10 ++++++++++ src/fileio.c | 5 ++++- src/main.c | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/avr.c b/src/avr.c index d6e78bb5..9d2bf503 100644 --- a/src/avr.c +++ b/src/avr.c @@ -282,6 +282,16 @@ int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, 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; /* return the highest non-0xff address regardless of how much memory was read */ diff --git a/src/fileio.c b/src/fileio.c index 7c021ce4..429a200e 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1594,7 +1594,10 @@ int fileio(int op, char * filename, FILEFMT format, * if we are reading flash, just mark the size as being the * highest non-0xff byte */ - rc = avr_mem_hiaddr(mem); + int hiaddr = avr_mem_hiaddr(mem); + + if(hiaddr < rc) /* if trailing-0xff not disabled */ + rc = hiaddr; } } if (format != FMT_IMM && !using_stdio) { diff --git a/src/main.c b/src/main.c index 253c6e51..c3bc0381 100644 --- a/src/main.c +++ b/src/main.c @@ -528,6 +528,7 @@ int main(int argc, char * argv []) case 'D': /* disable auto erase */ uflags &= ~UF_AUTO_ERASE; + avr_mem_hiaddr(NULL); /* disable trailing 0xff optimisation */ break; case 'e': /* perform a chip erase */ From e18d436f88e575afcee68343842660b44aa9ce30 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 15 Apr 2022 20:48:46 +0100 Subject: [PATCH 02/11] Move evaluating 'is flash' from caller to callee avr_mem_hiaddr() --- src/avr.c | 27 +++++++++++---------------- src/fileio.c | 19 ++++++------------- 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/avr.c b/src/avr.c index 9d2bf503..a6d621b7 100644 --- a/src/avr.c +++ b/src/avr.c @@ -278,6 +278,7 @@ 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) { @@ -293,6 +294,13 @@ int avr_mem_hiaddr(AVRMEM * mem) 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 */ for (i=mem->size-1; i>0; i--) { @@ -426,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 */ } @@ -464,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/fileio.c b/src/fileio.c index 429a200e..754e267b 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1585,21 +1585,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 - */ - int hiaddr = avr_mem_hiaddr(mem); + /* on reading flash set the size to location of highest non-0xff byte */ + if (rc > 0 && op == FIO_READ) { + int hiaddr = avr_mem_hiaddr(mem); - if(hiaddr < rc) /* if trailing-0xff not disabled */ - rc = hiaddr; - } + if(hiaddr < rc) /* if trailing-0xff not disabled */ + rc = hiaddr; } + if (format != FMT_IMM && !using_stdio) { fclose(f); } From 2397984d2b13b885fee4100f79af6612dca33599 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 27 Apr 2022 18:54:13 +0100 Subject: [PATCH 03/11] Disable trailing-0xff removal when invoking arduino programmer --- src/arduino.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/arduino.c b/src/arduino.c index dbaafef2..7f030a13 100644 --- a/src/arduino.c +++ b/src/arduino.c @@ -130,4 +130,7 @@ void arduino_initpgm(PROGRAMMER * pgm) pgm->read_sig_bytes = arduino_read_sig_bytes; pgm->open = arduino_open; pgm->close = arduino_close; + + /* disable trailing-0xff removal when reading input files and avr flash */ + avr_mem_hiaddr(NULL); } From 52b20f4a2808dc6732fd9d185a9f0b3c1122b7e0 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 28 Apr 2022 17:26:09 +0100 Subject: [PATCH 04/11] Provide self-documenting API for disabling trailing-0xff removal --- src/arduino.c | 3 +-- src/libavrdude.h | 1 + src/main.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/arduino.c b/src/arduino.c index 7f030a13..f7b60246 100644 --- a/src/arduino.c +++ b/src/arduino.c @@ -131,6 +131,5 @@ void arduino_initpgm(PROGRAMMER * pgm) pgm->open = arduino_open; pgm->close = arduino_close; - /* disable trailing-0xff removal when reading input files and avr flash */ - avr_mem_hiaddr(NULL); + disable_trailing_ff_removal(); /* so that arduino bootloader can ignore chip erase */ } diff --git a/src/libavrdude.h b/src/libavrdude.h index ddb72b48..d8d5739a 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -787,6 +787,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); diff --git a/src/main.c b/src/main.c index c3bc0381..526ae35f 100644 --- a/src/main.c +++ b/src/main.c @@ -528,7 +528,7 @@ int main(int argc, char * argv []) case 'D': /* disable auto erase */ uflags &= ~UF_AUTO_ERASE; - avr_mem_hiaddr(NULL); /* disable trailing 0xff optimisation */ + disable_trailing_ff_removal(); break; case 'e': /* perform a chip erase */ From 52734bafc6af7cfc4b72824629159900ee88f6a6 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 28 Apr 2022 17:29:06 +0100 Subject: [PATCH 05/11] Add option -A to separately disable trailing-0xff removal --- src/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index 526ae35f..f5381834 100644 --- a/src/main.c +++ b/src/main.c @@ -110,7 +110,8 @@ static void usage(void) " -B Specify JTAG/STK500v2 bit clock period (us).\n" " -C Specify location of configuration file.\n" " -c 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 ISP Clock Delay [in microseconds]\n" " -P 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,9 @@ 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; From f47ec634f81a0f9bd89aa6ce0616b147f69da5d9 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 28 Apr 2022 17:53:10 +0100 Subject: [PATCH 06/11] On verify always verify full input file --- src/fileio.c | 9 +++++---- src/libavrdude.h | 5 +++-- src/update.c | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 754e267b..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,8 +1586,8 @@ int fileio(int op, char * filename, FILEFMT format, return -1; } - /* on reading flash set the size to location of highest non-0xff byte */ - if (rc > 0 && op == FIO_READ) { + /* 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 */ diff --git a/src/libavrdude.h b/src/libavrdude.h index d8d5739a..73083932 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -826,7 +826,8 @@ struct fioparms { enum { FIO_READ, - FIO_WRITE + FIO_WRITE, + FIO_READ_FOR_VERIFY, }; #ifdef __cplusplus @@ -835,7 +836,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/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); From 580c37fbfefcff83131ea767b176cbf27f9a39a8 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 29 Apr 2022 00:14:45 +0100 Subject: [PATCH 07/11] Describe -A in the man and .texi documentation --- src/avrdude.1 | 25 ++++++++++++++++++++++--- src/doc/avrdude.texi | 15 +++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index cc05cf4c..48082d00 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -18,7 +18,7 @@ .\" .\" $Id$ .\" -.Dd DATE November 22, 2021 +.Dd DATE April 28, 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 ad4a6598..a7901361 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 From a721e485cb873c1ef38bbe756c85cc012d412327 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 4 Jul 2022 23:04:36 +0100 Subject: [PATCH 08/11] Refactor paged read/write routines in ft245r.c --- src/ft245r.c | 326 +++++++++++++++++++++++---------------------------- 1 file changed, 149 insertions(+), 177 deletions(-) diff --git a/src/ft245r.c b/src/ft245r.c index d5af4ca9..4525cab1 100644 --- a/src/ft245r.c +++ b/src/ft245r.c @@ -107,10 +107,10 @@ void ft245r_initpgm(PROGRAMMER * pgm) { #else -#define FT245R_CYCLES 2 -#define FT245R_FRAGMENT_SIZE 512 -#define REQ_OUTSTANDINGS 10 -//#define USE_INLINE_WRITE_PAGE +#define FT245R_CYCLES 2 +#define FT245R_CMD_SIZE (4 * 8*FT245R_CYCLES) +#define FT245R_FRAGMENT_SIZE (8 * FT245R_CMD_SIZE) +#define REQ_OUTSTANDINGS 10 #define FT245R_DEBUG 0 /* @@ -992,40 +992,18 @@ static void ft245r_display(PROGRAMMER * pgm, const char * p) { pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS); } -static int ft245r_paged_write_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - unsigned int page_size, unsigned int addr, - unsigned int n_bytes) { - unsigned long i, pa; - int rc; - for (i=0; ibuf[addr]); - if (rc != 0) { +static int ft245r_paged_write_gen(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { + + for(int i=0; i < (int) n_bytes; i++, addr++) + if(avr_write_byte_default(pgm, p, m, addr, m->buf[addr]) != 0) return -2; - } - if (m->paged) { - // Can this piece of code ever be activated?? Do AVRs exist that - // have paged non-flash memories? -- REW - // XXX Untested code below. - /* - * check to see if it is time to flush the page with a page - * write - */ - - if (((addr % m->page_size) == m->page_size-1) || (i == n_bytes-1)) { - pa = addr - (addr % m->page_size); - - rc = avr_write_page(pgm, p, m, pa); - if (rc != 0) { - return -2; - } - } - } - } - return i; + return n_bytes; } + static struct ft245r_request { int addr; int bytes; @@ -1081,178 +1059,172 @@ static int do_request(PROGRAMMER * pgm, AVRMEM *m) { return 1; } -static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - int page_size, int addr, int n_bytes) { - unsigned int i,j; - int addr_save,buf_pos,do_page_write,req_count; - unsigned char buf[FT245R_FRAGMENT_SIZE+1+128]; - req_count = 0; - for (i=0; i> 9) & 0xff ); - buf_pos += set_data(pgm, buf+buf_pos, (addr >> 1) & 0xff ); - buf_pos += set_data(pgm, buf+buf_pos, m->buf[addr]); - addr ++; - i++; - if ( (m->paged) && - (((i % m->page_size) == 0) || (i == n_bytes))) { - do_page_write = 1; - break; - } - } -#if defined(USE_INLINE_WRITE_PAGE) - if (do_page_write) { - int addr_wk = addr_save - (addr_save % m->page_size); - /* If this device has a "load extended address" command, issue it. */ - if (m->op[AVR_OP_LOAD_EXT_ADDR]) { - unsigned char cmd[4]; - OPCODE *lext = m->op[AVR_OP_LOAD_EXT_ADDR]; +static int ft245r_paged_write_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { - memset(cmd, 0, 4); - avr_set_bits(lext, cmd); - avr_set_addr(lext, cmd, addr_wk/2); - buf_pos += set_data(pgm, buf+buf_pos, cmd[0]); - buf_pos += set_data(pgm, buf+buf_pos, cmd[1]); - buf_pos += set_data(pgm, buf+buf_pos, cmd[2]); - buf_pos += set_data(pgm, buf+buf_pos, cmd[3]); + int i, j, addr_save, buf_pos, req_count, do_page_write; + unsigned char buf[FT245R_FRAGMENT_SIZE+1]; + unsigned char cmd[4]; + + if(m->op[AVR_OP_LOADPAGE_LO] == NULL || m->op[AVR_OP_LOADPAGE_HI] == NULL) { + avrdude_message(MSG_INFO, "AVR_OP_LOADPAGE_HI/LO command not defined for %s\n", p->desc); + return -1; + } + + do_page_write = req_count = i = j = buf_pos = 0; + addr_save = addr; + while(i < (int) n_bytes) { + int spi = addr&1? AVR_OP_LOADPAGE_HI: AVR_OP_LOADPAGE_LO; + + // put the SPI loadpage command as FT245R_CMD_SIZE bytes into buffer + memset(cmd, 0, sizeof cmd); + avr_set_bits(m->op[spi], cmd); + avr_set_addr(m->op[spi], cmd, addr/2); + avr_set_input(m->op[spi], cmd, m->buf[addr]); + for(int k=0; kpaged && (i%m->page_size == 0 || i >= (int) n_bytes)) + do_page_write = 1; + + // page boundary, finished or buffer exhausted? queue up requests + if(do_page_write || i >= (int) n_bytes || j >= FT245R_FRAGMENT_SIZE/FT245R_CMD_SIZE) { + if(i >= n_bytes) { + ft245r_out = SET_BITS_0(ft245r_out, pgm, PIN_AVR_SCK, 0); // SCK down + buf[buf_pos++] = ft245r_out; + } else { + // stretch sequence to allow correct readout, see extract_data() + buf[buf_pos] = buf[buf_pos - 1]; + buf_pos++; } - buf_pos += set_data(pgm, buf+buf_pos, 0x4C); /* Issue Page Write */ - buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 9) & 0xff); - buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 1) & 0xff); - buf_pos += set_data(pgm, buf+buf_pos, 0); - } -#endif - if (i >= n_bytes) { - ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down - buf[buf_pos++] = ft245r_out; - } - else { - /* stretch sequence to allow correct readout, see extract_data() */ - buf[buf_pos] = buf[buf_pos - 1]; - buf_pos++; - } - ft245r_send(pgm, buf, buf_pos); - put_request(addr_save, buf_pos, 0); - //ft245r_sync(pgm); -#if 0 - avrdude_message(MSG_INFO, "send addr 0x%04x bufsize %d [%02x %02x] page_write %d\n", - addr_save,buf_pos, - extract_data_out(pgm, buf , (0*4 + 3) ), - extract_data_out(pgm, buf , (1*4 + 3) ), - do_page_write); -#endif - req_count++; - if (req_count > REQ_OUTSTANDINGS) - do_request(pgm, m); - if (do_page_write) { -#if defined(USE_INLINE_WRITE_PAGE) - while (do_request(pgm, m)) - ; - ft245r_usleep(pgm, m->max_write_delay); -#else - int addr_wk = addr_save - (addr_save % m->page_size); - int rc; - while (do_request(pgm, m)) - ; - rc = avr_write_page(pgm, p, m, addr_wk); - if (rc != 0) { - return -2; + ft245r_send(pgm, buf, buf_pos); + put_request(addr_save, buf_pos, 0); + + if(++req_count > REQ_OUTSTANDINGS) + do_request(pgm, m); + + if(do_page_write) { + while(do_request(pgm, m)) + continue; + if(avr_write_page(pgm, p, m, addr_save - (addr_save % m->page_size)) != 0) + return -2; + do_page_write = req_count = 0; } -#endif - req_count = 0; + + // reset buffer variables + j = buf_pos = 0; + addr_save = addr; } } - while (do_request(pgm, m)) - ; - return i; + + while(do_request(pgm, m)) + continue; + + return n_bytes; } static int ft245r_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - unsigned int page_size, unsigned int addr, unsigned int n_bytes) { - if (strcmp(m->desc, "flash") == 0) { + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { + + if(!n_bytes) + return 0; + + if(strcmp(m->desc, "flash") == 0) return ft245r_paged_write_flash(pgm, p, m, page_size, addr, n_bytes); - } else if (strcmp(m->desc, "eeprom") == 0) { + + if(strcmp(m->desc, "eeprom") == 0) return ft245r_paged_write_gen(pgm, p, m, page_size, addr, n_bytes); - } else { - return -2; - } + + return -2; } -static int ft245r_paged_load_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - unsigned int page_size, unsigned int addr, - int n_bytes) { - unsigned char rbyte; - unsigned long i; - int rc; +static int ft245r_paged_load_gen(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { - for (i=0; ibuf[i+addr] = rbyte; + + m->buf[addr+i] = rbyte; } + return 0; } -static int ft245r_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - unsigned int page_size, unsigned int addr, - unsigned int n_bytes) { - unsigned long i,j,n; - int addr_save,buf_pos; - int req_count = 0; + +static int ft245r_paged_load_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { + + int i, j, addr_save, buf_pos, req_count; unsigned char buf[FT245R_FRAGMENT_SIZE+1]; + unsigned char cmd[4]; - for (i=0; i= n_bytes) break; - buf_pos += set_data(pgm, buf+buf_pos, (addr & 1)?0x28:0x20 ); - buf_pos += set_data(pgm, buf+buf_pos, (addr >> 9) & 0xff ); - buf_pos += set_data(pgm, buf+buf_pos, (addr >> 1) & 0xff ); - buf_pos += set_data(pgm, buf+buf_pos, 0); - addr ++; - i++; - } - if (i >= n_bytes) { - ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down - buf[buf_pos++] = ft245r_out; - } - else { - /* stretch sequence to allow correct readout, see extract_data() */ - buf[buf_pos] = buf[buf_pos - 1]; - buf_pos++; - } - n = j; - ft245r_send(pgm, buf, buf_pos); - put_request(addr_save, buf_pos, n); - req_count++; - if (req_count > REQ_OUTSTANDINGS) - do_request(pgm, m); - + if(m->op[AVR_OP_READ_LO] == NULL || m->op[AVR_OP_READ_HI] == NULL) { + avrdude_message(MSG_INFO, "AVR_OP_READ_HI/LO command not defined for %s\n", p->desc); + return -1; } - while (do_request(pgm, m)) - ; + + req_count = i = j = buf_pos = 0; + addr_save = addr; + while(i < (int) n_bytes) { + int spi = addr&1? AVR_OP_READ_HI: AVR_OP_READ_LO; + + // put the SPI read command as FT245R_CMD_SIZE bytes into buffer + memset(cmd, 0, sizeof cmd); + avr_set_bits(m->op[spi], cmd); + avr_set_addr(m->op[spi], cmd, addr/2); + for(int k=0; k= (int) n_bytes || j >= FT245R_FRAGMENT_SIZE/FT245R_CMD_SIZE) { + if(i >= (int) n_bytes) { + ft245r_out = SET_BITS_0(ft245r_out, pgm, PIN_AVR_SCK, 0); // SCK down + buf[buf_pos++] = ft245r_out; + } else { + // stretch sequence to allow correct readout, see extract_data() + buf[buf_pos] = buf[buf_pos - 1]; + buf_pos++; + } + ft245r_send(pgm, buf, buf_pos); + put_request(addr_save, buf_pos, j); + + if(++req_count > REQ_OUTSTANDINGS) + do_request(pgm, m); + + // reset buffer variables + j = buf_pos = 0; + addr_save = addr; + } + } + + while(do_request(pgm, m)) + continue; + return 0; } -static int ft245r_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - unsigned int page_size, unsigned int addr, - unsigned int n_bytes) { - if (strcmp(m->desc, "flash") == 0) { +static int ft245r_paged_load(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { + + if(!n_bytes) + return 0; + + if(strcmp(m->desc, "flash") == 0) return ft245r_paged_load_flash(pgm, p, m, page_size, addr, n_bytes); - } else if (strcmp(m->desc, "eeprom") == 0) { + + if(strcmp(m->desc, "eeprom") == 0) return ft245r_paged_load_gen(pgm, p, m, page_size, addr, n_bytes); - } else { - return -2; - } + + return -2; } void ft245r_initpgm(PROGRAMMER * pgm) { From 7aad03cbcdd762b912f9ef920c2badd2463efabb Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 4 Jul 2022 23:11:32 +0100 Subject: [PATCH 09/11] Fix paged read for ATmega2560 et al for ft245r.c --- src/ft245r.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/ft245r.c b/src/ft245r.c index 4525cab1..874167ac 100644 --- a/src/ft245r.c +++ b/src/ft245r.c @@ -1170,6 +1170,19 @@ static int ft245r_paged_load_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, return -1; } + // always called with addr at page boundary, and n_bytes == m->page_size; + // hence, OK to prepend load extended address command (at most) once + if(m->op[AVR_OP_LOAD_EXT_ADDR]) { + memset(cmd, 0, sizeof cmd); + avr_set_bits(m->op[AVR_OP_LOAD_EXT_ADDR], cmd); + avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], cmd, addr/2); + + buf_pos = 0; + for(int k=0; k Date: Sun, 10 Jul 2022 23:25:31 +0100 Subject: [PATCH 10/11] Fix PICKit2 ATmega2560 flash paged flash read The paged read in pickit2.c has two errors: - It drops load extended address commands unless a paged read happens at a 64k byte boundary; this is invalid when reading files with holes - It wrongly assumed that flash memory is byte addressed The fix is to carry out a load extended address command, if needed, at the beginning of each paged flash read with the correct word address. Although the pickit2_paged_load() has independent parameters page_size, addr and n_bytes, AVRDUDE only ever calls paged read/write functions with page_size and n_bytes both set to mem->page_size and addr aligned with a page boundary. Therefore, it is sufficient to set the load extended address at the beginning of each page read. --- src/pickit2.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/pickit2.c b/src/pickit2.c index 9e4be94c..ac3781f5 100644 --- a/src/pickit2.c +++ b/src/pickit2.c @@ -491,18 +491,15 @@ static int pickit2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, pgm->pgm_led(pgm, ON); + if (lext) { + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(lext, cmd); + avr_set_addr(lext, cmd, addr/2); + pgm->cmd(pgm, cmd, res); + } + for (addr_base = addr; addr_base < max_addr; ) { - if ((addr_base == 0 || (addr_base % /*ext_address_boundary*/ 65536) == 0) - && lext != NULL) - { - memset(cmd, 0, sizeof(cmd)); - - avr_set_bits(lext, cmd); - avr_set_addr(lext, cmd, addr_base); - pgm->cmd(pgm, cmd, res); - } - // bytes to send in the next packet -- not necessary as pickit2_spi() handles breaking up // the data into packets -- but we need to keep transfers frequent so that we can update the // status indicator bar From c81f52ff1088310e77f74d11fa8ff4238ec4a7bc Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Tue, 12 Jul 2022 15:52:37 +0100 Subject: [PATCH 11/11] Update NEWS --- NEWS | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 78f59f95..7bea2bcb 100644 --- a/NEWS +++ b/NEWS @@ -32,8 +32,12 @@ Changes since version 7.0: - Replace internal knowledge in jtag3.c by a public API #996 - JTAG3 UPDI EEPROM fix #1013 - Treat x bits in .conf SPI commands as 0 #943 - - Fix avrftdi support for ATmega2560 et al #474 - - Fix avrdude.conf timings for ATmega328PB and other parts #976 + - Fix avrftdi support for ATmega2560 et al #998 + - Fix avrdude.conf timings for ATmega328PB and other parts #1001 + - Fix PICKit2 ATmega2560 flash paged flash read #1023 + - Fix ft245r paged read for ATmega2560 et al #1018 + - Add option -A that supresses trailing 0xff optimisation + and automatically do so for -c arduino #936 * Internals: