diff --git a/ChangeLog b/ChangeLog index 4e6d9480..c4d3db7f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2012-05-04 Joerg Wunsch + + Xmega page erase implementation for JTAGICEmkII + * jtagmkII.c: Handle flash pages sizes > 256 bytes, implement + page_erase() method + * avrdude.conf.in: Change flash pagesize for all Xmega devices + to 512 bytes + * avr.c: Implement auto_erase, using page_erase if available + * avr.h: Remove unused parameters from avr_read(), replace + unused parameter in avr_write)() by auto_erase + * stk500v2.c: Handle flash page sizes > 256 bytes + * update.c (do_op): Handle new updateflags parameter + * main.c: Implement auto_erase as page_erase if possible + * update.h (enum updateflags): New enum + * pgm.h (struct programmer_t): Add page_erase method + 2012-04-26 Joerg Wunsch * jtagmkII.c (jtagmkII_paged_load, jtagmkII_paged_write): fix bug diff --git a/NEWS b/NEWS index 2fa590bd..367ef53c 100644 --- a/NEWS +++ b/NEWS @@ -86,6 +86,9 @@ Current: Xmega devices, and "flash" for everything else. This ensures the bootloader is not touched. + * For programmers that support it, the default erase method is a + page erase now, rather than a chip erase (Xmega only). + * Programmers and parts lists They are now sorted at output with '-c ?'/'-p ?'. (patch #7671: diff --git a/avr.c b/avr.c index cd2eb49b..95689513 100644 --- a/avr.c +++ b/avr.c @@ -213,7 +213,7 @@ int avr_mem_hiaddr(AVRMEM * mem) * Return the number of bytes read, or < 0 if an error occurs. */ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, - AVRPART * v, int verb) + AVRPART * v) { unsigned long i, lastaddr; unsigned char cmd[4]; @@ -718,7 +718,7 @@ int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, * Return the number of bytes written, or -1 if an error occurs. */ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, - int verb) + int auto_erase) { int rc; int newpage, page_tainted, flush_page, do_write; @@ -813,6 +813,10 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, break; } if (need_write) { + rc = 0; + if (auto_erase) + rc = pgm->page_erase(pgm, p, m, pageaddr); + if (rc >= 0) rc = pgm->paged_write(pgm, p, m, m->page_size, pageaddr, m->page_size); if (rc < 0) /* paged write failed, fall back to byte-at-a-time write below */ @@ -925,7 +929,7 @@ int avr_signature(PROGRAMMER * pgm, AVRPART * p) int rc; report_progress (0,1,"Reading"); - rc = avr_read(pgm, p, "signature", 0, 0); + rc = avr_read(pgm, p, "signature", 0); if (rc < 0) { fprintf(stderr, "%s: error reading signature data for part \"%s\", rc=%d\n", diff --git a/avr.h b/avr.h index 1a85ed4f..67a2c293 100644 --- a/avr.h +++ b/avr.h @@ -41,8 +41,7 @@ int avr_tpi_poll_nvmbsy(PROGRAMMER *pgm); int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsigned long addr, unsigned char * value); -int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, AVRPART * v, - int verbose); +int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, AVRPART * v); int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsigned long addr); @@ -54,7 +53,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsigned long addr, unsigned char data); int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, - int verbose); + int auto_erase); int avr_signature(PROGRAMMER * pgm, AVRPART * p); diff --git a/avrdude.conf.in b/avrdude.conf.in index 338d7ba2..9cfc4fe2 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -12291,14 +12291,14 @@ part memory "prodsig" size = 0x200; offset = 0x8e0200; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "usersig" size = 0x200; offset = 0x8e0400; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12358,28 +12358,28 @@ part parent ".xmega" memory "application" size = 0x00010000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "apptable" size = 0x00001000; offset = 0x0080f000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "boot" size = 0x00001000; offset = 0x00810000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "flash" size = 0x00011000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12408,28 +12408,28 @@ part parent ".xmega" memory "application" size = 0x00020000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "apptable" size = 0x00002000; offset = 0x0081e000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "boot" size = 0x00002000; offset = 0x00820000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "flash" size = 0x00022000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12468,28 +12468,28 @@ part parent ".xmega" memory "application" size = 0x00030000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "apptable" size = 0x00002000; offset = 0x0082e000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "boot" size = 0x00002000; offset = 0x00830000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "flash" size = 0x00032000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12518,28 +12518,28 @@ part parent ".xmega" memory "application" size = 0x00040000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "apptable" size = 0x00002000; offset = 0x0083e000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "boot" size = 0x00002000; offset = 0x00840000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "flash" size = 0x00042000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12618,14 +12618,14 @@ part parent ".xmega" memory "application" size = 0x00004000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "apptable" size = 0x00001000; offset = 0x00803000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12639,7 +12639,7 @@ part parent ".xmega" memory "flash" size = 0x00005000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12668,28 +12668,28 @@ part parent ".xmega" memory "application" size = 0x00008000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "apptable" size = 0x00001000; offset = 0x00807000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "boot" size = 0x00001000; offset = 0x00808000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "flash" size = 0x00009000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12738,28 +12738,28 @@ part parent ".xmega" memory "application" size = 0x00004000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "apptable" size = 0x00001000; offset = 0x00803000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "boot" size = 0x00001000; offset = 0x00804000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "flash" size = 0x00005000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; ; @@ -12784,28 +12784,28 @@ part parent ".xmega" memory "application" size = 0x00008000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "apptable" size = 0x00001000; offset = 0x00807000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "boot" size = 0x00001000; offset = 0x00808000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "flash" size = 0x00009000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; ; @@ -12830,7 +12830,7 @@ part parent ".xmega" memory "application" size = 0x00010000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12844,14 +12844,14 @@ part parent ".xmega" memory "boot" size = 0x00001000; offset = 0x00810000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; memory "flash" size = 0x00011000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; ; @@ -12876,7 +12876,7 @@ part parent ".xmega" memory "application" size = 0x00020000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12886,7 +12886,7 @@ part parent ".xmega" # XML file also says it's 8 KiB, use this. size = 0x00002000; offset = 0x0081e000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; @@ -12900,7 +12900,7 @@ part parent ".xmega" memory "flash" size = 0x00022000; offset = 0x0800000; - page_size = 0x100; + page_size = 0x200; readsize = 0x100; ; ; diff --git a/jtagmkII.c b/jtagmkII.c index 78b8910b..c96d4ca7 100644 --- a/jtagmkII.c +++ b/jtagmkII.c @@ -993,10 +993,13 @@ static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p) for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { m = ldata(ln); if (strcmp(m->desc, "flash") == 0) { - PDATA(pgm)->flash_pagesize = m->page_size; + if (m->page_size > 256) + PDATA(pgm)->flash_pagesize = 256; + else + PDATA(pgm)->flash_pagesize = m->page_size; u32_to_b4(sendbuf.dd.ulFlashSize, m->size); - u16_to_b2(sendbuf.dd.uiFlashPageSize, PDATA(pgm)->flash_pagesize); - u16_to_b2(sendbuf.dd.uiFlashpages, m->size / PDATA(pgm)->flash_pagesize); + u16_to_b2(sendbuf.dd.uiFlashPageSize, m->page_size); + u16_to_b2(sendbuf.dd.uiFlashpages, m->size / m->page_size); if (p->flags & AVRPART_HAS_DW) { memcpy(sendbuf.dd.ucFlashInst, p->flash_instr, FLASH_INSTR_SIZE); memcpy(sendbuf.dd.ucEepromInst, p->eeprom_instr, EEPROM_INSTR_SIZE); @@ -1061,8 +1064,11 @@ static void jtagmkII_set_xmega_params(PROGRAMMER * pgm, AVRPART * p) for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { m = ldata(ln); if (strcmp(m->desc, "flash") == 0) { - PDATA(pgm)->flash_pagesize = m->page_size; - u16_to_b2(sendbuf.dd.flash_page_size, m->page_size * 2); + if (m->page_size > 256) + PDATA(pgm)->flash_pagesize = 256; + else + PDATA(pgm)->flash_pagesize = m->page_size; + u16_to_b2(sendbuf.dd.flash_page_size, m->page_size); } else if (strcmp(m->desc, "eeprom") == 0) { sendbuf.dd.eeprom_page_size = m->page_size; u16_to_b2(sendbuf.dd.eeprom_size, m->size); @@ -1366,6 +1372,15 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) return -1; } + /* + * If this is an ATxmega device in JTAG mode, change the emulator + * mode from JTAG to JTAG_XMEGA. + */ + if ((pgm->flag & PGM_FL_IS_JTAG) && + (p->flags & AVRPART_HAS_PDI)) { + if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG_XMEGA) < 0) + return -1; + } /* * Must set the device descriptor before entering programming mode. */ @@ -1381,8 +1396,6 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) */ if ((pgm->flag & PGM_FL_IS_JTAG) && (p->flags & AVRPART_HAS_PDI)) { - if (jtagmkII_getsync(pgm, EMULATOR_MODE_JTAG_XMEGA) < 0) - return -1; /* * Find out where the border between application and boot area * is. @@ -1394,6 +1407,16 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p) "%s: jtagmkII_initialize(): Cannot locate \"flash\" and \"boot\" memories in description\n", progname); } else { + if (PDATA(pgm)->fwver < 0x700) { + /* V7+ firmware does not need this anymore */ + unsigned char par[4]; + + u32_to_b4(par, flashmem->offset); + (void) jtagmkII_setparm(pgm, PAR_PDI_OFFSET_START, par); + u32_to_b4(par, bootmem->offset); + (void) jtagmkII_setparm(pgm, PAR_PDI_OFFSET_END, par); + } + PDATA(pgm)->boot_start = bootmem->offset - flashmem->offset; } } @@ -1856,6 +1879,107 @@ void jtagmkII_close(PROGRAMMER * pgm) pgm->fd.ifd = -1; } +static int jtagmkII_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + unsigned int addr) +{ + unsigned char cmd[6]; + unsigned char *resp; + int status, tries; + long otimeout = serial_recv_timeout; + + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_page_erase(.., %s, 0x%x)\n", + progname, m->desc, addr); + + if (!(p->flags & AVRPART_HAS_PDI)) { + fprintf(stderr, "%s: jtagmkII_page_erase: not an Xmega device\n", + progname); + return -1; + } + if ((pgm->flag & PGM_FL_IS_DW)) { + fprintf(stderr, "%s: jtagmkII_page_erase: not applicable to debugWIRE\n", + progname); + return -1; + } + + if (jtagmkII_program_enable(pgm) < 0) + return -1; + + cmd[0] = CMND_XMEGA_ERASE; + if (strcmp(m->desc, "flash") == 0) { + if (jtagmkII_memtype(pgm, p, addr) == MTYPE_FLASH) + cmd[1] = XMEGA_ERASE_APP_PAGE; + else + cmd[1] = XMEGA_ERASE_BOOT_PAGE; + } else if (strcmp(m->desc, "eeprom") == 0) { + cmd[1] = XMEGA_ERASE_EEPROM_PAGE; + } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { + cmd[1] = XMEGA_ERASE_USERSIG; + } else if ( ( strcmp(m->desc, "boot") == 0 ) ) { + cmd[1] = XMEGA_ERASE_BOOT_PAGE; + } else { + cmd[1] = XMEGA_ERASE_APP_PAGE; + } + serial_recv_timeout = 100; + + /* + * Don't use jtagmkII_memaddr() here. While with all other + * commands, firmware 7+ doesn't require the NVM offsets being + * applied, the erase page commands make an exception, and do + * require the NVM offsets as part of the (page) address. + */ + u32_to_b4(cmd + 2, addr + m->offset); + + tries = 0; + + retry: + if (verbose >= 2) + fprintf(stderr, "%s: jtagmkII_page_erase(): " + "Sending xmega erase command: ", + progname); + jtagmkII_send(pgm, cmd, sizeof cmd); + + status = jtagmkII_recv(pgm, &resp); + if (status <= 0) { + if (verbose >= 2) + putc('\n', stderr); + if (verbose >= 1) + fprintf(stderr, + "%s: jtagmkII_page_erase(): " + "timeout/error communicating with programmer (status %d)\n", + progname, status); + if (tries++ < 4) { + serial_recv_timeout *= 2; + goto retry; + } + fprintf(stderr, + "%s: jtagmkII_page_erase(): fatal timeout/" + "error communicating with programmer (status %d)\n", + progname, status); + serial_recv_timeout = otimeout; + return -1; + } + if (verbose >= 3) { + putc('\n', stderr); + jtagmkII_prmsg(pgm, resp, status); + } else if (verbose == 2) + fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status); + if (resp[0] != RSP_OK) { + fprintf(stderr, + "%s: jtagmkII_page_erase(): " + "bad response to xmega erase command: %s\n", + progname, jtagmkII_get_rc(resp[0])); + free(resp); + serial_recv_timeout = otimeout; + return -1; + } + free(resp); + + serial_recv_timeout = otimeout; + + return 0; +} + static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned int page_size, unsigned int addr, unsigned int n_bytes) @@ -1864,7 +1988,6 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned int maxaddr = addr + n_bytes; unsigned char *cmd; unsigned char *resp; - unsigned char par[4]; int status, tries, dynamic_memtype = 0; long otimeout = serial_recv_timeout; @@ -1876,24 +1999,17 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, return -1; if (page_size == 0) page_size = 256; + else if (page_size > 256) page_size = 256; if ((cmd = malloc(page_size + 10)) == NULL) { fprintf(stderr, "%s: jtagmkII_paged_write(): Out of memory\n", progname); return -1; } - if ( p->flags & AVRPART_HAS_PDI ) - { - u32_to_b4( par, m->offset ); - (void) jtagmkII_setparm( pgm, PAR_PDI_OFFSET_START, par ); - u32_to_b4( par, m->offset + m->size ); - (void) jtagmkII_setparm( pgm, PAR_PDI_OFFSET_END, par ); - } cmd[0] = CMND_WRITE_MEMORY; if (strcmp(m->desc, "flash") == 0) { PDATA(pgm)->flash_pageaddr = (unsigned long)-1L; - page_size = PDATA(pgm)->flash_pagesize; cmd[1] = jtagmkII_memtype(pgm, p, addr); if (p->flags & AVRPART_HAS_PDI) /* dynamically decide between flash/boot memtype */ @@ -1916,7 +2032,6 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, } cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE; PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; - page_size = PDATA(pgm)->eeprom_pagesize; } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { cmd[1] = MTYPE_USERSIG; } else if ( ( strcmp(m->desc, "boot") == 0 ) ) { @@ -2136,8 +2251,11 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, addr += mem->offset; cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE; - if (strcmp(mem->desc, "flash") == 0) { - pagesize = mem->page_size; + if (strcmp(mem->desc, "flash") == 0 || + strcmp(mem->desc, "application") == 0 || + strcmp(mem->desc, "apptable") == 0 || + strcmp(mem->desc, "boot") == 0) { + pagesize = PDATA(pgm)->flash_pagesize; paddr = addr & ~(pagesize - 1); paddr_ptr = &PDATA(pgm)->flash_pageaddr; cache_ptr = PDATA(pgm)->flash_pagecache; @@ -3771,6 +3889,7 @@ void jtagmkII_initpgm(PROGRAMMER * pgm) */ pgm->paged_write = jtagmkII_paged_write; pgm->paged_load = jtagmkII_paged_load; + pgm->page_erase = jtagmkII_page_erase; pgm->print_parms = jtagmkII_print_parms; pgm->set_sck_period = jtagmkII_set_sck_period; pgm->parseextparams = jtagmkII_parseextparms; @@ -3837,6 +3956,7 @@ void jtagmkII_pdi_initpgm(PROGRAMMER * pgm) */ pgm->paged_write = jtagmkII_paged_write; pgm->paged_load = jtagmkII_paged_load; + pgm->page_erase = jtagmkII_page_erase; pgm->print_parms = jtagmkII_print_parms; pgm->setup = jtagmkII_setup; pgm->teardown = jtagmkII_teardown; @@ -3869,6 +3989,7 @@ void jtagmkII_dragon_initpgm(PROGRAMMER * pgm) */ pgm->paged_write = jtagmkII_paged_write; pgm->paged_load = jtagmkII_paged_load; + pgm->page_erase = jtagmkII_page_erase; pgm->print_parms = jtagmkII_print_parms; pgm->set_sck_period = jtagmkII_set_sck_period; pgm->parseextparams = jtagmkII_parseextparms; @@ -3969,6 +4090,7 @@ void jtagmkII_dragon_pdi_initpgm(PROGRAMMER * pgm) */ pgm->paged_write = jtagmkII_paged_write; pgm->paged_load = jtagmkII_paged_load; + pgm->page_erase = jtagmkII_page_erase; pgm->print_parms = jtagmkII_print_parms; pgm->setup = jtagmkII_setup; pgm->teardown = jtagmkII_teardown; diff --git a/main.c b/main.c index a39c4b84..83d59f3e 100644 --- a/main.c +++ b/main.c @@ -315,11 +315,8 @@ int main(int argc, char * argv []) /* options / operating mode variables */ int erase; /* 1=erase chip, 0=don't */ int calibrate; /* 1=calibrate RC oscillator, 0=don't */ - int auto_erase; /* 0=never erase unless explicity told to do - so, 1=erase if we are going to program flash */ char * port; /* device port (/dev/xxx) */ int terminal; /* 1=enter terminal mode, 0=don't */ - int nowrite; /* don't actually write anything to the chip */ int verify; /* perform a verify operation */ char * exitspecs; /* exit specs string from command line */ char * programmer; /* programmer id */ @@ -336,6 +333,7 @@ int main(int argc, char * argv []) int silentsafe; /* Don't ask about fuses, 1=silent, 0=normal */ int init_ok; /* Device initialization worked well */ int is_open; /* Device open succeeded */ + enum updateflags uflags = UF_AUTO_ERASE; /* Flags for do_op() */ unsigned char safemode_lfuse = 0xff; unsigned char safemode_hfuse = 0xff; unsigned char safemode_efuse = 0xff; @@ -397,11 +395,9 @@ int main(int argc, char * argv []) port = NULL; erase = 0; calibrate = 0; - auto_erase = 1; p = NULL; ovsigck = 0; terminal = 0; - nowrite = 0; verify = 1; /* on by default */ quell_progress = 0; exitspecs = NULL; @@ -508,11 +504,12 @@ int main(int argc, char * argv []) break; case 'D': /* disable auto erase */ - auto_erase = 0; + uflags &= ~UF_AUTO_ERASE; break; case 'e': /* perform a chip erase */ erase = 1; + uflags &= ~UF_AUTO_ERASE; break; case 'E': @@ -524,7 +521,7 @@ int main(int argc, char * argv []) break; case 'n': - nowrite = 1; + uflags |= UF_NOWRITE; break; case 'O': /* perform RC oscillator calibration */ @@ -844,7 +841,6 @@ int main(int argc, char * argv []) if(p->flags & AVRPART_AVR32) { safemode = 0; - auto_erase = 0; } if(p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_TPI)) { @@ -1131,23 +1127,36 @@ int main(int argc, char * argv []) } } - if ((erase == 0) && (auto_erase == 1)) { - AVRMEM * m; - for (ln=lfirst(updates); ln; ln=lnext(ln)) { - upd = ldata(ln); - m = avr_locate_mem(p, upd->memtype); - if (m == NULL) - continue; - if ((strcasecmp(m->desc, "flash") == 0) && (upd->op == DEVICE_WRITE)) { - erase = 1; - if (quell_progress < 2) { - fprintf(stderr, - "%s: NOTE: FLASH memory has been specified, an erase cycle " - "will be performed\n" - "%sTo disable this feature, specify the -D option.\n", - progname, progbuf); + if (uflags & UF_AUTO_ERASE) { + if ((p->flags & AVRPART_HAS_PDI) && pgm->page_erase != NULL && + lsize(updates) > 0) { + if (quell_progress < 2) { + fprintf(stderr, + "%s: NOTE: Programmer supports page erase for Xmega devices.\n" + "%sEach page will be erased before programming it, but no chip erase is performed.\n" + "%sTo disable page erases, specify the -D option; for a chip-erase, use the -e option.\n", + progname, progbuf, progbuf); + } + } else { + AVRMEM * m; + const char *memname = (p->flags & AVRPART_HAS_PDI)? "application": "flash"; + for (ln=lfirst(updates); ln; ln=lnext(ln)) { + upd = ldata(ln); + m = avr_locate_mem(p, upd->memtype); + if (m == NULL) + continue; + if ((strcasecmp(m->desc, memname) == 0) && (upd->op == DEVICE_WRITE)) { + erase = 1; + uflags &= ~UF_AUTO_ERASE; + if (quell_progress < 2) { + fprintf(stderr, + "%s: NOTE: \"%s\" memory has been specified, an erase cycle " + "will be performed\n" + "%sTo disable this feature, specify the -D option.\n", + progname, memname, progbuf); + } + break; } - break; } } } @@ -1199,7 +1208,7 @@ int main(int argc, char * argv []) * erase the chip's flash and eeprom memories, this is required * before the chip can accept new programming */ - if (nowrite) { + if (uflags & UF_NOWRITE) { fprintf(stderr, "%s: conflicting -e and -n options specified, NOT erasing chip\n", progname); @@ -1230,7 +1239,7 @@ int main(int argc, char * argv []) for (ln=lfirst(updates); ln; ln=lnext(ln)) { upd = ldata(ln); - rc = do_op(pgm, p, upd, nowrite); + rc = do_op(pgm, p, upd, uflags); if (rc) { exitrc = 1; break; diff --git a/pgm.h b/pgm.h index 784a32f4..57e5d8ff 100644 --- a/pgm.h +++ b/pgm.h @@ -109,6 +109,8 @@ typedef struct programmer_t { int (*paged_load) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m, unsigned int page_size, unsigned int baseaddr, unsigned int n_bytes); + int (*page_erase) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m, + unsigned int baseaddr); void (*write_setup) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m); int (*write_byte) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m, unsigned long addr, unsigned char value); diff --git a/stk500v2.c b/stk500v2.c index 5db352af..0eedb8f3 100644 --- a/stk500v2.c +++ b/stk500v2.c @@ -1171,8 +1171,12 @@ static int stk500hv_initialize(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode) for (ln = lfirst(p->mem); ln; ln = lnext(ln)) { m = ldata(ln); if (strcmp(m->desc, "flash") == 0) { - if (m->page_size > 0) - PDATA(pgm)->flash_pagesize = m->page_size; + if (m->page_size > 0) { + if (m->page_size > 256) + PDATA(pgm)->flash_pagesize = 256; + else + PDATA(pgm)->flash_pagesize = m->page_size; + } } else if (strcmp(m->desc, "eeprom") == 0) { if (m->page_size > 0) PDATA(pgm)->eeprom_pagesize = m->page_size; @@ -1456,9 +1460,7 @@ static int stk500hv_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (strcmp(mem->desc, "flash") == 0) { buf[0] = mode == PPMODE? CMD_READ_FLASH_PP: CMD_READ_FLASH_HVSP; cmdlen = 3; - pagesize = mem->page_size; - if (pagesize == 0) - pagesize = 2; + pagesize = PDATA(pgm)->flash_pagesize; paddr = addr & ~(pagesize - 1); paddr_ptr = &PDATA(pgm)->flash_pageaddr; cache_ptr = PDATA(pgm)->flash_pagecache; @@ -1587,9 +1589,7 @@ static int stk500hv_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (strcmp(mem->desc, "flash") == 0) { buf[0] = mode == PPMODE? CMD_PROGRAM_FLASH_PP: CMD_PROGRAM_FLASH_HVSP; - pagesize = mem->page_size; - if (pagesize == 0) - pagesize = 2; + pagesize = PDATA(pgm)->flash_pagesize; paddr = addr & ~(pagesize - 1); paddr_ptr = &PDATA(pgm)->flash_pageaddr; cache_ptr = PDATA(pgm)->flash_pagecache; diff --git a/update.c b/update.c index f5ecd6c2..4caf28ec 100644 --- a/update.c +++ b/update.c @@ -216,7 +216,7 @@ void free_update(UPDATE * u) } -int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite) +int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags flags) { struct avrpart * v; AVRMEM * mem; @@ -239,7 +239,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite) progname, mem->desc); } report_progress(0,1,"Reading"); - rc = avr_read(pgm, p, upd->memtype, 0, 1); + rc = avr_read(pgm, p, upd->memtype, 0); if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", progname, mem->desc, rc); @@ -288,9 +288,9 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite) progname, mem->desc, size); } - if (!nowrite) { + if (!(flags & UF_NOWRITE)) { report_progress(0,1,"Writing"); - rc = avr_write(pgm, p, upd->memtype, size, 1); + rc = avr_write(pgm, p, upd->memtype, size, (flags & UF_AUTO_ERASE) != 0); report_progress(1,1,NULL); } else { @@ -346,7 +346,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, int nowrite) } report_progress (0,1,"Reading"); - rc = avr_read(pgm, p, upd->memtype, v, 1); + rc = avr_read(pgm, p, upd->memtype, v); if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", progname, mem->desc, rc); diff --git a/update.h b/update.h index 4768a1a3..92d8ca71 100644 --- a/update.h +++ b/update.h @@ -29,6 +29,12 @@ enum { DEVICE_VERIFY }; +enum updateflags { + UF_NONE = 0, + UF_NOWRITE = 1, + UF_AUTO_ERASE = 2, +}; + typedef struct update_t { char * memtype; @@ -47,7 +53,7 @@ extern UPDATE * new_update(int op, char * memtype, int filefmt, char * filename); extern void free_update(UPDATE * upd); extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, - int nowrite); + enum updateflags flags); #ifdef __cplusplus }