From 48919f59b318ac001146959079914fee4d27d386 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Tue, 11 Oct 2022 15:31:18 +0100 Subject: [PATCH 1/3] Use byte-wise read/write when page size is 1 in terminal cache --- src/avrcache.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/avrcache.c b/src/avrcache.c index 299e9288..ed105f25 100644 --- a/src/avrcache.c +++ b/src/avrcache.c @@ -114,7 +114,10 @@ * - Memory has positive page size, which is a power of two * - Memory has positive size, which is a multiple of the page size * - Memory is flash type or eeprom type + * + * Note that in this definition the page size can be 1 */ + int avr_has_paged_access(const PROGRAMMER *pgm, const AVRMEM *mem) { return pgm->paged_load && pgm->paged_write && mem->page_size > 0 && (mem->page_size & (mem->page_size-1)) == 0 && @@ -127,6 +130,7 @@ int avr_has_paged_access(const PROGRAMMER *pgm, const AVRMEM *mem) { * Read the page containing addr from the device into buf * - Caller to ensure buf has mem->page_size bytes * - Part memory buffer mem is unaffected by this (though temporarily changed) + * - Uses read_byte() if memory page size is one, otherwise paged_load() */ int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, unsigned char *buf) { if(!avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size) @@ -135,6 +139,9 @@ int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM int rc, pgsize = mem->page_size, off = addr & ~(pgsize-1); unsigned char *pagecopy = cfg_malloc("avr_read_page_default()", pgsize); + if(pgsize == 1) + return pgm->read_byte(pgm, p, mem, addr, buf); + memcpy(pagecopy, mem->buf + off, pgsize); if((rc = pgm->paged_load(pgm, p, mem, pgsize, off, pgsize)) >= 0) memcpy(buf, mem->buf + off, pgsize); @@ -149,6 +156,7 @@ int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM * Write the data page to the device into the page containing addr * - Caller to provide all mem->page_size bytes incl padding if any * - Part memory buffer mem is unaffected by this (though temporarily changed) + * - Uses write_byte() if memory page size is one, otherwise paged_write() */ int avr_write_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, unsigned char *data) { if(!avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size) @@ -157,6 +165,9 @@ int avr_write_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM int rc, pgsize = mem->page_size, off = addr & ~(pgsize-1); unsigned char *pagecopy = cfg_malloc("avr_write_page_default()", pgsize); + if(pgsize == 1) + return pgm->write_byte(pgm, p, mem, addr, *data); + memcpy(pagecopy, mem->buf + off, pgsize); memcpy(mem->buf + off, data, pgsize); rc = pgm->paged_write(pgm, p, mem, pgsize, off, pgsize); @@ -652,11 +663,16 @@ int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM int addr = uaddr; - if(!pgm->page_erase || !avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size) + if(!avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size) return LIBAVRDUDE_GENERAL_FAILURE; - if(pgm->page_erase(pgm, p, mem, uaddr) < 0) - return LIBAVRDUDE_GENERAL_FAILURE; + if(mem->page_size == 1) { + if(pgm->write_byte(pgm, p, mem, uaddr, 0xff) < 0) + return LIBAVRDUDE_GENERAL_FAILURE; + } else { + if(!pgm->page_erase || pgm->page_erase(pgm, p, mem, uaddr) < 0) + return LIBAVRDUDE_GENERAL_FAILURE; + } AVR_Cache *cp = avr_mem_is_eeprom_type(mem)? pgm->cp_eeprom: pgm->cp_flash; From 8a3864d2639c97b03a57b685c96aa52ef32290a9 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 12 Oct 2022 15:53:54 +0100 Subject: [PATCH 2/3] Fall back on bytewise r/w if paged access fails for avr cache --- src/avrcache.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/avrcache.c b/src/avrcache.c index ed105f25..aa919584 100644 --- a/src/avrcache.c +++ b/src/avrcache.c @@ -32,7 +32,7 @@ #include "avrintel.h" /* - * Provides an API for cached byte-wise access + * Provides an API for cached bytewise access * * int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const * AVRMEM *mem, unsigned long addr, unsigned char *value); @@ -52,8 +52,8 @@ * avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged * routines are available and if the device memory is EEPROM or flash, * otherwise they fall back to pgm->read_byte() and pgm->write_byte(), - * respectively. Byte-wise cached read always gets its data from the cache, - * possibly after reading a page from the device memory. Byte-wise cached + * respectively. Bytewise cached read always gets its data from the cache, + * possibly after reading a page from the device memory. Bytewise cached * write with an address in memory range only ever modifies the cache. Any * modifications are written to the device after calling avr_flush_cache() or * when attempting to read or write from a location outside the address range @@ -131,6 +131,7 @@ int avr_has_paged_access(const PROGRAMMER *pgm, const AVRMEM *mem) { * - Caller to ensure buf has mem->page_size bytes * - Part memory buffer mem is unaffected by this (though temporarily changed) * - Uses read_byte() if memory page size is one, otherwise paged_load() + * - Fall back to bytewise read if paged_load() returned an error */ int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, unsigned char *buf) { if(!avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size) @@ -146,6 +147,18 @@ int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM if((rc = pgm->paged_load(pgm, p, mem, pgsize, off, pgsize)) >= 0) memcpy(buf, mem->buf + off, pgsize); memcpy(mem->buf + off, pagecopy, pgsize); + + if(rc < 0) { + rc = LIBAVRDUDE_SUCCESS; + for(int i=0; iread_byte(pgm, p, mem, off+i, pagecopy+i) < 0) { + rc = LIBAVRDUDE_GENERAL_FAILURE; + break; + } + } + if(rc == LIBAVRDUDE_SUCCESS) + memcpy(buf, pagecopy, pgsize); + } free(pagecopy); return rc; @@ -248,13 +261,20 @@ static int loadCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, static int writeCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int base, int nlOnErr) { - // Write modified page cont to device + // Write modified page cont to device; if unsuccessful try bytewise access if(avr_write_page_default(pgm, p, mem, base, cp->cont + base) < 0) { - report_progress(1, -1, NULL); - if(nlOnErr && quell_progress) - avrdude_message(MSG_INFO, "\n"); - avrdude_message(MSG_INFO, "%s: writeCachePage() %s write error at addr 0x%04x\n", progname, mem->desc, base); - return LIBAVRDUDE_GENERAL_FAILURE; + for(int i=0; i < cp->page_size; i++) + if(cp->cont[base+i] != cp->copy[base+i]) + if(pgm->write_byte(pgm, p, mem, base+i, cp->cont[base+i]) < 0 || + pgm->read_byte(pgm, p, mem, base+i, cp->copy+base+i) < 0) { + report_progress(1, -1, NULL); + if(nlOnErr && quell_progress) + avrdude_message(MSG_INFO, "\n"); + avrdude_message(MSG_INFO, "%s: writeCachePage() %s access error at addr 0x%04x\n", progname, mem->desc, base+i); + return LIBAVRDUDE_GENERAL_FAILURE; + } + + return LIBAVRDUDE_SUCCESS; // Bytewise writes & reads successful } // Read page back from device and update copy to what is on device if(avr_read_page_default(pgm, p, mem, base, cp->copy + base) < 0) { From 714c2fbf959253f4b03106e39d9a2ec140db8ceb Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Wed, 12 Oct 2022 15:55:22 +0100 Subject: [PATCH 3/3] Rename variable for clarity in avrcache.c --- src/avrcache.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/avrcache.c b/src/avrcache.c index aa919584..23563036 100644 --- a/src/avrcache.c +++ b/src/avrcache.c @@ -137,21 +137,21 @@ int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM if(!avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size) return LIBAVRDUDE_GENERAL_FAILURE; - int rc, pgsize = mem->page_size, off = addr & ~(pgsize-1); + int rc, pgsize = mem->page_size, base = addr & ~(pgsize-1); unsigned char *pagecopy = cfg_malloc("avr_read_page_default()", pgsize); if(pgsize == 1) return pgm->read_byte(pgm, p, mem, addr, buf); - memcpy(pagecopy, mem->buf + off, pgsize); - if((rc = pgm->paged_load(pgm, p, mem, pgsize, off, pgsize)) >= 0) - memcpy(buf, mem->buf + off, pgsize); - memcpy(mem->buf + off, pagecopy, pgsize); + memcpy(pagecopy, mem->buf + base, pgsize); + if((rc = pgm->paged_load(pgm, p, mem, pgsize, base, pgsize)) >= 0) + memcpy(buf, mem->buf + base, pgsize); + memcpy(mem->buf + base, pagecopy, pgsize); if(rc < 0) { rc = LIBAVRDUDE_SUCCESS; for(int i=0; iread_byte(pgm, p, mem, off+i, pagecopy+i) < 0) { + if(pgm->read_byte(pgm, p, mem, base+i, pagecopy+i) < 0) { rc = LIBAVRDUDE_GENERAL_FAILURE; break; } @@ -175,16 +175,16 @@ int avr_write_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM if(!avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size) return LIBAVRDUDE_GENERAL_FAILURE; - int rc, pgsize = mem->page_size, off = addr & ~(pgsize-1); + int rc, pgsize = mem->page_size, base = addr & ~(pgsize-1); unsigned char *pagecopy = cfg_malloc("avr_write_page_default()", pgsize); if(pgsize == 1) return pgm->write_byte(pgm, p, mem, addr, *data); - memcpy(pagecopy, mem->buf + off, pgsize); - memcpy(mem->buf + off, data, pgsize); - rc = pgm->paged_write(pgm, p, mem, pgsize, off, pgsize); - memcpy(mem->buf + off, pagecopy, pgsize); + memcpy(pagecopy, mem->buf + base, pgsize); + memcpy(mem->buf + base, data, pgsize); + rc = pgm->paged_write(pgm, p, mem, pgsize, base, pgsize); + memcpy(mem->buf + base, pagecopy, pgsize); free(pagecopy); return rc;