added TPI support for USBasp (patch #7440)
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@961 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
fc13ef96a1
commit
ddfbdc0b87
|
@ -1,3 +1,9 @@
|
|||
2011-05-28 Thomas Fischl <tfischl@gmx.de>
|
||||
|
||||
Based on patch #7440 commited by Slawomir Fraś:
|
||||
* usbasp.c: added TPI support for USBasp
|
||||
* usbasp.h: (Ditto.)
|
||||
|
||||
2011-05-11 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||
|
||||
* avrdude.conf.in: Add support for ATmega168P.
|
||||
|
|
|
@ -16641,22 +16641,26 @@ part
|
|||
memory "signature"
|
||||
size = 3;
|
||||
offset = 0x3fc0;
|
||||
page_size = 16;
|
||||
;
|
||||
|
||||
memory "fuse"
|
||||
size = 1;
|
||||
offset = 0x3f40;
|
||||
page_size = 16;
|
||||
blocksize = 4;
|
||||
;
|
||||
|
||||
memory "calibration"
|
||||
size = 1;
|
||||
offset = 0x3f80;
|
||||
page_size = 16;
|
||||
;
|
||||
|
||||
memory "lockbits"
|
||||
size = 1;
|
||||
offset = 0x3f00;
|
||||
page_size = 16;
|
||||
;
|
||||
;
|
||||
|
||||
|
@ -16681,22 +16685,26 @@ part
|
|||
memory "signature"
|
||||
size = 3;
|
||||
offset = 0x3fc0;
|
||||
page_size = 16;
|
||||
;
|
||||
|
||||
memory "fuse"
|
||||
size = 1;
|
||||
offset = 0x3f40;
|
||||
page_size = 16;
|
||||
blocksize = 4;
|
||||
;
|
||||
|
||||
memory "calibration"
|
||||
size = 1;
|
||||
offset = 0x3f80;
|
||||
page_size = 16;
|
||||
;
|
||||
|
||||
memory "lockbits"
|
||||
size = 1;
|
||||
offset = 0x3f00;
|
||||
page_size = 16;
|
||||
;
|
||||
;
|
||||
|
||||
|
@ -16721,22 +16729,26 @@ part
|
|||
memory "signature"
|
||||
size = 3;
|
||||
offset = 0x3fc0;
|
||||
page_size = 16;
|
||||
;
|
||||
|
||||
memory "fuse"
|
||||
size = 1;
|
||||
offset = 0x3f40;
|
||||
page_size = 16;
|
||||
blocksize = 4;
|
||||
;
|
||||
|
||||
memory "calibration"
|
||||
size = 1;
|
||||
offset = 0x3f80;
|
||||
page_size = 16;
|
||||
;
|
||||
|
||||
memory "lockbits"
|
||||
size = 1;
|
||||
offset = 0x3f00;
|
||||
page_size = 16;
|
||||
;
|
||||
;
|
||||
|
||||
|
@ -16761,22 +16773,26 @@ part
|
|||
memory "signature"
|
||||
size = 3;
|
||||
offset = 0x3fc0;
|
||||
page_size = 16;
|
||||
;
|
||||
|
||||
memory "fuse"
|
||||
size = 1;
|
||||
offset = 0x3f40;
|
||||
page_size = 16;
|
||||
blocksize = 4;
|
||||
;
|
||||
|
||||
memory "calibration"
|
||||
size = 1;
|
||||
offset = 0x3f80;
|
||||
page_size = 16;
|
||||
;
|
||||
|
||||
memory "lockbits"
|
||||
size = 1;
|
||||
offset = 0x3f00;
|
||||
page_size = 16;
|
||||
;
|
||||
;
|
||||
|
||||
|
|
436
usbasp.c
436
usbasp.c
|
@ -106,11 +106,56 @@ struct pdata
|
|||
#else
|
||||
usb_dev_handle *usbhandle;
|
||||
#endif
|
||||
int sckfreq_hz;
|
||||
int sckfreq_hz;
|
||||
unsigned int capabilities;
|
||||
int use_tpi;
|
||||
};
|
||||
|
||||
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
|
||||
#define IMPORT_PDATA(pgm) struct pdata *pdata = PDATA(pgm)
|
||||
|
||||
|
||||
|
||||
/* Prototypes */
|
||||
// interface - management
|
||||
static void usbasp_setup(PROGRAMMER * pgm);
|
||||
static void usbasp_teardown(PROGRAMMER * pgm);
|
||||
// internal functions
|
||||
static int usbasp_transmit(PROGRAMMER * pgm, unsigned char receive, unsigned char functionid, unsigned char send[4], unsigned char * buffer, int buffersize);
|
||||
#ifdef USE_LIBUSB_1_0
|
||||
static int usbOpenDevice(libusb_device_handle **device, int vendor, char *vendorName, int product, char *productName);
|
||||
#else
|
||||
static int usbOpenDevice(usb_dev_handle **device, int vendor, char *vendorName, int product, char *productName);
|
||||
#endif
|
||||
// interface - prog.
|
||||
static int usbasp_open(PROGRAMMER * pgm, char * port);
|
||||
static void usbasp_close(PROGRAMMER * pgm);
|
||||
// dummy functions
|
||||
static void usbasp_disable(PROGRAMMER * pgm);
|
||||
static void usbasp_enable(PROGRAMMER * pgm);
|
||||
static void usbasp_display(PROGRAMMER * pgm, const char * p);
|
||||
// universal functions
|
||||
static int usbasp_initialize(PROGRAMMER * pgm, AVRPART * p);
|
||||
// SPI specific functions
|
||||
static int usbasp_spi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]);
|
||||
static int usbasp_spi_program_enable(PROGRAMMER * pgm, AVRPART * p);
|
||||
static int usbasp_spi_chip_erase(PROGRAMMER * pgm, AVRPART * p);
|
||||
static int usbasp_spi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes);
|
||||
static int usbasp_spi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes);
|
||||
static int usbasp_spi_set_sck_period(PROGRAMMER *pgm, double sckperiod);
|
||||
// TPI specific functions
|
||||
static void usbasp_tpi_send_byte(PROGRAMMER * pgm, uint8_t b);
|
||||
static int usbasp_tpi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]);
|
||||
static int usbasp_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p);
|
||||
static int usbasp_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p);
|
||||
static int usbasp_tpi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes);
|
||||
static int usbasp_tpi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes);
|
||||
static int usbasp_tpi_set_sck_period(PROGRAMMER *pgm, double sckperiod);
|
||||
static int usbasp_tpi_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned long addr, unsigned char * value);
|
||||
static int usbasp_tpi_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned long addr, unsigned char data);
|
||||
|
||||
|
||||
/* Interface - management */
|
||||
static void usbasp_setup(PROGRAMMER * pgm)
|
||||
{
|
||||
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
|
||||
|
@ -127,7 +172,7 @@ static void usbasp_teardown(PROGRAMMER * pgm)
|
|||
free(pgm->cookie);
|
||||
}
|
||||
|
||||
|
||||
/* Internal functions */
|
||||
/*
|
||||
* wrapper for usb_control_msg call
|
||||
*/
|
||||
|
@ -333,6 +378,8 @@ static int didUsbInit = 0;
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Interface - prog. */
|
||||
static int usbasp_open(PROGRAMMER * pgm, char * port)
|
||||
{
|
||||
#ifdef USE_LIBUSB_1_0
|
||||
|
@ -377,13 +424,18 @@ static int usbasp_open(PROGRAMMER * pgm, char * port)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void usbasp_close(PROGRAMMER * pgm)
|
||||
{
|
||||
if (PDATA(pgm)->usbhandle!=NULL) {
|
||||
unsigned char temp[4];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
usbasp_transmit(pgm, 1, USBASP_FUNC_DISCONNECT, temp, temp, sizeof(temp));
|
||||
|
||||
if (PDATA(pgm)->use_tpi) {
|
||||
usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_DISCONNECT, temp, temp, sizeof(temp));
|
||||
} else {
|
||||
usbasp_transmit(pgm, 1, USBASP_FUNC_DISCONNECT, temp, temp, sizeof(temp));
|
||||
}
|
||||
|
||||
#ifdef USE_LIBUSB_1_0
|
||||
libusb_close(PDATA(pgm)->usbhandle);
|
||||
#else
|
||||
|
@ -393,24 +445,7 @@ static void usbasp_close(PROGRAMMER * pgm)
|
|||
}
|
||||
|
||||
|
||||
static int usbasp_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
|
||||
unsigned char temp[4];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
|
||||
/* set sck period */
|
||||
pgm->set_sck_period(pgm, pgm->bitclock);
|
||||
|
||||
/* connect to target device */
|
||||
usbasp_transmit(pgm, 1, USBASP_FUNC_CONNECT, temp, temp, sizeof(temp));
|
||||
|
||||
/* wait, so device is ready to receive commands */
|
||||
usleep(100000);
|
||||
|
||||
return pgm->program_enable(pgm, p);
|
||||
}
|
||||
|
||||
/* Dummy functions */
|
||||
static void usbasp_disable(PROGRAMMER * pgm)
|
||||
{
|
||||
/* Do nothing. */
|
||||
|
@ -431,7 +466,75 @@ static void usbasp_display(PROGRAMMER * pgm, const char * p)
|
|||
}
|
||||
|
||||
|
||||
static int usbasp_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
/* Universal functions: for both SPI and TPI */
|
||||
static int usbasp_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
int dly;
|
||||
unsigned char temp[4];
|
||||
unsigned char res[4];
|
||||
IMPORT_PDATA(pgm);
|
||||
|
||||
|
||||
/* get capabilities */
|
||||
memset(temp, 0, sizeof(temp));
|
||||
if(usbasp_transmit(pgm, 1, USBASP_FUNC_GETCAPABILITIES, temp, res, sizeof(res)) == 4)
|
||||
pdata->capabilities = res[0] | ((unsigned int)res[1] << 8) | ((unsigned int)res[2] << 16) | ((unsigned int)res[3] << 24);
|
||||
else
|
||||
pdata->capabilities = 0;
|
||||
|
||||
pdata->use_tpi = ((pdata->capabilities & USBASP_CAP_TPI) != 0 && (p->flags & AVRPART_HAS_TPI) != 0) ? 1 : 0;
|
||||
|
||||
if(pdata->use_tpi)
|
||||
{
|
||||
/* calc tpiclk delay */
|
||||
dly = 1500000.0 * pgm->bitclock;
|
||||
if(dly < 1)
|
||||
dly = 1;
|
||||
else if(dly > 2047)
|
||||
dly = 2047;
|
||||
temp[0] = dly;
|
||||
temp[1] = dly >> 8;
|
||||
|
||||
/* connect */
|
||||
usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_CONNECT, temp, res, sizeof(res));
|
||||
|
||||
/* change interface */
|
||||
pgm->program_enable = usbasp_tpi_program_enable;
|
||||
pgm->chip_erase = usbasp_tpi_chip_erase;
|
||||
pgm->cmd = usbasp_tpi_cmd;
|
||||
pgm->read_byte = usbasp_tpi_read_byte;
|
||||
pgm->write_byte = usbasp_tpi_write_byte;
|
||||
pgm->paged_write = usbasp_tpi_paged_write;
|
||||
pgm->paged_load = usbasp_tpi_paged_load;
|
||||
pgm->set_sck_period = usbasp_tpi_set_sck_period;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set sck period */
|
||||
pgm->set_sck_period(pgm, pgm->bitclock);
|
||||
|
||||
/* connect to target device */
|
||||
usbasp_transmit(pgm, 1, USBASP_FUNC_CONNECT, temp, res, sizeof(res));
|
||||
|
||||
/* change interface */
|
||||
pgm->program_enable = usbasp_spi_program_enable;
|
||||
pgm->chip_erase = usbasp_spi_chip_erase;
|
||||
pgm->cmd = usbasp_spi_cmd;
|
||||
pgm->read_byte = avr_read_byte_default;
|
||||
pgm->write_byte = avr_write_byte_default;
|
||||
pgm->paged_write = usbasp_spi_paged_write;
|
||||
pgm->paged_load = usbasp_spi_paged_load;
|
||||
pgm->set_sck_period = usbasp_spi_set_sck_period;
|
||||
}
|
||||
|
||||
/* wait, so device is ready to receive commands */
|
||||
usleep(100000);
|
||||
|
||||
return pgm->program_enable(pgm, p);
|
||||
}
|
||||
|
||||
/* SPI specific functions */
|
||||
static int usbasp_spi_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
||||
unsigned char res[4])
|
||||
{
|
||||
int nbytes =
|
||||
|
@ -446,8 +549,7 @@ static int usbasp_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
static int usbasp_spi_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char res[4];
|
||||
unsigned char cmd[4];
|
||||
|
@ -468,8 +570,7 @@ static int usbasp_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
static int usbasp_spi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
|
@ -490,8 +591,7 @@ static int usbasp_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
static int usbasp_spi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
int n;
|
||||
|
@ -557,7 +657,7 @@ static int usbasp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|||
return n_bytes;
|
||||
}
|
||||
|
||||
static int usbasp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
static int usbasp_spi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||
int page_size, int n_bytes)
|
||||
{
|
||||
int n;
|
||||
|
@ -630,7 +730,6 @@ static int usbasp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|||
return n_bytes;
|
||||
}
|
||||
|
||||
|
||||
/* The list of SCK frequencies in Hz supported by USBasp */
|
||||
static struct sckoptions_t usbaspSCKoptions[] = {
|
||||
{ USBASP_ISP_SCK_1500, 1500000 },
|
||||
|
@ -647,12 +746,11 @@ static struct sckoptions_t usbaspSCKoptions[] = {
|
|||
{ USBASP_ISP_SCK_0_5, 500 }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Set sck period (in seconds)
|
||||
* Find next possible sck period and write it to the programmer.
|
||||
*/
|
||||
static int usbasp_set_sck_period(PROGRAMMER *pgm, double sckperiod)
|
||||
static int usbasp_spi_set_sck_period(PROGRAMMER *pgm, double sckperiod)
|
||||
{
|
||||
char clockoption = USBASP_ISP_SCK_AUTO;
|
||||
unsigned char res[4];
|
||||
|
@ -714,6 +812,266 @@ static int usbasp_set_sck_period(PROGRAMMER *pgm, double sckperiod)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* TPI specific functions */
|
||||
static void usbasp_tpi_send_byte(PROGRAMMER * pgm, uint8_t b)
|
||||
{
|
||||
unsigned char temp[4];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
|
||||
temp[0] = b;
|
||||
|
||||
usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_RAWWRITE, temp, temp, sizeof(temp));
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_tpi_recv_byte(PROGRAMMER * pgm)
|
||||
{
|
||||
unsigned char temp[4];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
|
||||
if(usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_RAWREAD, temp, temp, sizeof(temp)) != 1)
|
||||
{
|
||||
fprintf(stderr, "%s: error: wrong responds size\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return temp[0];
|
||||
}
|
||||
|
||||
|
||||
static int usbasp_tpi_nvm_waitbusy(PROGRAMMER * pgm)
|
||||
{
|
||||
int retry;
|
||||
|
||||
|
||||
for(retry=50; retry>0; retry--)
|
||||
{
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SIN(NVMCSR));
|
||||
if(usbasp_tpi_recv_byte(pgm) & NVMCSR_BSY)
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int usbasp_tpi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4])
|
||||
{
|
||||
fprintf(stderr, "%s: error: spi_cmd used in TPI mode: not allowed\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int usbasp_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
int retry;
|
||||
|
||||
|
||||
/* change guard time */
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SSTCS(TPIPCR));
|
||||
usbasp_tpi_send_byte(pgm, TPIPCR_GT_2b);
|
||||
|
||||
/* send SKEY */
|
||||
usbasp_tpi_send_byte(pgm, 0xE0);
|
||||
usbasp_tpi_send_byte(pgm, 0xFF);
|
||||
usbasp_tpi_send_byte(pgm, 0x88);
|
||||
usbasp_tpi_send_byte(pgm, 0xD8);
|
||||
usbasp_tpi_send_byte(pgm, 0xCD);
|
||||
usbasp_tpi_send_byte(pgm, 0x45);
|
||||
usbasp_tpi_send_byte(pgm, 0xAB);
|
||||
usbasp_tpi_send_byte(pgm, 0x89);
|
||||
usbasp_tpi_send_byte(pgm, 0x12);
|
||||
|
||||
/* check if device is ready */
|
||||
for(retry=0; retry<10; retry++)
|
||||
{
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SLDCS(TPIIR));
|
||||
if(usbasp_tpi_recv_byte(pgm) != 0x80)
|
||||
continue;
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SLDCS(TPISR));
|
||||
if((usbasp_tpi_recv_byte(pgm) & TPISR_NVMEN) == 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if(retry >= 10)
|
||||
{
|
||||
fprintf(stderr, "%s: error: programm enable: target doesn't answer.\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbasp_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
/* Set PR to flash */
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(0));
|
||||
usbasp_tpi_send_byte(pgm, 0x01);
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(1));
|
||||
usbasp_tpi_send_byte(pgm, 0x40);
|
||||
/* select ERASE */
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SOUT(NVMCMD));
|
||||
usbasp_tpi_send_byte(pgm, NVMCMD_CHIP_ERASE);
|
||||
/* dummy write */
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SST_INC);
|
||||
usbasp_tpi_send_byte(pgm, 0x00);
|
||||
usbasp_tpi_nvm_waitbusy(pgm);
|
||||
|
||||
usleep(p->chip_erase_delay);
|
||||
pgm->initialize(pgm, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbasp_tpi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char* dptr;
|
||||
int readed, clen, n;
|
||||
uint16_t pr;
|
||||
|
||||
|
||||
dptr = m->buf;
|
||||
pr = m->offset;
|
||||
readed = 0;
|
||||
|
||||
while(readed < n_bytes)
|
||||
{
|
||||
clen = n_bytes - readed;
|
||||
if(clen > 32)
|
||||
clen = 32;
|
||||
|
||||
/* prepare READBLOCK cmd */
|
||||
cmd[0] = pr & 0xFF;
|
||||
cmd[1] = pr >> 8;
|
||||
cmd[2] = 0;
|
||||
cmd[3] = 0;
|
||||
n = usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_READBLOCK, cmd, dptr, clen);
|
||||
if(n != clen)
|
||||
{
|
||||
fprintf(stderr, "%s: error: wrong reading bytes %x\n", progname, n);
|
||||
return -3;
|
||||
}
|
||||
|
||||
readed += clen;
|
||||
pr += clen;
|
||||
dptr += clen;
|
||||
|
||||
report_progress(readed, n_bytes, NULL);
|
||||
}
|
||||
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
static int usbasp_tpi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
unsigned char dummy[8];
|
||||
unsigned char* sptr;
|
||||
int writed, clen, n;
|
||||
uint16_t pr;
|
||||
|
||||
|
||||
sptr = m->buf;
|
||||
pr = m->offset;
|
||||
writed = 0;
|
||||
|
||||
/* Set PR to flash */
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(0));
|
||||
usbasp_tpi_send_byte(pgm, (pr & 0xFF) | 1 );
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(1));
|
||||
usbasp_tpi_send_byte(pgm, (pr >> 8) );
|
||||
/* select SECTIONERASE */
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SOUT(NVMCMD));
|
||||
usbasp_tpi_send_byte(pgm, NVMCMD_SECTION_ERASE);
|
||||
/* dummy write */
|
||||
usbasp_tpi_send_byte(pgm, TPI_OP_SST);
|
||||
usbasp_tpi_send_byte(pgm, 0x00);
|
||||
usbasp_tpi_nvm_waitbusy(pgm);
|
||||
|
||||
usleep(p->chip_erase_delay);
|
||||
|
||||
while(writed < n_bytes)
|
||||
{
|
||||
clen = n_bytes - writed;
|
||||
if(clen > 32)
|
||||
clen = 32;
|
||||
|
||||
/* prepare WRITEBLOCK cmd */
|
||||
cmd[0] = pr & 0xFF;
|
||||
cmd[1] = pr >> 8;
|
||||
cmd[2] = 0;
|
||||
cmd[3] = 0;
|
||||
n = usbasp_transmit(pgm, 0, USBASP_FUNC_TPI_WRITEBLOCK, cmd, sptr, clen);
|
||||
if(n != clen)
|
||||
{
|
||||
fprintf(stderr, "%s: error: wrong count at writing %x\n", progname, n);
|
||||
return -3;
|
||||
}
|
||||
|
||||
writed += clen;
|
||||
pr += clen;
|
||||
sptr += clen;
|
||||
|
||||
report_progress(writed, n_bytes, NULL);
|
||||
}
|
||||
|
||||
/* finishing write */
|
||||
while(( clen = (-pr) & (m->page_size-1) ) != 0)
|
||||
{
|
||||
if(clen > 8)
|
||||
clen = 8;
|
||||
|
||||
memset(dummy, 0xFF, clen);
|
||||
|
||||
cmd[0] = pr & 0xFF;
|
||||
cmd[1] = pr >> 8;
|
||||
cmd[2] = 0;
|
||||
cmd[3] = 0;
|
||||
n = usbasp_transmit(pgm, 0, USBASP_FUNC_TPI_WRITEBLOCK, cmd, dummy, clen);
|
||||
if(n != clen)
|
||||
{
|
||||
fprintf(stderr, "%s: error: wrong count at writing %x\n", progname, n);
|
||||
return -3;
|
||||
}
|
||||
|
||||
pr += clen;
|
||||
}
|
||||
|
||||
return n_bytes;
|
||||
}
|
||||
|
||||
static int usbasp_tpi_set_sck_period(PROGRAMMER *pgm, double sckperiod)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int usbasp_tpi_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned long addr, unsigned char * value)
|
||||
{
|
||||
unsigned char cmd[4];
|
||||
int n;
|
||||
uint16_t pr;
|
||||
|
||||
|
||||
pr = m->offset + addr;
|
||||
|
||||
/* READBLOCK */
|
||||
cmd[0] = pr & 0xFF;
|
||||
cmd[1] = pr >> 8;
|
||||
cmd[2] = 0;
|
||||
cmd[3] = 0;
|
||||
n = usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_READBLOCK, cmd, value, 1);
|
||||
if(n != 1)
|
||||
{
|
||||
fprintf(stderr, "%s: error: wrong reading bytes %x\n", progname, n);
|
||||
return -3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbasp_tpi_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned long addr, unsigned char data)
|
||||
{
|
||||
fprintf(stderr, "%s: error: usbasp_write_byte in TPI mode: all writes have to be done at page level\n", progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void usbasp_initpgm(PROGRAMMER * pgm)
|
||||
{
|
||||
|
@ -727,9 +1085,9 @@ void usbasp_initpgm(PROGRAMMER * pgm)
|
|||
pgm->display = usbasp_display;
|
||||
pgm->enable = usbasp_enable;
|
||||
pgm->disable = usbasp_disable;
|
||||
pgm->program_enable = usbasp_program_enable;
|
||||
pgm->chip_erase = usbasp_chip_erase;
|
||||
pgm->cmd = usbasp_cmd;
|
||||
pgm->program_enable = usbasp_spi_program_enable;
|
||||
pgm->chip_erase = usbasp_spi_chip_erase;
|
||||
pgm->cmd = usbasp_spi_cmd;
|
||||
pgm->open = usbasp_open;
|
||||
pgm->close = usbasp_close;
|
||||
pgm->read_byte = avr_read_byte_default;
|
||||
|
@ -739,11 +1097,11 @@ void usbasp_initpgm(PROGRAMMER * pgm)
|
|||
* optional functions
|
||||
*/
|
||||
|
||||
pgm->paged_write = usbasp_paged_write;
|
||||
pgm->paged_load = usbasp_paged_load;
|
||||
pgm->paged_write = usbasp_spi_paged_write;
|
||||
pgm->paged_load = usbasp_spi_paged_load;
|
||||
pgm->setup = usbasp_setup;
|
||||
pgm->teardown = usbasp_teardown;
|
||||
pgm->set_sck_period = usbasp_set_sck_period;
|
||||
pgm->set_sck_period = usbasp_spi_set_sck_period;
|
||||
|
||||
}
|
||||
|
||||
|
|
57
usbasp.h
57
usbasp.h
|
@ -45,6 +45,16 @@
|
|||
#define USBASP_FUNC_WRITEEEPROM 8
|
||||
#define USBASP_FUNC_SETLONGADDRESS 9
|
||||
#define USBASP_FUNC_SETISPSCK 10
|
||||
#define USBASP_FUNC_TPI_CONNECT 11
|
||||
#define USBASP_FUNC_TPI_DISCONNECT 12
|
||||
#define USBASP_FUNC_TPI_RAWREAD 13
|
||||
#define USBASP_FUNC_TPI_RAWWRITE 14
|
||||
#define USBASP_FUNC_TPI_READBLOCK 15
|
||||
#define USBASP_FUNC_TPI_WRITEBLOCK 16
|
||||
#define USBASP_FUNC_GETCAPABILITIES 127
|
||||
|
||||
/* USBASP capabilities */
|
||||
#define USBASP_CAP_TPI 0x01
|
||||
|
||||
/* Block mode flags */
|
||||
#define USBASP_BLOCKFLAG_FIRST 1
|
||||
|
@ -69,6 +79,53 @@
|
|||
#define USBASP_ISP_SCK_750 11 /* 750 kHz */
|
||||
#define USBASP_ISP_SCK_1500 12 /* 1.5 MHz */
|
||||
|
||||
/* TPI instructions */
|
||||
#define TPI_OP_SLD 0x20
|
||||
#define TPI_OP_SLD_INC 0x24
|
||||
#define TPI_OP_SST 0x60
|
||||
#define TPI_OP_SST_INC 0x64
|
||||
#define TPI_OP_SSTPR(a) (0x68 | (a))
|
||||
#define TPI_OP_SIN(a) (0x10 | (((a)<<1)&0x60) | ((a)&0x0F) )
|
||||
#define TPI_OP_SOUT(a) (0x90 | (((a)<<1)&0x60) | ((a)&0x0F) )
|
||||
#define TPI_OP_SLDCS(a) (0x80 | ((a)&0x0F) )
|
||||
#define TPI_OP_SSTCS(a) (0xC0 | ((a)&0x0F) )
|
||||
#define TPI_OP_SKEY 0xE0
|
||||
|
||||
/* TPI control/status registers */
|
||||
#define TPIIR 0xF
|
||||
#define TPIPCR 0x2
|
||||
#define TPISR 0x0
|
||||
|
||||
// TPIPCR bits
|
||||
#define TPIPCR_GT_2 0x04
|
||||
#define TPIPCR_GT_1 0x02
|
||||
#define TPIPCR_GT_0 0x01
|
||||
#define TPIPCR_GT_128b 0x00
|
||||
#define TPIPCR_GT_64b 0x01
|
||||
#define TPIPCR_GT_32b 0x02
|
||||
#define TPIPCR_GT_16b 0x03
|
||||
#define TPIPCR_GT_8b 0x04
|
||||
#define TPIPCR_GT_4b 0x05
|
||||
#define TPIPCR_GT_2b 0x06
|
||||
#define TPIPCR_GT_0b 0x07
|
||||
|
||||
// TPISR bits
|
||||
#define TPISR_NVMEN 0x02
|
||||
|
||||
/* NVM registers */
|
||||
#define NVMCSR 0x32
|
||||
#define NVMCMD 0x33
|
||||
|
||||
// NVMCSR bits
|
||||
#define NVMCSR_BSY 0x80
|
||||
|
||||
// NVMCMD values
|
||||
#define NVMCMD_NOP 0x00
|
||||
#define NVMCMD_CHIP_ERASE 0x10
|
||||
#define NVMCMD_SECTION_ERASE 0x14
|
||||
#define NVMCMD_WORD_WRITE 0x1D
|
||||
|
||||
|
||||
typedef struct sckoptions_t {
|
||||
int id;
|
||||
double frequency;
|
||||
|
|
Loading…
Reference in New Issue