Ensure full words are loaded, low-byte first, for ISP programming (#1265)

This commit is contained in:
Stefan Rueger 2023-01-05 16:43:35 +00:00 committed by GitHub
parent 5328b798e4
commit 653d66b014
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 25 additions and 42 deletions

View File

@ -843,7 +843,6 @@ int avr_write(const PROGRAMMER *pgm, const AVRPART *p, const char *memtype, int
*/ */
int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int size, int auto_erase) { int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int size, int auto_erase) {
int rc; int rc;
int newpage, page_tainted, flush_page, do_write;
int wsize; int wsize;
unsigned int i, lastaddr; unsigned int i, lastaddr;
unsigned char data; unsigned char data;
@ -1044,51 +1043,42 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
/* else: fall back to byte-at-a-time write, for historical reasons */ /* else: fall back to byte-at-a-time write, for historical reasons */
} }
if (pgm->write_setup) { // ISP programming from now on; flash will look like NOR-memory
pgm->write_setup(pgm, p, m); if (pgm->write_setup)
} pgm->write_setup(pgm, p, m);
newpage = 1; int page_tainted = 0;
page_tainted = 0; int flush_page = 0;
flush_page = 0; int paged = avr_mem_is_flash_type(m) && m->paged;
if(paged)
wsize = (wsize+1)/2*2; // Round up write size for word boundary
for (i = 0; i < (unsigned int) wsize; i++) { for (i = 0; i < (unsigned int) wsize; i++) {
data = m->buf[i]; data = m->buf[i];
report_progress(i, wsize, NULL); report_progress(i, wsize, NULL);
/* /*
* Find out whether the write action must be invoked for this * Find out whether the write action must be invoked for this byte.
* byte.
* *
* For non-paged memory, this only happens if TAG_ALLOCATED is * For non-paged memory, this means the byte is set to TAG_ALLOCATED.
* set for the byte.
* *
* For paged memory, TAG_ALLOCATED also invokes the write * For paged memory, TAG_ALLOCATED also invokes loading the associated
* operation, which is actually a page buffer fill only. This * full word, low-byte first, into the device page buffer as required by
* "taints" the page, and upon encountering the last byte of each * ISP page programming. This "taints" the page, and upon encountering
* tainted page, the write operation must also be invoked in order * the last byte of each tainted page, the write operation must also be
* to actually write the page buffer to memory. * invoked in order to actually write the page buffer to device memory.
*/ */
do_write = (m->tags[i] & TAG_ALLOCATED) != 0; int do_write = (paged? m->tags[i&~1] | m->tags[i|1]: m->tags[i]) & TAG_ALLOCATED;
if (m->paged) { if (paged) {
if (newpage) { page_tainted |= do_write;
page_tainted = do_write; if ((int) i % m->page_size == m->page_size - 1 || (int) i == wsize - 1) {
} else {
page_tainted |= do_write;
}
if (i % m->page_size == (unsigned int) m->page_size - 1 ||
i == (unsigned int) wsize - 1) {
/* last byte this page */
flush_page = page_tainted; flush_page = page_tainted;
newpage = 1; page_tainted = 0;
} else {
flush_page = newpage = 0;
} }
} }
if (!do_write && !flush_page) { if (!do_write && !flush_page)
continue; continue;
}
if (do_write) { if (do_write) {
rc = avr_write_byte(pgm, p, m, i, data); rc = avr_write_byte(pgm, p, m, i, data);
@ -1099,11 +1089,8 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
} }
} }
/* if (flush_page) { // Time to flush the page with a page write
* check to see if it is time to flush the page with a page flush_page = 0;
* write
*/
if (flush_page) {
rc = avr_write_page(pgm, p, m, i); rc = avr_write_page(pgm, p, m, i);
if (rc) { if (rc) {
msg_error(" *** page %d (addresses 0x%04x - 0x%04x) failed to write\n\n", msg_error(" *** page %d (addresses 0x%04x - 0x%04x) failed to write\n\n",
@ -1113,13 +1100,9 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
} }
} }
if (werror) { // Ensure error led stays on lest it was cleared in avr_write_byte()
/* if (werror)
* make sure the error led stay on if there was a previous write
* error, otherwise it gets cleared in avr_write_byte()
*/
pgm->err_led(pgm, ON); pgm->err_led(pgm, ON);
}
} }
return i; return i;