Pad pages with input file contents before avr_write()
This commit is contained in:
parent
883d9494c8
commit
25ca91371d
109
src/avr.c
109
src/avr.c
|
@ -828,12 +828,13 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
|
||||||
wsize = m->size;
|
wsize = m->size;
|
||||||
if (size < wsize) {
|
if (size < wsize) {
|
||||||
wsize = size;
|
wsize = size;
|
||||||
}
|
} else if (size > wsize) {
|
||||||
else if (size > wsize) {
|
|
||||||
pmsg_warning("%d bytes requested, but memory region is only %d bytes\n", size, wsize);
|
pmsg_warning("%d bytes requested, but memory region is only %d bytes\n", size, wsize);
|
||||||
imsg_warning("Only %d bytes will actually be written\n", wsize);
|
imsg_warning("Only %d bytes will actually be written\n", wsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(wsize <= 0)
|
||||||
|
return wsize;
|
||||||
|
|
||||||
if ((p->prog_modes & PM_TPI) && m->page_size > 1 && pgm->cmd_tpi) {
|
if ((p->prog_modes & PM_TPI) && m->page_size > 1 && pgm->cmd_tpi) {
|
||||||
unsigned int chunk; /* number of words for each write command */
|
unsigned int chunk; /* number of words for each write command */
|
||||||
|
@ -901,50 +902,114 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
|
||||||
/*
|
/*
|
||||||
* the programmer supports a paged mode write
|
* the programmer supports a paged mode write
|
||||||
*/
|
*/
|
||||||
int need_write, failure;
|
int need_write, failure, nset;
|
||||||
unsigned int pageaddr;
|
unsigned int pageaddr;
|
||||||
unsigned int npages, nwritten;
|
unsigned int npages, nwritten;
|
||||||
|
|
||||||
/* quickly scan number of pages to be written to first */
|
/*
|
||||||
for (pageaddr = 0, npages = 0;
|
* Not all paged memory looks like NOR memory to AVRDUDE, particularly
|
||||||
pageaddr < wsize;
|
* - EEPROM
|
||||||
pageaddr += m->page_size) {
|
* - when talking to a bootloader
|
||||||
/* check whether this page must be written to */
|
* - handling write via a part-programmer combo that can do page erase
|
||||||
for (i = pageaddr;
|
*
|
||||||
i < pageaddr + m->page_size;
|
* Hence, read in from the chip all pages with holes to fill them in. The
|
||||||
i++)
|
* small cost of doing so is outweighed by the benefit of not potentially
|
||||||
if ((m->tags[i] & TAG_ALLOCATED) != 0) {
|
* overwriting bytes with 0xff outside the input file.
|
||||||
|
*
|
||||||
|
* Also consider that the effective page size for *SPM* erasing of parts
|
||||||
|
* can be 4 times the page size for SPM writing (eg, ATtiny1634). Thus
|
||||||
|
* ensure the holes cover the effective page size for SPM programming.
|
||||||
|
* Benefits -c arduino with input files with holes on 4-page-erase parts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
AVRMEM *cm = avr_dup_mem(m);
|
||||||
|
|
||||||
|
// Establish and sanity check effective page size
|
||||||
|
int pgsize = (pgm->prog_modes & PM_SPM) && p->n_page_erase > 0?
|
||||||
|
p->n_page_erase*cm->page_size: cm->page_size;
|
||||||
|
if((pgsize & (pgsize-1)) || pgsize < 1) {
|
||||||
|
pmsg_error("effective page size %d implausible\n", pgsize);
|
||||||
|
avr_free_mem(cm);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *spc = cfg_malloc(__func__, cm->page_size);
|
||||||
|
|
||||||
|
// Set cwsize as rounded-up wsize
|
||||||
|
int cwsize = (wsize + pgsize-1)/pgsize*pgsize;
|
||||||
|
|
||||||
|
for(pageaddr = 0; pageaddr < (unsigned int) cwsize; pageaddr += pgsize) {
|
||||||
|
for(i = pageaddr, nset = 0; i < pageaddr + pgsize; i++)
|
||||||
|
if(cm->tags[i] & TAG_ALLOCATED)
|
||||||
|
nset++;
|
||||||
|
|
||||||
|
if(nset && nset != pgsize) { // Effective page has holes
|
||||||
|
for(int np=0; np < pgsize/cm->page_size; np++) { // page by page
|
||||||
|
unsigned int beg = pageaddr + np*cm->page_size;
|
||||||
|
unsigned int end = beg + cm->page_size;
|
||||||
|
|
||||||
|
for(i = beg; i < end; i++)
|
||||||
|
if(!(cm->tags[i] & TAG_ALLOCATED))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(i >= end) // Memory page has no holes
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Read flash contents to separate memory spc and fill in holes
|
||||||
|
if(avr_read_page_default(pgm, p, cm, beg, spc) == 0) {
|
||||||
|
pmsg_notice2("padding %s [0x%04x, 0x%04x]\n", cm->desc, beg, end-1);
|
||||||
|
for(i = beg; i < end; i++)
|
||||||
|
if(!(cm->tags[i] & TAG_ALLOCATED)) {
|
||||||
|
cm->tags[i] |= TAG_ALLOCATED;
|
||||||
|
cm->buf[i] = spc[i-beg];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pmsg_notice2("cannot read %s [0x%04x, 0x%04x] to pad page\n",
|
||||||
|
cm->desc, beg, end-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quickly scan number of pages to be written to
|
||||||
|
for(pageaddr = 0, npages = 0; pageaddr < (unsigned int) cwsize; pageaddr += cm->page_size) {
|
||||||
|
for(i = pageaddr; i < pageaddr + cm->page_size; i++)
|
||||||
|
if(cm->tags[i] & TAG_ALLOCATED) {
|
||||||
npages++;
|
npages++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pageaddr = 0, failure = 0, nwritten = 0;
|
for (pageaddr = 0, failure = 0, nwritten = 0;
|
||||||
!failure && pageaddr < wsize;
|
!failure && pageaddr < (unsigned int) cwsize;
|
||||||
pageaddr += m->page_size) {
|
pageaddr += cm->page_size) {
|
||||||
/* check whether this page must be written to */
|
|
||||||
for (i = pageaddr, need_write = 0;
|
// Check whether this page must be written to
|
||||||
i < pageaddr + m->page_size;
|
for (i = pageaddr, need_write = 0; i < pageaddr + cm->page_size; i++)
|
||||||
i++)
|
if ((cm->tags[i] & TAG_ALLOCATED) != 0) {
|
||||||
if ((m->tags[i] & TAG_ALLOCATED) != 0) {
|
|
||||||
need_write = 1;
|
need_write = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_write) {
|
if (need_write) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
if (auto_erase)
|
if (auto_erase)
|
||||||
rc = pgm->page_erase(pgm, p, m, pageaddr);
|
rc = pgm->page_erase(pgm, p, cm, pageaddr);
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
rc = pgm->paged_write(pgm, p, m, m->page_size, pageaddr, m->page_size);
|
rc = pgm->paged_write(pgm, p, cm, cm->page_size, pageaddr, cm->page_size);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
/* paged write failed, fall back to byte-at-a-time write below */
|
/* paged write failed, fall back to byte-at-a-time write below */
|
||||||
failure = 1;
|
failure = 1;
|
||||||
} else {
|
} else {
|
||||||
pmsg_debug("avr_write_mem(): skipping page %u: no interesting data\n", pageaddr / m->page_size);
|
pmsg_debug("avr_write_mem(): skipping page %u: no interesting data\n", pageaddr / cm->page_size);
|
||||||
}
|
}
|
||||||
nwritten++;
|
nwritten++;
|
||||||
report_progress(nwritten, npages, NULL);
|
report_progress(nwritten, npages, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
avr_free_mem(cm);
|
||||||
|
free(spc);
|
||||||
|
|
||||||
if (!failure)
|
if (!failure)
|
||||||
return wsize;
|
return wsize;
|
||||||
/* else: fall back to byte-at-a-time write, for historical reasons */
|
/* else: fall back to byte-at-a-time write, for historical reasons */
|
||||||
|
|
Loading…
Reference in New Issue