Handle n_page_erase in urclock for parts t441, t841 and t1634
This commit is contained in:
parent
6e3a99be87
commit
b178deef5f
|
@ -71,7 +71,7 @@
|
||||||
# prog_modes = PM_<i/f> {| PM_<i/f>} # interfaces, eg, PM_SPM|PM_ISP|PM_HVPP|PM_debugWIRE
|
# prog_modes = PM_<i/f> {| PM_<i/f>} # interfaces, eg, PM_SPM|PM_ISP|PM_HVPP|PM_debugWIRE
|
||||||
# mcuid = <num>; # unique id in 0..2039 for 8-bit AVRs
|
# mcuid = <num>; # unique id in 0..2039 for 8-bit AVRs
|
||||||
# n_interrupts = <num>; # number of interrupts, used for vector bootloaders
|
# n_interrupts = <num>; # number of interrupts, used for vector bootloaders
|
||||||
# n_page_erase = <num>; # if set, number of pages erased during NVM erase
|
# n_page_erase = <num>; # if set, number of pages erased during SPM erase
|
||||||
# hvupdi_variant = <num> ; # numeric -1 (n/a) or 0..2
|
# hvupdi_variant = <num> ; # numeric -1 (n/a) or 0..2
|
||||||
# devicecode = <num> ; # deprecated, use stk500_devcode
|
# devicecode = <num> ; # deprecated, use stk500_devcode
|
||||||
# stk500_devcode = <num> ; # numeric
|
# stk500_devcode = <num> ; # numeric
|
||||||
|
|
|
@ -1860,7 +1860,7 @@ part
|
||||||
prog_modes = PM_<i/f> @{| PM_<i/f>@} # interfaces, eg, PM_SPM|PM_ISP|PM_HVPP|PM_debugWIRE
|
prog_modes = PM_<i/f> @{| PM_<i/f>@} # interfaces, eg, PM_SPM|PM_ISP|PM_HVPP|PM_debugWIRE
|
||||||
mcuid = <num>; # unique id in 0..2039 for 8-bit AVRs
|
mcuid = <num>; # unique id in 0..2039 for 8-bit AVRs
|
||||||
n_interrupts = <num>; # number of interrupts, used for vector bootloaders
|
n_interrupts = <num>; # number of interrupts, used for vector bootloaders
|
||||||
n_page_erase = <num>; # if set, number of pages erased during NVM erase
|
n_page_erase = <num>; # if set, number of pages erased during SPM erase
|
||||||
hvupdi_variant = <num> ; # numeric -1 (n/a) or 0..2
|
hvupdi_variant = <num> ; # numeric -1 (n/a) or 0..2
|
||||||
devicecode = <num> ; # deprecated, use stk500_devcode
|
devicecode = <num> ; # deprecated, use stk500_devcode
|
||||||
stk500_devcode = <num> ; # numeric
|
stk500_devcode = <num> ; # numeric
|
||||||
|
|
145
src/urclock.c
145
src/urclock.c
|
@ -757,55 +757,8 @@ nopatch_nometa:
|
||||||
ur.emulate_ce = 0;
|
ur.emulate_ce = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ur.done_ce) { // Unless chip erase was just issued (where all mem is 0xff)
|
|
||||||
if((ur.urprotocol && !(ur.urfeatures & UB_FLASH_LL_NOR)) ||
|
|
||||||
ur.bloptiversion ||
|
|
||||||
(ur.blurversion && ur.blurversion < 076)) {
|
|
||||||
|
|
||||||
int ai, addr, nset;
|
// Ensure that vector bootloaders have correct r/jmp at address 0
|
||||||
|
|
||||||
// Scan the memory for pages with unset bytes and read these bytes from current chip flash
|
|
||||||
uint8_t spc[2048];
|
|
||||||
|
|
||||||
for(addr = 0; addr < maxsize; addr += ur.uP.pagesize) {
|
|
||||||
// How many bytes are set in this page?
|
|
||||||
for(ai = addr, nset = 0; ai < addr + ur.uP.pagesize; ai++)
|
|
||||||
if(flm->tags[ai] & TAG_ALLOCATED)
|
|
||||||
nset++;
|
|
||||||
|
|
||||||
// Holes in this page that needs writing? read them in from the chip
|
|
||||||
if(nset && nset != ur.uP.pagesize) {
|
|
||||||
// Identify a covering interval for all holes in page
|
|
||||||
int istart, isize;
|
|
||||||
|
|
||||||
// Lowest address with unset byte
|
|
||||||
for(ai = addr; flm->tags[ai] & TAG_ALLOCATED; ai++)
|
|
||||||
continue;
|
|
||||||
istart = ai;
|
|
||||||
|
|
||||||
// Highest address with unset byte
|
|
||||||
for(ai = addr + ur.uP.pagesize - 1; flm->tags[ai] & TAG_ALLOCATED; ai--)
|
|
||||||
continue;
|
|
||||||
isize = ai - istart + 1;
|
|
||||||
|
|
||||||
if(isize < 1 || isize > (int) sizeof spc) // Should not happen
|
|
||||||
Return("isize=%d out of range (enlarge spc[] and recompile)", isize);
|
|
||||||
|
|
||||||
if(ur_readEF(pgm, p, spc, istart, isize, 'F') == 0) {
|
|
||||||
for(ai = istart; ai < istart + isize; ai++)
|
|
||||||
if(!(flm->tags[ai] & TAG_ALLOCATED))
|
|
||||||
flm->buf[ai] = spc[ai-istart];
|
|
||||||
} else {
|
|
||||||
pmsg_notice2("cannot read flash [0x%04x, 0x%04x] to pad page bytes\n",
|
|
||||||
istart, istart+isize-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ur.done_ce = 0; // From now on can no longer rely on being deleted
|
|
||||||
|
|
||||||
// Last, but not least: ensure that vector bootloaders have correct r/jmp at address 0
|
|
||||||
if(ur.blstart && ur.vbllevel==1) {
|
if(ur.blstart && ur.vbllevel==1) {
|
||||||
int rc, set=0;
|
int rc, set=0;
|
||||||
for(int i=0; i < vecsz; i++)
|
for(int i=0; i < vecsz; i++)
|
||||||
|
@ -829,24 +782,10 @@ nopatch_nometa:
|
||||||
if((rc = ur_readEF(pgm, p, device, 0, vecsz, 'F')) < 0)
|
if((rc = ur_readEF(pgm, p, device, 0, vecsz, 'F')) < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
int changed = 0;
|
|
||||||
for(int i=0; i < vecsz; i++) {
|
for(int i=0; i < vecsz; i++) {
|
||||||
if((flm->tags[i] & TAG_ALLOCATED? flm->buf[i]: device[i]) != jmptoboot[i]) {
|
if((flm->tags[i] & TAG_ALLOCATED? flm->buf[i]: device[i]) != jmptoboot[i]) {
|
||||||
flm->buf[i] = jmptoboot[i];
|
flm->buf[i] = jmptoboot[i];
|
||||||
flm->tags[i] |= TAG_ALLOCATED;
|
flm->tags[i] |= TAG_ALLOCATED;
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If reset vector patched, ensure to fill in the holes in rest of page
|
|
||||||
if(changed && flm->page_size > vecsz && flm->page_size <= sizeof device) {
|
|
||||||
pmsg_warning("patching reset vector to protect vector bootloader\n");
|
|
||||||
if((rc = ur_readEF(pgm, p, device+vecsz, vecsz, flm->page_size - vecsz, 'F')) < 0)
|
|
||||||
return rc;
|
|
||||||
for(int i=vecsz; i < flm->page_size; i++) {
|
|
||||||
if(!(flm->tags[i] & TAG_ALLOCATED)) {
|
|
||||||
flm->buf[i] = jmptoboot[i];
|
|
||||||
flm->tags[i] |= TAG_ALLOCATED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // Flash not readable: patch reset vector
|
} else { // Flash not readable: patch reset vector
|
||||||
|
@ -870,6 +809,88 @@ nopatch_nometa:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Effective page size, can be 4*pagesize for 4-page erase parts
|
||||||
|
int pgsize = p->n_page_erase > 0? p->n_page_erase*ur.uP.pagesize: ur.uP.pagesize;
|
||||||
|
if((pgsize & (pgsize-1)) || pgsize < 1 || pgsize > maxsize || maxsize % pgsize)
|
||||||
|
Return("effective page size %d implausible for size %d below bootloader", pgsize, maxsize);
|
||||||
|
|
||||||
|
if(!ur.done_ce) { // Unless chip erase was just issued (where all mem is 0xff)
|
||||||
|
if((ur.urprotocol && !(ur.urfeatures & UB_FLASH_LL_NOR)) || !ur.urprotocol) {
|
||||||
|
// Scan the memory for eff pages with unset bytes and read these bytes from device flash
|
||||||
|
int ai, npe, addr, nset;
|
||||||
|
|
||||||
|
uint8_t spc[2048];
|
||||||
|
|
||||||
|
for(addr = 0; addr < maxsize; addr += pgsize) {
|
||||||
|
// How many bytes are set in this effective page?
|
||||||
|
for(ai = addr, nset = 0; ai < addr + pgsize; ai++)
|
||||||
|
if(flm->tags[ai] & TAG_ALLOCATED)
|
||||||
|
nset++;
|
||||||
|
|
||||||
|
// Holes in this page that needs writing? read them in from the chip
|
||||||
|
if(nset && nset != pgsize) {
|
||||||
|
for(npe=0; npe < pgsize/ur.uP.pagesize; npe++) {
|
||||||
|
// Identify a covering interval for all holes in page
|
||||||
|
int istart, isize, beg, end;
|
||||||
|
|
||||||
|
beg = addr + npe*ur.uP.pagesize;
|
||||||
|
end = beg + ur.uP.pagesize;
|
||||||
|
|
||||||
|
// Lowest address with unset byte (there might be none)
|
||||||
|
for(ai = beg; ai < end; ai++)
|
||||||
|
if(!(flm->tags[ai] & TAG_ALLOCATED))
|
||||||
|
break;
|
||||||
|
istart = ai;
|
||||||
|
|
||||||
|
if(istart < end) {
|
||||||
|
// Highest address with unset byte
|
||||||
|
for(ai = end - 1; ai >= istart; ai--)
|
||||||
|
if(!(flm->tags[ai] & TAG_ALLOCATED))
|
||||||
|
break;
|
||||||
|
isize = ai - istart + 1;
|
||||||
|
|
||||||
|
if(isize < 1 || isize > (int) sizeof spc) // Should not happen
|
||||||
|
Return("isize=%d out of range (enlarge spc[] and recompile)", isize);
|
||||||
|
|
||||||
|
if(ur_readEF(pgm, p, spc, istart, isize, 'F') == 0) {
|
||||||
|
pmsg_debug("padding [0x%04x, 0x%04x]\n", istart, istart+isize-1);
|
||||||
|
|
||||||
|
for(ai = istart; ai < istart + isize; ai++)
|
||||||
|
if(!(flm->tags[ai] & TAG_ALLOCATED)) {
|
||||||
|
flm->tags[ai] |= TAG_ALLOCATED;
|
||||||
|
flm->buf[ai] = spc[ai-istart];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pmsg_notice2("cannot read flash [0x%04x, 0x%04x] to pad page bytes\n",
|
||||||
|
istart, istart+isize-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ur.done_ce = 0; // From now on can no longer rely on being deleted
|
||||||
|
|
||||||
|
// Fill remaining holes (chip was erased, could not be read or memory looks like NOR memory)
|
||||||
|
int ai, addr, nset;
|
||||||
|
|
||||||
|
for(addr = 0; addr < maxsize; addr += pgsize) {
|
||||||
|
for(ai = addr, nset = 0; ai < addr + pgsize; ai++)
|
||||||
|
if(flm->tags[ai] & TAG_ALLOCATED)
|
||||||
|
nset++;
|
||||||
|
|
||||||
|
if(nset && nset != pgsize) { // Page has holes: fill them
|
||||||
|
pmsg_debug("0xff padding page addr 0x%04d\n", addr);
|
||||||
|
for(ai = addr, nset = 0; ai < addr + pgsize; ai++)
|
||||||
|
if(!(flm->tags[ai] & TAG_ALLOCATED)) {
|
||||||
|
flm->tags[ai] |= TAG_ALLOCATED;
|
||||||
|
flm->buf[ai] = 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue