Merge branch 'avrdudes:main' into terminal
This commit is contained in:
commit
feb38b83ef
8
NEWS
8
NEWS
|
@ -32,8 +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 #474
|
- Fix avrftdi support for ATmega2560 et al #998
|
||||||
- Fix avrdude.conf timings for ATmega328PB and other parts #976
|
- 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:
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
|
|
33
src/avr.c
33
src/avr.c
|
@ -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 ||
|
|
||||||
strcasecmp(mem->desc, "application") == 0 ||
|
|
||||||
strcasecmp(mem->desc, "apptable") == 0 ||
|
|
||||||
strcasecmp(mem->desc, "boot") == 0)
|
|
||||||
return avr_mem_hiaddr(mem);
|
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 ||
|
|
||||||
strcasecmp(mem->desc, "application") == 0 ||
|
|
||||||
strcasecmp(mem->desc, "apptable") == 0 ||
|
|
||||||
strcasecmp(mem->desc, "boot") == 0)
|
|
||||||
return avr_mem_hiaddr(mem);
|
return avr_mem_hiaddr(mem);
|
||||||
else
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
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)
|
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);
|
||||||
}
|
}
|
||||||
|
|
277
src/ft245r.c
277
src/ft245r.c
|
@ -108,9 +108,9 @@ 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 FT245R_FRAGMENT_SIZE (8 * FT245R_CMD_SIZE)
|
||||||
#define REQ_OUTSTANDINGS 10
|
#define REQ_OUTSTANDINGS 10
|
||||||
//#define USE_INLINE_WRITE_PAGE
|
|
||||||
|
|
||||||
#define FT245R_DEBUG 0
|
#define FT245R_DEBUG 0
|
||||||
/*
|
/*
|
||||||
|
@ -992,39 +992,17 @@ 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,
|
static int ft245r_paged_write_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) {
|
||||||
unsigned int n_bytes) {
|
|
||||||
unsigned long i, pa;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
for (i=0; i<n_bytes; i++, addr++) {
|
for(int i=0; i < (int) n_bytes; i++, addr++)
|
||||||
rc = avr_write_byte_default(pgm, p, m, addr, m->buf[addr]);
|
if(avr_write_byte_default(pgm, p, m, addr, m->buf[addr]) != 0)
|
||||||
if (rc != 0) {
|
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
|
return n_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ft245r_request {
|
static struct ft245r_request {
|
||||||
int addr;
|
int addr;
|
||||||
|
@ -1081,179 +1059,186 @@ static int do_request(PROGRAMMER * pgm, AVRMEM *m) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ft245r_paged_write_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
static int ft245r_paged_write_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
||||||
int page_size, int addr, int n_bytes) {
|
unsigned int page_size, unsigned int addr, unsigned 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;
|
int i, j, addr_save, buf_pos, req_count, do_page_write;
|
||||||
for (i=0; i<n_bytes; ) {
|
unsigned char buf[FT245R_FRAGMENT_SIZE+1];
|
||||||
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];
|
unsigned char cmd[4];
|
||||||
OPCODE *lext = m->op[AVR_OP_LOAD_EXT_ADDR];
|
|
||||||
|
|
||||||
memset(cmd, 0, 4);
|
if(m->op[AVR_OP_LOADPAGE_LO] == NULL || m->op[AVR_OP_LOADPAGE_HI] == NULL) {
|
||||||
avr_set_bits(lext, cmd);
|
avrdude_message(MSG_INFO, "AVR_OP_LOADPAGE_HI/LO command not defined for %s\n", p->desc);
|
||||||
avr_set_addr(lext, cmd, addr_wk/2);
|
return -1;
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
buf_pos += set_data(pgm, buf+buf_pos, 0x4C); /* Issue Page Write */
|
|
||||||
buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 9) & 0xff);
|
do_page_write = req_count = i = j = buf_pos = 0;
|
||||||
buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 1) & 0xff);
|
addr_save = addr;
|
||||||
buf_pos += set_data(pgm, buf+buf_pos, 0);
|
while(i < (int) n_bytes) {
|
||||||
}
|
int spi = addr&1? AVR_OP_LOADPAGE_HI: AVR_OP_LOADPAGE_LO;
|
||||||
#endif
|
|
||||||
|
// 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) {
|
if(i >= n_bytes) {
|
||||||
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down
|
ft245r_out = SET_BITS_0(ft245r_out, pgm, PIN_AVR_SCK, 0); // SCK down
|
||||||
buf[buf_pos++] = ft245r_out;
|
buf[buf_pos++] = ft245r_out;
|
||||||
}
|
} else {
|
||||||
else {
|
// stretch sequence to allow correct readout, see extract_data()
|
||||||
/* stretch sequence to allow correct readout, see extract_data() */
|
|
||||||
buf[buf_pos] = buf[buf_pos - 1];
|
buf[buf_pos] = buf[buf_pos - 1];
|
||||||
buf_pos++;
|
buf_pos++;
|
||||||
}
|
}
|
||||||
ft245r_send(pgm, buf, buf_pos);
|
ft245r_send(pgm, buf, buf_pos);
|
||||||
put_request(addr_save, buf_pos, 0);
|
put_request(addr_save, buf_pos, 0);
|
||||||
//ft245r_sync(pgm);
|
|
||||||
#if 0
|
if(++req_count > REQ_OUTSTANDINGS)
|
||||||
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);
|
do_request(pgm, m);
|
||||||
|
|
||||||
if(do_page_write) {
|
if(do_page_write) {
|
||||||
#if defined(USE_INLINE_WRITE_PAGE)
|
|
||||||
while(do_request(pgm, m))
|
while(do_request(pgm, m))
|
||||||
;
|
continue;
|
||||||
ft245r_usleep(pgm, m->max_write_delay);
|
if(avr_write_page(pgm, p, m, addr_save - (addr_save % m->page_size)) != 0)
|
||||||
#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;
|
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))
|
while(do_request(pgm, m))
|
||||||
;
|
continue;
|
||||||
return i;
|
|
||||||
|
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[addr+i] = rbyte;
|
||||||
}
|
}
|
||||||
m->buf[i+addr] = rbyte;
|
|
||||||
}
|
|
||||||
return 0;
|
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;
|
|
||||||
unsigned char buf[FT245R_FRAGMENT_SIZE+1];
|
|
||||||
|
|
||||||
for (i=0; i<n_bytes; ) {
|
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];
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
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;
|
addr_save = addr;
|
||||||
for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) {
|
while(i < (int) n_bytes) {
|
||||||
if (i >= n_bytes) break;
|
int spi = addr&1? AVR_OP_READ_HI: AVR_OP_READ_LO;
|
||||||
buf_pos += set_data(pgm, buf+buf_pos, (addr & 1)?0x28:0x20 );
|
|
||||||
buf_pos += set_data(pgm, buf+buf_pos, (addr >> 9) & 0xff );
|
// put the SPI read command as FT245R_CMD_SIZE bytes into buffer
|
||||||
buf_pos += set_data(pgm, buf+buf_pos, (addr >> 1) & 0xff );
|
memset(cmd, 0, sizeof cmd);
|
||||||
buf_pos += set_data(pgm, buf+buf_pos, 0);
|
avr_set_bits(m->op[spi], cmd);
|
||||||
addr ++;
|
avr_set_addr(m->op[spi], cmd, addr/2);
|
||||||
i++;
|
for(int k=0; k<sizeof cmd; k++)
|
||||||
}
|
buf_pos += set_data(pgm, buf+buf_pos, cmd[k]);
|
||||||
if (i >= n_bytes) {
|
|
||||||
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down
|
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;
|
buf[buf_pos++] = ft245r_out;
|
||||||
}
|
} else {
|
||||||
else {
|
// stretch sequence to allow correct readout, see extract_data()
|
||||||
/* stretch sequence to allow correct readout, see extract_data() */
|
|
||||||
buf[buf_pos] = buf[buf_pos - 1];
|
buf[buf_pos] = buf[buf_pos - 1];
|
||||||
buf_pos++;
|
buf_pos++;
|
||||||
}
|
}
|
||||||
n = j;
|
|
||||||
ft245r_send(pgm, buf, buf_pos);
|
ft245r_send(pgm, buf, buf_pos);
|
||||||
put_request(addr_save, buf_pos, n);
|
put_request(addr_save, buf_pos, j);
|
||||||
req_count++;
|
|
||||||
if (req_count > REQ_OUTSTANDINGS)
|
if(++req_count > REQ_OUTSTANDINGS)
|
||||||
do_request(pgm, m);
|
do_request(pgm, m);
|
||||||
|
|
||||||
|
// reset buffer variables
|
||||||
|
j = buf_pos = 0;
|
||||||
|
addr_save = addr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while(do_request(pgm, m))
|
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) {
|
||||||
strcpy(pgm->type, "ftdi_syncbb");
|
strcpy(pgm->type, "ftdi_syncbb");
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
for (addr_base = addr; addr_base < max_addr; )
|
if (lext) {
|
||||||
{
|
|
||||||
if ((addr_base == 0 || (addr_base % /*ext_address_boundary*/ 65536) == 0)
|
|
||||||
&& lext != NULL)
|
|
||||||
{
|
|
||||||
memset(cmd, 0, sizeof(cmd));
|
memset(cmd, 0, sizeof(cmd));
|
||||||
|
|
||||||
avr_set_bits(lext, cmd);
|
avr_set_bits(lext, cmd);
|
||||||
avr_set_addr(lext, cmd, addr_base);
|
avr_set_addr(lext, cmd, addr/2);
|
||||||
pgm->cmd(pgm, cmd, res);
|
pgm->cmd(pgm, cmd, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (addr_base = addr; addr_base < max_addr; )
|
||||||
|
{
|
||||||
// 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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue