Merge branch 'avrdudes:main' into partdesc
This commit is contained in:
commit
3ef8122d90
6
NEWS
6
NEWS
|
@ -32,6 +32,12 @@ Changes since version 7.0:
|
|||
- Replace internal knowledge in jtag3.c by a public API #996
|
||||
- JTAG3 UPDI EEPROM fix #1013
|
||||
- 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:
|
||||
|
||||
|
|
|
@ -130,4 +130,6 @@ void arduino_initpgm(PROGRAMMER * pgm)
|
|||
pgm->read_sig_bytes = arduino_read_sig_bytes;
|
||||
pgm->open = arduino_open;
|
||||
pgm->close = arduino_close;
|
||||
|
||||
disable_trailing_ff_removal(); /* so that arduino bootloader can ignore chip erase */
|
||||
}
|
||||
|
|
41
src/avr.c
41
src/avr.c
|
@ -234,7 +234,7 @@ int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
|||
|
||||
if (readop == NULL) {
|
||||
#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);
|
||||
#endif
|
||||
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
|
||||
* with "flash" memory, since writing 0xff to flash is typically a
|
||||
* 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 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
|
||||
memory was read */
|
||||
|
@ -416,15 +434,8 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype,
|
|||
nread++;
|
||||
report_progress(nread, npages, NULL);
|
||||
}
|
||||
if (!failure) {
|
||||
if (strcasecmp(mem->desc, "flash") == 0 ||
|
||||
strcasecmp(mem->desc, "application") == 0 ||
|
||||
strcasecmp(mem->desc, "apptable") == 0 ||
|
||||
strcasecmp(mem->desc, "boot") == 0)
|
||||
return avr_mem_hiaddr(mem);
|
||||
else
|
||||
return mem->size;
|
||||
}
|
||||
if (!failure)
|
||||
return avr_mem_hiaddr(mem);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
if (strcasecmp(mem->desc, "flash") == 0 ||
|
||||
strcasecmp(mem->desc, "application") == 0 ||
|
||||
strcasecmp(mem->desc, "apptable") == 0 ||
|
||||
strcasecmp(mem->desc, "boot") == 0)
|
||||
return avr_mem_hiaddr(mem);
|
||||
else
|
||||
return i;
|
||||
return avr_mem_hiaddr(mem);
|
||||
}
|
||||
|
||||
|
||||
|
@ -650,7 +655,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
|||
|
||||
if (writeop == NULL) {
|
||||
#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);
|
||||
#endif
|
||||
return -1;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
.\"
|
||||
.\" $Id$
|
||||
.\"
|
||||
.Dd November 22, 2021
|
||||
.Dd July 12, 2022
|
||||
.Os
|
||||
.Dt AVRDUDE 1
|
||||
.Sh NAME
|
||||
|
@ -31,6 +31,7 @@
|
|||
.Op Fl B Ar bitclock
|
||||
.Op Fl c Ar programmer-id
|
||||
.Op Fl C Ar config-file
|
||||
.Op Fl A
|
||||
.Op Fl D
|
||||
.Op Fl e
|
||||
.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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
@ -253,7 +254,7 @@ The Teensy bootloader is supported for all AVR boards.
|
|||
As the bootloader does not support reading from flash memory,
|
||||
use the
|
||||
.Fl V
|
||||
option to prevent AVRDUDE from verifing the flash memory.
|
||||
option to prevent AVRDUDE from verifying the flash memory.
|
||||
See the section on
|
||||
.Em extended parameters
|
||||
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
|
||||
several times, the files are read in same order as given on the command
|
||||
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
|
||||
Disable auto erase for flash. When the
|
||||
.Fl U
|
||||
|
@ -389,6 +404,10 @@ use page erase before writing each page so no explicit chip erase
|
|||
is required.
|
||||
Note however that any page not affected by the current operation
|
||||
will retain its previous contents.
|
||||
Setting
|
||||
.Fl D
|
||||
implies
|
||||
.Fl A.
|
||||
.It Fl e
|
||||
Causes a chip erase to be executed. This will reset the contents of the
|
||||
flash ROM and EEPROM to the value
|
||||
|
|
|
@ -5824,6 +5824,8 @@ part
|
|||
|
||||
memory "efuse"
|
||||
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",
|
||||
"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";
|
||||
desc = "ATmega48PB";
|
||||
signature = 0x1e 0x92 0x10;
|
||||
chip_erase_delay = 10500;
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
@ -8441,6 +8444,7 @@ part parent "m88"
|
|||
id = "m88pb";
|
||||
desc = "ATmega88PB";
|
||||
signature = 0x1e 0x93 0x16;
|
||||
chip_erase_delay = 10500;
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
@ -8670,6 +8674,7 @@ part parent "m168"
|
|||
id = "m168pb";
|
||||
desc = "ATmega168PB";
|
||||
signature = 0x1e 0x94 0x15;
|
||||
chip_erase_delay = 10500;
|
||||
;
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
@ -9826,6 +9831,7 @@ part parent "m328"
|
|||
id = "m328pb";
|
||||
desc = "ATmega328PB";
|
||||
signature = 0x1e 0x95 0x16;
|
||||
chip_erase_delay = 10500;
|
||||
|
||||
memory "efuse"
|
||||
size = 1;
|
||||
|
@ -9853,6 +9859,8 @@ part parent "m328"
|
|||
|
||||
memory "efuse"
|
||||
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",
|
||||
"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",
|
||||
|
|
|
@ -917,8 +917,19 @@ static int avrftdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
|||
static int
|
||||
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 };
|
||||
|
||||
/* 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_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,
|
||||
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 poll_index;
|
||||
|
||||
|
@ -1013,22 +1022,12 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|||
|
||||
page_size = m->page_size;
|
||||
|
||||
/* if we do cross a 64k word boundary (or write the
|
||||
* first page), we need to issue a 'load extended
|
||||
* address byte' command, which is defined as 0x4d
|
||||
* 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;
|
||||
}
|
||||
/* on large-flash devices > 128k issue extended address command when needed */
|
||||
if(avrftdi_lext(pgm, p, m, addr/2) < 0)
|
||||
return -1;
|
||||
|
||||
/* prepare the command stream for the whole page */
|
||||
/* addr is in bytes, but we program in words. addr/2 should be something
|
||||
* like addr >> WORD_SHIFT, though */
|
||||
/* addr is in bytes, but we program in words. */
|
||||
for(word = addr/2; word < (len + addr)/2; word++)
|
||||
{
|
||||
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;
|
||||
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 char* o_buf = alloca(buf_size);
|
||||
|
@ -1128,10 +1125,8 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if(use_lext_address && ((address & 0xffff0000))) {
|
||||
if (0 > avrftdi_lext(pgm, p, m, address))
|
||||
return -1;
|
||||
}
|
||||
if(avrftdi_lext(pgm, p, m, addr/2) < 0)
|
||||
return -1;
|
||||
|
||||
/* word addressing! */
|
||||
for(word = addr/2, index = 0; word < (addr + len)/2; word++)
|
||||
|
@ -1210,7 +1205,11 @@ avrftdi_setup(PROGRAMMER * pgm)
|
|||
{
|
||||
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->ftdic = ftdi_new();
|
||||
|
@ -1224,6 +1223,7 @@ avrftdi_setup(PROGRAMMER * pgm)
|
|||
pdata->pin_value = 0;
|
||||
pdata->pin_direction = 0;
|
||||
pdata->led_mask = 0;
|
||||
pdata->lext_byte = 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -81,6 +81,8 @@ typedef struct avrftdi_s {
|
|||
int tx_buffer_size;
|
||||
/* use bitbanging instead of mpsse spi */
|
||||
bool use_bitbanging;
|
||||
/* bits 16-23 of extended 24-bit word flash address for parts with flash > 128k */
|
||||
uint8_t lext_byte;
|
||||
} avrftdi_t;
|
||||
|
||||
void avrftdi_log(int level, const char * func, int line, const char * fmt, ...);
|
||||
|
|
|
@ -321,13 +321,13 @@ via a serial link (@url{https://github.com/ElTangas/jtag2updi}).
|
|||
|
||||
The Micronucleus bootloader is supported for both protocol version V1
|
||||
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}
|
||||
below for Micronucleus specific options.
|
||||
|
||||
The Teensy bootloader is supported for all AVR boards.
|
||||
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}
|
||||
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
|
||||
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
|
||||
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.
|
||||
Note however that any page not affected by the current operation
|
||||
will retain its previous contents.
|
||||
Setting -D implies -A.
|
||||
|
||||
@item -e
|
||||
Causes a chip erase to be executed. This will reset the contents of the
|
||||
|
|
23
src/fileio.c
23
src/fileio.c
|
@ -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)
|
||||
{
|
||||
int rc;
|
||||
int op, rc;
|
||||
FILE * f;
|
||||
char * fname;
|
||||
struct fioparms fio;
|
||||
AVRMEM * mem;
|
||||
int using_stdio;
|
||||
|
||||
op = oprwv == FIO_READ_FOR_VERIFY? FIO_READ: oprwv;
|
||||
mem = avr_locate_mem(p, memtype);
|
||||
if (mem == NULL) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (rc > 0) {
|
||||
if ((op == FIO_READ) && (strcasecmp(mem->desc, "flash") == 0 ||
|
||||
strcasecmp(mem->desc, "application") == 0 ||
|
||||
strcasecmp(mem->desc, "apptable") == 0 ||
|
||||
strcasecmp(mem->desc, "boot") == 0)) {
|
||||
/*
|
||||
* if we are reading flash, just mark the size as being the
|
||||
* highest non-0xff byte
|
||||
*/
|
||||
rc = avr_mem_hiaddr(mem);
|
||||
}
|
||||
/* on reading flash other than for verify set the size to location of highest non-0xff byte */
|
||||
if (rc > 0 && oprwv == FIO_READ) {
|
||||
int hiaddr = avr_mem_hiaddr(mem);
|
||||
|
||||
if(hiaddr < rc) /* if trailing-0xff not disabled */
|
||||
rc = hiaddr;
|
||||
}
|
||||
|
||||
if (format != FMT_IMM && !using_stdio) {
|
||||
fclose(f);
|
||||
}
|
||||
|
|
339
src/ft245r.c
339
src/ft245r.c
|
@ -107,10 +107,10 @@ void ft245r_initpgm(PROGRAMMER * pgm) {
|
|||
|
||||
#else
|
||||
|
||||
#define FT245R_CYCLES 2
|
||||
#define FT245R_FRAGMENT_SIZE 512
|
||||
#define REQ_OUTSTANDINGS 10
|
||||
//#define USE_INLINE_WRITE_PAGE
|
||||
#define FT245R_CYCLES 2
|
||||
#define FT245R_CMD_SIZE (4 * 8*FT245R_CYCLES)
|
||||
#define FT245R_FRAGMENT_SIZE (8 * FT245R_CMD_SIZE)
|
||||
#define REQ_OUTSTANDINGS 10
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
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++) {
|
||||
rc = avr_write_byte_default(pgm, p, m, addr, m->buf[addr]);
|
||||
if (rc != 0) {
|
||||
static int ft245r_paged_write_gen(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (m->paged) {
|
||||
// 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;
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
|
||||
static struct ft245r_request {
|
||||
int addr;
|
||||
int bytes;
|
||||
|
@ -1081,178 +1059,185 @@ static int do_request(PROGRAMMER * pgm, AVRMEM *m) {
|
|||
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;
|
||||
for (i=0; i<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];
|
||||
static int ft245r_paged_write_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
|
||||
|
||||
memset(cmd, 0, 4);
|
||||
avr_set_bits(lext, cmd);
|
||||
avr_set_addr(lext, cmd, addr_wk/2);
|
||||
buf_pos += set_data(pgm, buf+buf_pos, cmd[0]);
|
||||
buf_pos += set_data(pgm, buf+buf_pos, cmd[1]);
|
||||
buf_pos += set_data(pgm, buf+buf_pos, cmd[2]);
|
||||
buf_pos += set_data(pgm, buf+buf_pos, cmd[3]);
|
||||
int i, j, addr_save, buf_pos, req_count, do_page_write;
|
||||
unsigned char buf[FT245R_FRAGMENT_SIZE+1];
|
||||
unsigned char cmd[4];
|
||||
|
||||
if(m->op[AVR_OP_LOADPAGE_LO] == NULL || m->op[AVR_OP_LOADPAGE_HI] == NULL) {
|
||||
avrdude_message(MSG_INFO, "AVR_OP_LOADPAGE_HI/LO command not defined for %s\n", p->desc);
|
||||
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 */
|
||||
buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 9) & 0xff);
|
||||
buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 1) & 0xff);
|
||||
buf_pos += set_data(pgm, buf+buf_pos, 0);
|
||||
}
|
||||
#endif
|
||||
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++;
|
||||
}
|
||||
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;
|
||||
ft245r_send(pgm, buf, buf_pos);
|
||||
put_request(addr_save, buf_pos, 0);
|
||||
|
||||
if(++req_count > REQ_OUTSTANDINGS)
|
||||
do_request(pgm, m);
|
||||
|
||||
if(do_page_write) {
|
||||
while(do_request(pgm, m))
|
||||
continue;
|
||||
if(avr_write_page(pgm, p, m, addr_save - (addr_save % m->page_size)) != 0)
|
||||
return -2;
|
||||
do_page_write = req_count = 0;
|
||||
}
|
||||
#endif
|
||||
req_count = 0;
|
||||
|
||||
// reset buffer variables
|
||||
j = buf_pos = 0;
|
||||
addr_save = addr;
|
||||
}
|
||||
}
|
||||
while (do_request(pgm, m))
|
||||
;
|
||||
return i;
|
||||
|
||||
while(do_request(pgm, m))
|
||||
continue;
|
||||
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
|
||||
static int ft245r_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
|
||||
|
||||
if(!n_bytes)
|
||||
return 0;
|
||||
|
||||
if(strcmp(m->desc, "flash") == 0)
|
||||
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);
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int ft245r_paged_load_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
unsigned int page_size, unsigned int addr,
|
||||
int n_bytes) {
|
||||
unsigned char rbyte;
|
||||
unsigned long i;
|
||||
int rc;
|
||||
static int ft245r_paged_load_gen(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
|
||||
|
||||
for (i=0; i<n_bytes; i++) {
|
||||
rc = avr_read_byte_default(pgm, p, m, i+addr, &rbyte);
|
||||
if (rc != 0) {
|
||||
for(int i=0; i < (int) n_bytes; i++) {
|
||||
unsigned char rbyte;
|
||||
|
||||
if(avr_read_byte_default(pgm, p, m, addr+i, &rbyte) != 0)
|
||||
return -2;
|
||||
}
|
||||
m->buf[i+addr] = rbyte;
|
||||
|
||||
m->buf[addr+i] = rbyte;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ft245r_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
unsigned int page_size, unsigned int addr,
|
||||
unsigned int n_bytes) {
|
||||
unsigned long i,j,n;
|
||||
int addr_save,buf_pos;
|
||||
int req_count = 0;
|
||||
|
||||
static int ft245r_paged_load_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
|
||||
|
||||
int i, j, addr_save, buf_pos, req_count;
|
||||
unsigned char buf[FT245R_FRAGMENT_SIZE+1];
|
||||
unsigned char cmd[4];
|
||||
|
||||
for (i=0; i<n_bytes; ) {
|
||||
buf_pos = 0;
|
||||
addr_save = addr;
|
||||
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);
|
||||
|
||||
if(m->op[AVR_OP_READ_LO] == NULL || m->op[AVR_OP_READ_HI] == NULL) {
|
||||
avrdude_message(MSG_INFO, "AVR_OP_READ_HI/LO command not defined for %s\n", p->desc);
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
static int ft245r_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
unsigned int page_size, unsigned int addr,
|
||||
unsigned int n_bytes) {
|
||||
if (strcmp(m->desc, "flash") == 0) {
|
||||
static int ft245r_paged_load(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
|
||||
|
||||
if(!n_bytes)
|
||||
return 0;
|
||||
|
||||
if(strcmp(m->desc, "flash") == 0)
|
||||
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);
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
void ft245r_initpgm(PROGRAMMER * pgm) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
#define disable_trailing_ff_removal() avr_mem_hiaddr(NULL)
|
||||
int avr_mem_hiaddr(AVRMEM * mem);
|
||||
|
||||
int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p);
|
||||
|
@ -835,7 +836,8 @@ struct fioparms {
|
|||
|
||||
enum {
|
||||
FIO_READ,
|
||||
FIO_WRITE
|
||||
FIO_WRITE,
|
||||
FIO_READ_FOR_VERIFY,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -844,7 +846,7 @@ extern "C" {
|
|||
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -110,7 +110,8 @@ static void usage(void)
|
|||
" -B <bitclock> Specify JTAG/STK500v2 bit clock period (us).\n"
|
||||
" -C <config-file> Specify location of configuration file.\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"
|
||||
" -P <port> Specify connection port.\n"
|
||||
" -F Override invalid signature check.\n"
|
||||
|
@ -442,7 +443,7 @@ int main(int argc, char * argv [])
|
|||
/*
|
||||
* 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) {
|
||||
case 'b': /* override default programmer baud rate */
|
||||
|
@ -528,6 +529,10 @@ int main(int argc, char * argv [])
|
|||
|
||||
case 'D': /* disable auto erase */
|
||||
uflags &= ~UF_AUTO_ERASE;
|
||||
/* fall through */
|
||||
|
||||
case 'A': /* explicit disabling of trailing-0xff removal */
|
||||
disable_trailing_ff_removal();
|
||||
break;
|
||||
|
||||
case 'e': /* perform a chip erase */
|
||||
|
|
|
@ -491,18 +491,15 @@ static int pickit2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
|||
|
||||
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; )
|
||||
{
|
||||
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
|
||||
// the data into packets -- but we need to keep transfers frequent so that we can update the
|
||||
// status indicator bar
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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) {
|
||||
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
|
||||
progname, upd->filename);
|
||||
|
|
Loading…
Reference in New Issue