Merge branch 'avrdudes:main' into partdesc

This commit is contained in:
Stefan Rueger 2022-07-12 18:19:17 +01:00 committed by GitHub
commit 3ef8122d90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 290 additions and 251 deletions

6
NEWS
View File

@ -32,6 +32,12 @@ Changes since version 7.0:
- Replace internal knowledge in jtag3.c by a public API #996 - Replace internal knowledge in jtag3.c by a public API #996
- JTAG3 UPDI EEPROM fix #1013 - JTAG3 UPDI EEPROM fix #1013
- Treat x bits in .conf SPI commands as 0 #943 - Treat x bits in .conf SPI commands as 0 #943
- Fix avrftdi support for ATmega2560 et al #998
- Fix avrdude.conf timings for ATmega328PB and other parts #1001
- Fix PICKit2 ATmega2560 flash paged flash read #1023
- Fix ft245r paged read for ATmega2560 et al #1018
- Add option -A that supresses trailing 0xff optimisation
and automatically do so for -c arduino #936
* Internals: * Internals:

View File

@ -130,4 +130,6 @@ void arduino_initpgm(PROGRAMMER * pgm)
pgm->read_sig_bytes = arduino_read_sig_bytes; pgm->read_sig_bytes = arduino_read_sig_bytes;
pgm->open = arduino_open; pgm->open = arduino_open;
pgm->close = arduino_close; pgm->close = arduino_close;
disable_trailing_ff_removal(); /* so that arduino bootloader can ignore chip erase */
} }

View File

@ -234,7 +234,7 @@ int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
if (readop == NULL) { if (readop == NULL) {
#if DEBUG #if DEBUG
avrdude_message(MSG_INFO, "avr_read_byte(): operation not supported on memory type \"%s\"\n", avrdude_message(MSG_INFO, "avr_read_byte_default(): operation not supported on memory type \"%s\"\n",
mem->desc); mem->desc);
#endif #endif
return -1; return -1;
@ -278,10 +278,28 @@ int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
* value. This is useful for determining where to stop when dealing * value. This is useful for determining where to stop when dealing
* with "flash" memory, since writing 0xff to flash is typically a * with "flash" memory, since writing 0xff to flash is typically a
* no-op. Always return an even number since flash is word addressed. * no-op. Always return an even number since flash is word addressed.
* Only apply this optimisation on flash-type memory.
*/ */
int avr_mem_hiaddr(AVRMEM * mem) int avr_mem_hiaddr(AVRMEM * mem)
{ {
int i, n; int i, n;
static int disableffopt;
/* calling once with NULL disables any future trailing-0xff optimisation */
if(!mem) {
disableffopt = 1;
return 0;
}
if(disableffopt)
return mem->size;
/* if the memory is not a flash-type memory do not remove trailing 0xff */
if(strcasecmp(mem->desc, "flash") &&
strcasecmp(mem->desc, "application") &&
strcasecmp(mem->desc, "apptable") &&
strcasecmp(mem->desc, "boot"))
return mem->size;
/* return the highest non-0xff address regardless of how much /* return the highest non-0xff address regardless of how much
memory was read */ memory was read */
@ -416,15 +434,8 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype,
nread++; nread++;
report_progress(nread, npages, NULL); report_progress(nread, npages, NULL);
} }
if (!failure) { if (!failure)
if (strcasecmp(mem->desc, "flash") == 0 || return avr_mem_hiaddr(mem);
strcasecmp(mem->desc, "application") == 0 ||
strcasecmp(mem->desc, "apptable") == 0 ||
strcasecmp(mem->desc, "boot") == 0)
return avr_mem_hiaddr(mem);
else
return mem->size;
}
/* else: fall back to byte-at-a-time write, for historical reasons */ /* else: fall back to byte-at-a-time write, for historical reasons */
} }
@ -454,13 +465,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype,
report_progress(i, mem->size, NULL); report_progress(i, mem->size, NULL);
} }
if (strcasecmp(mem->desc, "flash") == 0 || return avr_mem_hiaddr(mem);
strcasecmp(mem->desc, "application") == 0 ||
strcasecmp(mem->desc, "apptable") == 0 ||
strcasecmp(mem->desc, "boot") == 0)
return avr_mem_hiaddr(mem);
else
return i;
} }
@ -650,7 +655,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
if (writeop == NULL) { if (writeop == NULL) {
#if DEBUG #if DEBUG
avrdude_message(MSG_INFO, "avr_write_byte(): write not supported for memory type \"%s\"\n", avrdude_message(MSG_INFO, "avr_write_byte_default(): write not supported for memory type \"%s\"\n",
mem->desc); mem->desc);
#endif #endif
return -1; return -1;

View File

@ -18,7 +18,7 @@
.\" .\"
.\" $Id$ .\" $Id$
.\" .\"
.Dd November 22, 2021 .Dd July 12, 2022
.Os .Os
.Dt AVRDUDE 1 .Dt AVRDUDE 1
.Sh NAME .Sh NAME
@ -31,6 +31,7 @@
.Op Fl B Ar bitclock .Op Fl B Ar bitclock
.Op Fl c Ar programmer-id .Op Fl c Ar programmer-id
.Op Fl C Ar config-file .Op Fl C Ar config-file
.Op Fl A
.Op Fl D .Op Fl D
.Op Fl e .Op Fl e
.Oo Fl E Ar exitspec Ns .Oo Fl E Ar exitspec Ns
@ -102,7 +103,7 @@ available (like almost all embedded Linux boards) you can do without
any additional hardware - just connect them to the MOSI, MISO, RESET any additional hardware - just connect them to the MOSI, MISO, RESET
and SCK pins on the AVR and use the linuxgpio programmer type. It bitbangs and SCK pins on the AVR and use the linuxgpio programmer type. It bitbangs
the lines using the Linux sysfs GPIO interface. Of course, care should the lines using the Linux sysfs GPIO interface. Of course, care should
be taken about voltage level compatibility. Also, although not strictrly be taken about voltage level compatibility. Also, although not strictly
required, it is strongly advisable to protect the GPIO pins from required, it is strongly advisable to protect the GPIO pins from
overcurrent situations in some way. The simplest would be to just put overcurrent situations in some way. The simplest would be to just put
some resistors in series or better yet use a 3-state buffer driver like some resistors in series or better yet use a 3-state buffer driver like
@ -253,7 +254,7 @@ The Teensy bootloader is supported for all AVR boards.
As the bootloader does not support reading from flash memory, As the bootloader does not support reading from flash memory,
use the use the
.Fl V .Fl V
option to prevent AVRDUDE from verifing the flash memory. option to prevent AVRDUDE from verifying the flash memory.
See the section on See the section on
.Em extended parameters .Em extended parameters
for Teensy specific options. for Teensy specific options.
@ -376,6 +377,20 @@ files. This can be used to add entries to the configuration
without patching your system wide configuration file. It can be used without patching your system wide configuration file. It can be used
several times, the files are read in same order as given on the command several times, the files are read in same order as given on the command
line. line.
.It Fl A
Disable the automatic removal of trailing-0xFF sequences in file
input that is to be programmed to flash and in AVR reads from
flash memory. Normally, trailing 0xFFs can be discarded, as flash
programming requires the memory be erased to 0xFF beforehand.
.Fl A
should be used when the programmer hardware, or bootloader
software for that matter, does not carry out chip erase and
instead handles the memory erase on a page level. The popular
Arduino bootloader exhibits this behaviour; for this reason
.Fl A
is engaged by default when specifying
. Fl c
arduino.
.It Fl D .It Fl D
Disable auto erase for flash. When the Disable auto erase for flash. When the
.Fl U .Fl U
@ -389,6 +404,10 @@ use page erase before writing each page so no explicit chip erase
is required. is required.
Note however that any page not affected by the current operation Note however that any page not affected by the current operation
will retain its previous contents. will retain its previous contents.
Setting
.Fl D
implies
.Fl A.
.It Fl e .It Fl e
Causes a chip erase to be executed. This will reset the contents of the Causes a chip erase to be executed. This will reset the contents of the
flash ROM and EEPROM to the value flash ROM and EEPROM to the value

View File

@ -5824,6 +5824,8 @@ part
memory "efuse" memory "efuse"
size = 1; size = 1;
min_write_delay = 2000;
max_write_delay = 2000;
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
"x x x x x x x x x x x x i i i i"; "x x x x x x x x x x x x i i i i";
@ -8214,6 +8216,7 @@ part parent "m48"
id = "m48pb"; id = "m48pb";
desc = "ATmega48PB"; desc = "ATmega48PB";
signature = 0x1e 0x92 0x10; signature = 0x1e 0x92 0x10;
chip_erase_delay = 10500;
; ;
#------------------------------------------------------------ #------------------------------------------------------------
@ -8441,6 +8444,7 @@ part parent "m88"
id = "m88pb"; id = "m88pb";
desc = "ATmega88PB"; desc = "ATmega88PB";
signature = 0x1e 0x93 0x16; signature = 0x1e 0x93 0x16;
chip_erase_delay = 10500;
; ;
#------------------------------------------------------------ #------------------------------------------------------------
@ -8670,6 +8674,7 @@ part parent "m168"
id = "m168pb"; id = "m168pb";
desc = "ATmega168PB"; desc = "ATmega168PB";
signature = 0x1e 0x94 0x15; signature = 0x1e 0x94 0x15;
chip_erase_delay = 10500;
; ;
#------------------------------------------------------------ #------------------------------------------------------------
@ -9826,6 +9831,7 @@ part parent "m328"
id = "m328pb"; id = "m328pb";
desc = "ATmega328PB"; desc = "ATmega328PB";
signature = 0x1e 0x95 0x16; signature = 0x1e 0x95 0x16;
chip_erase_delay = 10500;
memory "efuse" memory "efuse"
size = 1; size = 1;
@ -9853,6 +9859,8 @@ part parent "m328"
memory "efuse" memory "efuse"
size = 1; size = 1;
min_write_delay = 4500;
max_write_delay = 4500;
read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
"x x x x x x x x o o o o o o o o"; "x x x x x x x x o o o o o o o o";
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",

View File

@ -917,8 +917,19 @@ static int avrftdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
static int static int
avrftdi_lext(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, unsigned int address) avrftdi_lext(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, unsigned int address)
{ {
/* nothing to do if load extended address command unavailable */
if(m->op[AVR_OP_LOAD_EXT_ADDR] == NULL)
return 0;
avrftdi_t *pdata = to_pdata(pgm);
unsigned char buf[] = { 0x00, 0x00, 0x00, 0x00 }; unsigned char buf[] = { 0x00, 0x00, 0x00, 0x00 };
/* only send load extended address command if high byte changed */
if(pdata->lext_byte == (uint8_t) (address>>16))
return 0;
pdata->lext_byte = (uint8_t) (address>>16);
avr_set_bits(m->op[AVR_OP_LOAD_EXT_ADDR], buf); avr_set_bits(m->op[AVR_OP_LOAD_EXT_ADDR], buf);
avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], buf, address); avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], buf, address);
@ -983,8 +994,6 @@ static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int addr, unsigned int len) unsigned int page_size, unsigned int addr, unsigned int len)
{ {
int use_lext_address = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
unsigned int word; unsigned int word;
unsigned int poll_index; unsigned int poll_index;
@ -1013,22 +1022,12 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
page_size = m->page_size; page_size = m->page_size;
/* if we do cross a 64k word boundary (or write the /* on large-flash devices > 128k issue extended address command when needed */
* first page), we need to issue a 'load extended if(avrftdi_lext(pgm, p, m, addr/2) < 0)
* address byte' command, which is defined as 0x4d return -1;
* 0x00 <address byte> 0x00. As far as i know, this
* is only available on 256k parts. 64k word is 128k
* bytes.
* write the command only once.
*/
if(use_lext_address && (((addr/2) & 0xffff0000))) {
if (0 > avrftdi_lext(pgm, p, m, addr/2))
return -1;
}
/* prepare the command stream for the whole page */ /* prepare the command stream for the whole page */
/* addr is in bytes, but we program in words. addr/2 should be something /* addr is in bytes, but we program in words. */
* like addr >> WORD_SHIFT, though */
for(word = addr/2; word < (len + addr)/2; word++) for(word = addr/2; word < (len + addr)/2; word++)
{ {
log_debug("-< bytes = %d of %d\n", word * 2, len + addr); log_debug("-< bytes = %d of %d\n", word * 2, len + addr);
@ -1107,8 +1106,6 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
{ {
OPCODE * readop; OPCODE * readop;
int byte, word; int byte, word;
int use_lext_address = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
unsigned int address = addr/2;
unsigned int buf_size = 4 * len + 4; unsigned int buf_size = 4 * len + 4;
unsigned char* o_buf = alloca(buf_size); unsigned char* o_buf = alloca(buf_size);
@ -1128,10 +1125,8 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
return -1; return -1;
} }
if(use_lext_address && ((address & 0xffff0000))) { if(avrftdi_lext(pgm, p, m, addr/2) < 0)
if (0 > avrftdi_lext(pgm, p, m, address)) return -1;
return -1;
}
/* word addressing! */ /* word addressing! */
for(word = addr/2, index = 0; word < (addr + len)/2; word++) for(word = addr/2, index = 0; word < (addr + len)/2; word++)
@ -1210,7 +1205,11 @@ avrftdi_setup(PROGRAMMER * pgm)
{ {
avrftdi_t* pdata; avrftdi_t* pdata;
pgm->cookie = malloc(sizeof(avrftdi_t));
if(!(pgm->cookie = calloc(sizeof(avrftdi_t), 1))) {
log_err("Error allocating memory.\n");
exit(1);
}
pdata = to_pdata(pgm); pdata = to_pdata(pgm);
pdata->ftdic = ftdi_new(); pdata->ftdic = ftdi_new();
@ -1224,6 +1223,7 @@ avrftdi_setup(PROGRAMMER * pgm)
pdata->pin_value = 0; pdata->pin_value = 0;
pdata->pin_direction = 0; pdata->pin_direction = 0;
pdata->led_mask = 0; pdata->led_mask = 0;
pdata->lext_byte = 0xff;
} }
static void static void

View File

@ -81,6 +81,8 @@ typedef struct avrftdi_s {
int tx_buffer_size; int tx_buffer_size;
/* use bitbanging instead of mpsse spi */ /* use bitbanging instead of mpsse spi */
bool use_bitbanging; bool use_bitbanging;
/* bits 16-23 of extended 24-bit word flash address for parts with flash > 128k */
uint8_t lext_byte;
} avrftdi_t; } avrftdi_t;
void avrftdi_log(int level, const char * func, int line, const char * fmt, ...); void avrftdi_log(int level, const char * func, int line, const char * fmt, ...);

View File

@ -321,13 +321,13 @@ via a serial link (@url{https://github.com/ElTangas/jtag2updi}).
The Micronucleus bootloader is supported for both protocol version V1 The Micronucleus bootloader is supported for both protocol version V1
and V2. As the bootloader does not support reading from flash memory, and V2. As the bootloader does not support reading from flash memory,
use the @code{-V} option to prevent AVRDUDE from verifing the flash memory. use the @code{-V} option to prevent AVRDUDE from verifying the flash memory.
See the section on @emph{extended parameters} See the section on @emph{extended parameters}
below for Micronucleus specific options. below for Micronucleus specific options.
The Teensy bootloader is supported for all AVR boards. The Teensy bootloader is supported for all AVR boards.
As the bootloader does not support reading from flash memory, As the bootloader does not support reading from flash memory,
use the @code{-V} option to prevent AVRDUDE from verifing the flash memory. use the @code{-V} option to prevent AVRDUDE from verifying the flash memory.
See the section on @emph{extended parameters} See the section on @emph{extended parameters}
below for Teensy specific options. below for Teensy specific options.
@ -495,6 +495,16 @@ without patching your system wide configuration file. It can be used
several times, the files are read in same order as given on the command several times, the files are read in same order as given on the command
line. line.
@item -A
Disable the automatic removal of trailing-0xFF sequences in file
input that is to be programmed to flash and in AVR reads from
flash memory. Normally, trailing 0xFFs can be discarded, as flash
programming requires the memory be erased to 0xFF beforehand. -A
should be used when the programmer hardware, or bootloader
software for that matter, does not carry out chip erase and
instead handles the memory erase on a page level. The popular
Arduino bootloader exhibits this behaviour; for this reason -A is
engaged by default when specifying -c arduino.
@item -D @item -D
Disable auto erase for flash. When the -U option with flash memory is Disable auto erase for flash. When the -U option with flash memory is
@ -506,6 +516,7 @@ use page erase before writing each page so no explicit chip erase
is required. is required.
Note however that any page not affected by the current operation Note however that any page not affected by the current operation
will retain its previous contents. will retain its previous contents.
Setting -D implies -A.
@item -e @item -e
Causes a chip erase to be executed. This will reset the contents of the Causes a chip erase to be executed. This will reset the contents of the

View File

@ -1446,16 +1446,17 @@ static int fmt_autodetect(char * fname)
int fileio(int op, char * filename, FILEFMT format, int fileio(int oprwv, char * filename, FILEFMT format,
struct avrpart * p, char * memtype, int size) struct avrpart * p, char * memtype, int size)
{ {
int rc; int op, rc;
FILE * f; FILE * f;
char * fname; char * fname;
struct fioparms fio; struct fioparms fio;
AVRMEM * mem; AVRMEM * mem;
int using_stdio; int using_stdio;
op = oprwv == FIO_READ_FOR_VERIFY? FIO_READ: oprwv;
mem = avr_locate_mem(p, memtype); mem = avr_locate_mem(p, memtype);
if (mem == NULL) { if (mem == NULL) {
avrdude_message(MSG_INFO, "fileio(): memory type \"%s\" not configured for device \"%s\"\n", avrdude_message(MSG_INFO, "fileio(): memory type \"%s\" not configured for device \"%s\"\n",
@ -1585,18 +1586,14 @@ int fileio(int op, char * filename, FILEFMT format,
return -1; return -1;
} }
if (rc > 0) { /* on reading flash other than for verify set the size to location of highest non-0xff byte */
if ((op == FIO_READ) && (strcasecmp(mem->desc, "flash") == 0 || if (rc > 0 && oprwv == FIO_READ) {
strcasecmp(mem->desc, "application") == 0 || int hiaddr = avr_mem_hiaddr(mem);
strcasecmp(mem->desc, "apptable") == 0 ||
strcasecmp(mem->desc, "boot") == 0)) { if(hiaddr < rc) /* if trailing-0xff not disabled */
/* rc = hiaddr;
* if we are reading flash, just mark the size as being the
* highest non-0xff byte
*/
rc = avr_mem_hiaddr(mem);
}
} }
if (format != FMT_IMM && !using_stdio) { if (format != FMT_IMM && !using_stdio) {
fclose(f); fclose(f);
} }

View File

@ -107,10 +107,10 @@ void ft245r_initpgm(PROGRAMMER * pgm) {
#else #else
#define FT245R_CYCLES 2 #define FT245R_CYCLES 2
#define FT245R_FRAGMENT_SIZE 512 #define FT245R_CMD_SIZE (4 * 8*FT245R_CYCLES)
#define REQ_OUTSTANDINGS 10 #define FT245R_FRAGMENT_SIZE (8 * FT245R_CMD_SIZE)
//#define USE_INLINE_WRITE_PAGE #define REQ_OUTSTANDINGS 10
#define FT245R_DEBUG 0 #define FT245R_DEBUG 0
/* /*
@ -992,40 +992,18 @@ static void ft245r_display(PROGRAMMER * pgm, const char * p) {
pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS); pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS);
} }
static int ft245r_paged_write_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int addr,
unsigned int n_bytes) {
unsigned long i, pa;
int rc;
for (i=0; i<n_bytes; i++, addr++) { static int ft245r_paged_write_gen(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
rc = avr_write_byte_default(pgm, p, m, addr, m->buf[addr]); unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
if (rc != 0) {
for(int i=0; i < (int) n_bytes; i++, addr++)
if(avr_write_byte_default(pgm, p, m, addr, m->buf[addr]) != 0)
return -2; return -2;
}
if (m->paged) { return n_bytes;
// Can this piece of code ever be activated?? Do AVRs exist that
// have paged non-flash memories? -- REW
// XXX Untested code below.
/*
* check to see if it is time to flush the page with a page
* write
*/
if (((addr % m->page_size) == m->page_size-1) || (i == n_bytes-1)) {
pa = addr - (addr % m->page_size);
rc = avr_write_page(pgm, p, m, pa);
if (rc != 0) {
return -2;
}
}
}
}
return i;
} }
static struct ft245r_request { static struct ft245r_request {
int addr; int addr;
int bytes; int bytes;
@ -1081,178 +1059,185 @@ static int do_request(PROGRAMMER * pgm, AVRMEM *m) {
return 1; return 1;
} }
static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int page_size, int addr, int n_bytes) {
unsigned int i,j;
int addr_save,buf_pos,do_page_write,req_count;
unsigned char buf[FT245R_FRAGMENT_SIZE+1+128];
req_count = 0; static int ft245r_paged_write_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
for (i=0; i<n_bytes; ) { unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
addr_save = addr;
buf_pos = 0;
do_page_write = 0;
for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) {
buf_pos += set_data(pgm, buf+buf_pos, (addr & 1)?0x48:0x40 );
buf_pos += set_data(pgm, buf+buf_pos, (addr >> 9) & 0xff );
buf_pos += set_data(pgm, buf+buf_pos, (addr >> 1) & 0xff );
buf_pos += set_data(pgm, buf+buf_pos, m->buf[addr]);
addr ++;
i++;
if ( (m->paged) &&
(((i % m->page_size) == 0) || (i == n_bytes))) {
do_page_write = 1;
break;
}
}
#if defined(USE_INLINE_WRITE_PAGE)
if (do_page_write) {
int addr_wk = addr_save - (addr_save % m->page_size);
/* If this device has a "load extended address" command, issue it. */
if (m->op[AVR_OP_LOAD_EXT_ADDR]) {
unsigned char cmd[4];
OPCODE *lext = m->op[AVR_OP_LOAD_EXT_ADDR];
memset(cmd, 0, 4); int i, j, addr_save, buf_pos, req_count, do_page_write;
avr_set_bits(lext, cmd); unsigned char buf[FT245R_FRAGMENT_SIZE+1];
avr_set_addr(lext, cmd, addr_wk/2); unsigned char cmd[4];
buf_pos += set_data(pgm, buf+buf_pos, cmd[0]);
buf_pos += set_data(pgm, buf+buf_pos, cmd[1]); if(m->op[AVR_OP_LOADPAGE_LO] == NULL || m->op[AVR_OP_LOADPAGE_HI] == NULL) {
buf_pos += set_data(pgm, buf+buf_pos, cmd[2]); avrdude_message(MSG_INFO, "AVR_OP_LOADPAGE_HI/LO command not defined for %s\n", p->desc);
buf_pos += set_data(pgm, buf+buf_pos, cmd[3]); return -1;
}
do_page_write = req_count = i = j = buf_pos = 0;
addr_save = addr;
while(i < (int) n_bytes) {
int spi = addr&1? AVR_OP_LOADPAGE_HI: AVR_OP_LOADPAGE_LO;
// put the SPI loadpage command as FT245R_CMD_SIZE bytes into buffer
memset(cmd, 0, sizeof cmd);
avr_set_bits(m->op[spi], cmd);
avr_set_addr(m->op[spi], cmd, addr/2);
avr_set_input(m->op[spi], cmd, m->buf[addr]);
for(int k=0; k<sizeof cmd; k++)
buf_pos += set_data(pgm, buf+buf_pos, cmd[k]);
i++; j++; addr++;
if(m->paged && (i%m->page_size == 0 || i >= (int) n_bytes))
do_page_write = 1;
// page boundary, finished or buffer exhausted? queue up requests
if(do_page_write || i >= (int) n_bytes || j >= FT245R_FRAGMENT_SIZE/FT245R_CMD_SIZE) {
if(i >= n_bytes) {
ft245r_out = SET_BITS_0(ft245r_out, pgm, PIN_AVR_SCK, 0); // SCK down
buf[buf_pos++] = ft245r_out;
} else {
// stretch sequence to allow correct readout, see extract_data()
buf[buf_pos] = buf[buf_pos - 1];
buf_pos++;
} }
buf_pos += set_data(pgm, buf+buf_pos, 0x4C); /* Issue Page Write */ ft245r_send(pgm, buf, buf_pos);
buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 9) & 0xff); put_request(addr_save, buf_pos, 0);
buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 1) & 0xff);
buf_pos += set_data(pgm, buf+buf_pos, 0); if(++req_count > REQ_OUTSTANDINGS)
} do_request(pgm, m);
#endif
if (i >= n_bytes) { if(do_page_write) {
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down while(do_request(pgm, m))
buf[buf_pos++] = ft245r_out; continue;
} if(avr_write_page(pgm, p, m, addr_save - (addr_save % m->page_size)) != 0)
else { return -2;
/* stretch sequence to allow correct readout, see extract_data() */ do_page_write = req_count = 0;
buf[buf_pos] = buf[buf_pos - 1];
buf_pos++;
}
ft245r_send(pgm, buf, buf_pos);
put_request(addr_save, buf_pos, 0);
//ft245r_sync(pgm);
#if 0
avrdude_message(MSG_INFO, "send addr 0x%04x bufsize %d [%02x %02x] page_write %d\n",
addr_save,buf_pos,
extract_data_out(pgm, buf , (0*4 + 3) ),
extract_data_out(pgm, buf , (1*4 + 3) ),
do_page_write);
#endif
req_count++;
if (req_count > REQ_OUTSTANDINGS)
do_request(pgm, m);
if (do_page_write) {
#if defined(USE_INLINE_WRITE_PAGE)
while (do_request(pgm, m))
;
ft245r_usleep(pgm, m->max_write_delay);
#else
int addr_wk = addr_save - (addr_save % m->page_size);
int rc;
while (do_request(pgm, m))
;
rc = avr_write_page(pgm, p, m, addr_wk);
if (rc != 0) {
return -2;
} }
#endif
req_count = 0; // reset buffer variables
j = buf_pos = 0;
addr_save = addr;
} }
} }
while (do_request(pgm, m))
; while(do_request(pgm, m))
return i; continue;
return n_bytes;
} }
static int ft245r_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, static int ft245r_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int addr, unsigned int n_bytes) { unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
if (strcmp(m->desc, "flash") == 0) {
if(!n_bytes)
return 0;
if(strcmp(m->desc, "flash") == 0)
return ft245r_paged_write_flash(pgm, p, m, page_size, addr, n_bytes); return ft245r_paged_write_flash(pgm, p, m, page_size, addr, n_bytes);
} else if (strcmp(m->desc, "eeprom") == 0) {
if(strcmp(m->desc, "eeprom") == 0)
return ft245r_paged_write_gen(pgm, p, m, page_size, addr, n_bytes); return ft245r_paged_write_gen(pgm, p, m, page_size, addr, n_bytes);
} else {
return -2; return -2;
}
} }
static int ft245r_paged_load_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, static int ft245r_paged_load_gen(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
unsigned int page_size, unsigned int addr, unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
int n_bytes) {
unsigned char rbyte;
unsigned long i;
int rc;
for (i=0; i<n_bytes; i++) { for(int i=0; i < (int) n_bytes; i++) {
rc = avr_read_byte_default(pgm, p, m, i+addr, &rbyte); unsigned char rbyte;
if (rc != 0) {
if(avr_read_byte_default(pgm, p, m, addr+i, &rbyte) != 0)
return -2; return -2;
}
m->buf[i+addr] = rbyte; m->buf[addr+i] = rbyte;
} }
return 0; return 0;
} }
static int ft245r_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int addr, static int ft245r_paged_load_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
unsigned int n_bytes) { unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
unsigned long i,j,n;
int addr_save,buf_pos; int i, j, addr_save, buf_pos, req_count;
int req_count = 0;
unsigned char buf[FT245R_FRAGMENT_SIZE+1]; unsigned char buf[FT245R_FRAGMENT_SIZE+1];
unsigned char cmd[4];
for (i=0; i<n_bytes; ) { if(m->op[AVR_OP_READ_LO] == NULL || m->op[AVR_OP_READ_HI] == NULL) {
buf_pos = 0; avrdude_message(MSG_INFO, "AVR_OP_READ_HI/LO command not defined for %s\n", p->desc);
addr_save = addr; return -1;
for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) {
if (i >= n_bytes) break;
buf_pos += set_data(pgm, buf+buf_pos, (addr & 1)?0x28:0x20 );
buf_pos += set_data(pgm, buf+buf_pos, (addr >> 9) & 0xff );
buf_pos += set_data(pgm, buf+buf_pos, (addr >> 1) & 0xff );
buf_pos += set_data(pgm, buf+buf_pos, 0);
addr ++;
i++;
}
if (i >= n_bytes) {
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down
buf[buf_pos++] = ft245r_out;
}
else {
/* stretch sequence to allow correct readout, see extract_data() */
buf[buf_pos] = buf[buf_pos - 1];
buf_pos++;
}
n = j;
ft245r_send(pgm, buf, buf_pos);
put_request(addr_save, buf_pos, n);
req_count++;
if (req_count > REQ_OUTSTANDINGS)
do_request(pgm, m);
} }
while (do_request(pgm, m))
; // always called with addr at page boundary, and n_bytes == m->page_size;
// hence, OK to prepend load extended address command (at most) once
if(m->op[AVR_OP_LOAD_EXT_ADDR]) {
memset(cmd, 0, sizeof cmd);
avr_set_bits(m->op[AVR_OP_LOAD_EXT_ADDR], cmd);
avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], cmd, addr/2);
buf_pos = 0;
for(int k=0; k<sizeof cmd; k++)
buf_pos += set_data(pgm, buf+buf_pos, cmd[k]);
ft245r_send_and_discard(pgm, buf, buf_pos);
}
req_count = i = j = buf_pos = 0;
addr_save = addr;
while(i < (int) n_bytes) {
int spi = addr&1? AVR_OP_READ_HI: AVR_OP_READ_LO;
// put the SPI read command as FT245R_CMD_SIZE bytes into buffer
memset(cmd, 0, sizeof cmd);
avr_set_bits(m->op[spi], cmd);
avr_set_addr(m->op[spi], cmd, addr/2);
for(int k=0; k<sizeof cmd; k++)
buf_pos += set_data(pgm, buf+buf_pos, cmd[k]);
i++; j++; addr++;
// finished or buffer exhausted? queue up requests
if(i >= (int) n_bytes || j >= FT245R_FRAGMENT_SIZE/FT245R_CMD_SIZE) {
if(i >= (int) n_bytes) {
ft245r_out = SET_BITS_0(ft245r_out, pgm, PIN_AVR_SCK, 0); // SCK down
buf[buf_pos++] = ft245r_out;
} else {
// stretch sequence to allow correct readout, see extract_data()
buf[buf_pos] = buf[buf_pos - 1];
buf_pos++;
}
ft245r_send(pgm, buf, buf_pos);
put_request(addr_save, buf_pos, j);
if(++req_count > REQ_OUTSTANDINGS)
do_request(pgm, m);
// reset buffer variables
j = buf_pos = 0;
addr_save = addr;
}
}
while(do_request(pgm, m))
continue;
return 0; return 0;
} }
static int ft245r_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, static int ft245r_paged_load(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
unsigned int page_size, unsigned int addr, unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
unsigned int n_bytes) {
if (strcmp(m->desc, "flash") == 0) { if(!n_bytes)
return 0;
if(strcmp(m->desc, "flash") == 0)
return ft245r_paged_load_flash(pgm, p, m, page_size, addr, n_bytes); return ft245r_paged_load_flash(pgm, p, m, page_size, addr, n_bytes);
} else if (strcmp(m->desc, "eeprom") == 0) {
if(strcmp(m->desc, "eeprom") == 0)
return ft245r_paged_load_gen(pgm, p, m, page_size, addr, n_bytes); return ft245r_paged_load_gen(pgm, p, m, page_size, addr, n_bytes);
} else {
return -2; return -2;
}
} }
void ft245r_initpgm(PROGRAMMER * pgm) { void ft245r_initpgm(PROGRAMMER * pgm) {

View File

@ -797,6 +797,7 @@ int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles);
int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles); int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles);
#define disable_trailing_ff_removal() avr_mem_hiaddr(NULL)
int avr_mem_hiaddr(AVRMEM * mem); int avr_mem_hiaddr(AVRMEM * mem);
int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p); int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p);
@ -835,7 +836,8 @@ struct fioparms {
enum { enum {
FIO_READ, FIO_READ,
FIO_WRITE FIO_WRITE,
FIO_READ_FOR_VERIFY,
}; };
#ifdef __cplusplus #ifdef __cplusplus
@ -844,7 +846,7 @@ extern "C" {
char * fmtstr(FILEFMT format); char * fmtstr(FILEFMT format);
int fileio(int op, char * filename, FILEFMT format, int fileio(int oprwv, char * filename, FILEFMT format,
struct avrpart * p, char * memtype, int size); struct avrpart * p, char * memtype, int size);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -110,7 +110,8 @@ static void usage(void)
" -B <bitclock> Specify JTAG/STK500v2 bit clock period (us).\n" " -B <bitclock> Specify JTAG/STK500v2 bit clock period (us).\n"
" -C <config-file> Specify location of configuration file.\n" " -C <config-file> Specify location of configuration file.\n"
" -c <programmer> Specify programmer type.\n" " -c <programmer> Specify programmer type.\n"
" -D Disable auto erase for flash memory\n" " -A Disable trailing-0xff removal from file and AVR read.\n"
" -D Disable auto erase for flash memory; implies -A.\n"
" -i <delay> ISP Clock Delay [in microseconds]\n" " -i <delay> ISP Clock Delay [in microseconds]\n"
" -P <port> Specify connection port.\n" " -P <port> Specify connection port.\n"
" -F Override invalid signature check.\n" " -F Override invalid signature check.\n"
@ -442,7 +443,7 @@ int main(int argc, char * argv [])
/* /*
* process command line arguments * process command line arguments
*/ */
while ((ch = getopt(argc,argv,"?b:B:c:C:DeE:Fi:l:np:OP:qstU:uvVx:yY:")) != -1) { while ((ch = getopt(argc,argv,"?Ab:B:c:C:DeE:Fi:l:np:OP:qstU:uvVx:yY:")) != -1) {
switch (ch) { switch (ch) {
case 'b': /* override default programmer baud rate */ case 'b': /* override default programmer baud rate */
@ -528,6 +529,10 @@ int main(int argc, char * argv [])
case 'D': /* disable auto erase */ case 'D': /* disable auto erase */
uflags &= ~UF_AUTO_ERASE; uflags &= ~UF_AUTO_ERASE;
/* fall through */
case 'A': /* explicit disabling of trailing-0xff removal */
disable_trailing_ff_removal();
break; break;
case 'e': /* perform a chip erase */ case 'e': /* perform a chip erase */

View File

@ -491,18 +491,15 @@ static int pickit2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
pgm->pgm_led(pgm, ON); pgm->pgm_led(pgm, ON);
if (lext) {
memset(cmd, 0, sizeof(cmd));
avr_set_bits(lext, cmd);
avr_set_addr(lext, cmd, addr/2);
pgm->cmd(pgm, cmd, res);
}
for (addr_base = addr; addr_base < max_addr; ) for (addr_base = addr; addr_base < max_addr; )
{ {
if ((addr_base == 0 || (addr_base % /*ext_address_boundary*/ 65536) == 0)
&& lext != NULL)
{
memset(cmd, 0, sizeof(cmd));
avr_set_bits(lext, cmd);
avr_set_addr(lext, cmd, addr_base);
pgm->cmd(pgm, cmd, res);
}
// bytes to send in the next packet -- not necessary as pickit2_spi() handles breaking up // bytes to send in the next packet -- not necessary as pickit2_spi() handles breaking up
// the data into packets -- but we need to keep transfers frequent so that we can update the // the data into packets -- but we need to keep transfers frequent so that we can update the
// status indicator bar // status indicator bar

View File

@ -341,7 +341,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
progname, mem->desc, alias_mem_desc, upd->filename); progname, mem->desc, alias_mem_desc, upd->filename);
} }
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); rc = fileio(FIO_READ_FOR_VERIFY, upd->filename, upd->format, p, upd->memtype, -1);
if (rc < 0) { if (rc < 0) {
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n", avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
progname, upd->filename); progname, upd->filename);