Submitted by Jan Egil Ruud <janegil.ruud@microchip.com>

patch #9507: Fix UPDI chip erase
* libavrdude.h (PROGRAMMER): add unlock method
* avr.c (avr_unlock): Generic unlock function
* jtag3.c: Implement unlock feature; avoid calling
jtag3_edbg_prepare() and jtag3_edbg_signoff() on XplainedMini
boards to work around a bug in early firmware versions;
implement "userrow" memory region
* main.c: Call avr_unlock() rather than avr_chip_erase() when
encountering a locked UPDI chip



git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1417 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
joerg_wunsch 2018-01-16 21:17:04 +00:00
parent b79d8b1cfb
commit d32c587511
5 changed files with 87 additions and 25 deletions

View File

@ -1,3 +1,16 @@
2018-01-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jan Egil Ruud <janegil.ruud@microchip.com>
patch #9507: Fix UPDI chip erase
* libavrdude.h (PROGRAMMER): add unlock method
* avr.c (avr_unlock): Generic unlock function
* jtag3.c: Implement unlock feature; avoid calling
jtag3_edbg_prepare() and jtag3_edbg_signoff() on XplainedMini
boards to work around a bug in early firmware versions;
implement "userrow" memory region
* main.c: Call avr_unlock() rather than avr_chip_erase() when
encountering a locked UPDI chip
2018-01-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de> 2018-01-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Nicolas BRULEZ Submitted by Nicolas BRULEZ

10
avr.c
View File

@ -1195,6 +1195,16 @@ int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p)
return rc; return rc;
} }
int avr_unlock(PROGRAMMER * pgm, AVRPART * p)
{
int rc = -1;
if (pgm->unlock)
rc = pgm->unlock(pgm, p);
return rc;
}
/* /*
* Report the progress of a read or write operation from/to the * Report the progress of a read or write operation from/to the
* device. * device.

80
jtag3.c
View File

@ -864,10 +864,15 @@ int jtag3_getsync(PROGRAMMER * pgm, int mode) {
avrdude_message(MSG_DEBUG, "%s: jtag3_getsync()\n", progname); avrdude_message(MSG_DEBUG, "%s: jtag3_getsync()\n", progname);
/* XplainedMini boards do not need this, and early revisions had a
* firmware bug where they complained about it. */
if (pgm->flag & PGM_FL_IS_EDBG) { if (pgm->flag & PGM_FL_IS_EDBG) {
if (jtag3_edbg_prepare(pgm) < 0) if (strcmp(pgm->id, "xplainedmini_updi") != 0) {
if (jtag3_edbg_prepare(pgm) < 0) {
return -1; return -1;
} }
}
}
/* Get the sign-on information. */ /* Get the sign-on information. */
buf[0] = SCOPE_GENERAL; buf[0] = SCOPE_GENERAL;
@ -903,9 +908,9 @@ static int jtag3_chip_erase(PROGRAMMER * pgm, AVRPART * p)
} }
/* /*
* UPDI 'chip erase' -> 'enter progmode' with chip erase key * UPDI 'unlock' -> 'enter progmode' with chip erase key
*/ */
static int jtag3_chip_erase_updi(PROGRAMMER * pgm, AVRPART * p) static int jtag3_unlock_erase_key(PROGRAMMER * pgm, AVRPART * p)
{ {
unsigned char buf[8], *resp; unsigned char buf[8], *resp;
@ -1573,8 +1578,13 @@ void jtag3_close(PROGRAMMER * pgm)
if (jtag3_command(pgm, buf, 4, &resp, "sign-off") >= 0) if (jtag3_command(pgm, buf, 4, &resp, "sign-off") >= 0)
free(resp); free(resp);
if (pgm->flag & PGM_FL_IS_EDBG) /* XplainedMini boards do not need this, and early revisions had a
* firmware bug where they complained about it. */
if (pgm->flag & PGM_FL_IS_EDBG) {
if (strcmp(pgm->id, "xplainedmini_updi") != 0) {
jtag3_edbg_signoff(pgm); jtag3_edbg_signoff(pgm);
}
}
serial_close(&pgm->fd); serial_close(&pgm->fd);
pgm->fd.ifd = -1; pgm->fd.ifd = -1;
@ -1636,8 +1646,13 @@ static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int status, dynamic_memtype = 0; int status, dynamic_memtype = 0;
long otimeout = serial_recv_timeout; long otimeout = serial_recv_timeout;
avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(.., %s, %d, %d)\n", avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(.., %s, %d, 0x%lx, %d)\n",
progname, m->desc, page_size, n_bytes); progname, m->desc, page_size, addr, n_bytes);
block_size = jtag3_memaddr(pgm, p, m, addr);
if(block_size != addr)
avrdude_message(MSG_NOTICE2, " mapped to address: 0x%lx\n", block_size);
block_size = 0;
if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0) if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0)
return -1; return -1;
@ -1679,6 +1694,8 @@ static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
} else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
cmd[3] = MTYPE_USERSIG; cmd[3] = MTYPE_USERSIG;
} else if ( ( strcmp(m->desc, "userrow") == 0 ) ) {
cmd[3] = MTYPE_USERSIG;
} else if ( ( strcmp(m->desc, "boot") == 0 ) ) { } else if ( ( strcmp(m->desc, "boot") == 0 ) ) {
cmd[3] = MTYPE_BOOT_FLASH; cmd[3] = MTYPE_BOOT_FLASH;
} else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) { } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
@ -1740,8 +1757,13 @@ static int jtag3_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int status, dynamic_memtype = 0; int status, dynamic_memtype = 0;
long otimeout = serial_recv_timeout; long otimeout = serial_recv_timeout;
avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_load(.., %s, %d, %d)\n", avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_load(.., %s, %d, 0x%lx, %d)\n",
progname, m->desc, page_size, n_bytes); progname, m->desc, page_size, addr, n_bytes);
block_size = jtag3_memaddr(pgm, p, m, addr);
if(block_size != addr)
avrdude_message(MSG_NOTICE2, " mapped to address: 0x%lx\n", block_size);
block_size = 0;
if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0) if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0)
return -1; return -1;
@ -1765,6 +1787,8 @@ static int jtag3_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[3] = MTYPE_PRODSIG; cmd[3] = MTYPE_PRODSIG;
} else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
cmd[3] = MTYPE_USERSIG; cmd[3] = MTYPE_USERSIG;
} else if ( ( strcmp(m->desc, "userrow") == 0 ) ) {
cmd[3] = MTYPE_USERSIG;
} else if ( ( strcmp(m->desc, "boot") == 0 ) ) { } else if ( ( strcmp(m->desc, "boot") == 0 ) ) {
cmd[3] = MTYPE_BOOT_FLASH; cmd[3] = MTYPE_BOOT_FLASH;
} else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) { } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
@ -1819,6 +1843,11 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
avrdude_message(MSG_NOTICE2, "%s: jtag3_read_byte(.., %s, 0x%lx, ...)\n", avrdude_message(MSG_NOTICE2, "%s: jtag3_read_byte(.., %s, 0x%lx, ...)\n",
progname, mem->desc, addr); progname, mem->desc, addr);
paddr = jtag3_memaddr(pgm, p, mem, addr);
if(paddr != addr)
avrdude_message(MSG_NOTICE2, " mapped to address: 0x%lx\n", paddr);
paddr = 0;
if (!(pgm->flag & PGM_FL_IS_DW)) if (!(pgm->flag & PGM_FL_IS_DW))
if ((status = jtag3_program_enable(pgm)) < 0) if ((status = jtag3_program_enable(pgm)) < 0)
return status; return status;
@ -1828,8 +1857,6 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
cmd[2] = 0; cmd[2] = 0;
cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE; cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE;
if (p->flags & AVRPART_HAS_UPDI)
addr += mem->offset;
if (strcmp(mem->desc, "flash") == 0 || if (strcmp(mem->desc, "flash") == 0 ||
strcmp(mem->desc, "application") == 0 || strcmp(mem->desc, "application") == 0 ||
strcmp(mem->desc, "apptable") == 0 || strcmp(mem->desc, "apptable") == 0 ||
@ -1874,6 +1901,8 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
addr = mem->offset & 7; addr = mem->offset & 7;
} else if (strcmp(mem->desc, "usersig") == 0) { } else if (strcmp(mem->desc, "usersig") == 0) {
cmd[3] = MTYPE_USERSIG; cmd[3] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "userrow") == 0) {
cmd[3] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "prodsig") == 0) { } else if (strcmp(mem->desc, "prodsig") == 0) {
cmd[3] = MTYPE_PRODSIG; cmd[3] = MTYPE_PRODSIG;
} else if (strcmp(mem->desc, "calibration") == 0) { } else if (strcmp(mem->desc, "calibration") == 0) {
@ -1892,11 +1921,7 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
* harm for other connection types either. * harm for other connection types either.
*/ */
u32_to_b4(cmd + 8, 3); u32_to_b4(cmd + 8, 3);
u32_to_b4(cmd + 4, mem->offset); u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
if (p->flags & AVRPART_HAS_UPDI){
addr -= mem->offset;
}
if (addr == 0) { if (addr == 0) {
if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0) if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
@ -1942,10 +1967,11 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
if (pagesize) { if (pagesize) {
u32_to_b4(cmd + 8, pagesize); u32_to_b4(cmd + 8, pagesize);
u32_to_b4(cmd + 4, paddr); u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, paddr));
} else { } else {
u32_to_b4(cmd + 8, 1); u32_to_b4(cmd + 8, 1);
u32_to_b4(cmd + 4, addr); u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
} }
if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0) if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
@ -1978,16 +2004,19 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned char *cache_ptr = 0; unsigned char *cache_ptr = 0;
int status, unsupp = 0; int status, unsupp = 0;
unsigned int pagesize = 0; unsigned int pagesize = 0;
unsigned long mapped_addr;
avrdude_message(MSG_NOTICE2, "%s: jtag3_write_byte(.., %s, 0x%lx, ...)\n", avrdude_message(MSG_NOTICE2, "%s: jtag3_write_byte(.., %s, 0x%lx, ...)\n",
progname, mem->desc, addr); progname, mem->desc, addr);
mapped_addr = jtag3_memaddr(pgm, p, mem, addr);
if(mapped_addr != addr)
avrdude_message(MSG_NOTICE2, " mapped to address: 0x%lx\n", mapped_addr);
cmd[0] = SCOPE_AVR; cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_WRITE_MEMORY; cmd[1] = CMD3_WRITE_MEMORY;
cmd[2] = 0; cmd[2] = 0;
cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_SPM; cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_SPM;
if (p->flags & AVRPART_HAS_UPDI)
addr += mem->offset;
if (strcmp(mem->desc, "flash") == 0) { if (strcmp(mem->desc, "flash") == 0) {
cache_ptr = PDATA(pgm)->flash_pagecache; cache_ptr = PDATA(pgm)->flash_pagecache;
pagesize = PDATA(pgm)->flash_pagesize; pagesize = PDATA(pgm)->flash_pagesize;
@ -2070,7 +2099,7 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
return -1; return -1;
u32_to_b4(cmd + 8, 1); u32_to_b4(cmd + 8, 1);
u32_to_b4(cmd + 4, addr); u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
cmd[12] = 0; cmd[12] = 0;
cmd[13] = data; cmd[13] = data;
@ -2325,7 +2354,13 @@ static unsigned int jtag3_memaddr(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, uns
* Non-Xmega device. * Non-Xmega device.
*/ */
if (p->flags & AVRPART_HAS_UPDI) { if (p->flags & AVRPART_HAS_UPDI) {
if (strcmp(m->desc, "flash") != 0) { if (strcmp(m->desc, "fuses") == 0) {
addr += m->offset;
}
else if (strncmp(m->desc, "fuse", strlen("fuse")) == 0) {
addr = m->offset;
}
else if (strcmp(m->desc, "flash") != 0) {
addr += m->offset; addr += m->offset;
} }
} }
@ -2448,7 +2483,7 @@ void jtag3_updi_initpgm(PROGRAMMER * pgm)
pgm->enable = jtag3_enable; pgm->enable = jtag3_enable;
pgm->disable = jtag3_disable; pgm->disable = jtag3_disable;
pgm->program_enable = jtag3_program_enable_dummy; pgm->program_enable = jtag3_program_enable_dummy;
pgm->chip_erase = jtag3_chip_erase_updi; pgm->chip_erase = jtag3_chip_erase;
pgm->open = jtag3_open_updi; pgm->open = jtag3_open_updi;
pgm->close = jtag3_close; pgm->close = jtag3_close;
pgm->read_byte = jtag3_read_byte; pgm->read_byte = jtag3_read_byte;
@ -2466,6 +2501,7 @@ void jtag3_updi_initpgm(PROGRAMMER * pgm)
pgm->teardown = jtag3_teardown; pgm->teardown = jtag3_teardown;
pgm->page_size = 256; pgm->page_size = 256;
pgm->flag = PGM_FL_IS_UPDI; pgm->flag = PGM_FL_IS_UPDI;
pgm->unlock = jtag3_unlock_erase_key;
pgm->read_sib = jtag3_read_sib; pgm->read_sib = jtag3_read_sib;
} }

View File

@ -647,6 +647,7 @@ typedef struct programmer_t {
void (*powerdown) (struct programmer_t * pgm); void (*powerdown) (struct programmer_t * pgm);
int (*program_enable) (struct programmer_t * pgm, AVRPART * p); int (*program_enable) (struct programmer_t * pgm, AVRPART * p);
int (*chip_erase) (struct programmer_t * pgm, AVRPART * p); int (*chip_erase) (struct programmer_t * pgm, AVRPART * p);
int (*unlock) (struct programmer_t * pgm, AVRPART * p);
int (*cmd) (struct programmer_t * pgm, const unsigned char *cmd, int (*cmd) (struct programmer_t * pgm, const unsigned char *cmd,
unsigned char *res); unsigned char *res);
int (*cmd_tpi) (struct programmer_t * pgm, const unsigned char *cmd, int (*cmd_tpi) (struct programmer_t * pgm, const unsigned char *cmd,
@ -764,6 +765,8 @@ int avr_mem_hiaddr(AVRMEM * mem);
int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p); int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p);
int avr_unlock(PROGRAMMER * pgm, AVRPART * p);
void report_progress (int completed, int total, char *hdr); void report_progress (int completed, int total, char *hdr);
#ifdef __cplusplus #ifdef __cplusplus

2
main.c
View File

@ -1077,7 +1077,7 @@ int main(int argc, char * argv [])
if (quell_progress < 2) { if (quell_progress < 2) {
avrdude_message(MSG_INFO, "%s: erasing chip\n", progname); avrdude_message(MSG_INFO, "%s: erasing chip\n", progname);
} }
exitrc = avr_chip_erase(pgm, p); exitrc = avr_unlock(pgm, p);
if(exitrc) goto main_exit; if(exitrc) goto main_exit;
goto sig_again; goto sig_again;
} }