Merge pull request #1018 from stefanrueger/issue995
Fix Issue #995 ft245r paged read for ATmega2560 et al
This commit is contained in:
commit
04f790ad85
339
src/ft245r.c
339
src/ft245r.c
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue