Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
/*
|
|
|
|
* avrdude - A Downloader/Uploader for AVR device programmers
|
|
|
|
* Copyright (C) 2005 Erik Walthinsen
|
|
|
|
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
2005-05-10 20:58:45 +00:00
|
|
|
/* $Id$ */
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
/* Based on Id: stk500.c,v 1.46 2004/12/22 01:52:45 bdean Exp */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* avrdude interface for Atmel STK500V2 programmer
|
|
|
|
*
|
|
|
|
* Note: most commands use the "universal command" feature of the
|
|
|
|
* programmer in a "pass through" mode, exceptions are "program
|
|
|
|
* enable", "paged read", and "paged write".
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ac_cfg.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
#include "avr.h"
|
|
|
|
#include "pgm.h"
|
|
|
|
#include "stk500_private.h" // temp until all code converted
|
|
|
|
#include "stk500v2_private.h"
|
|
|
|
#include "serial.h"
|
|
|
|
|
|
|
|
#define STK500V2_XTAL 7372800U
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
#define DEBUG(format,args...) fprintf(stderr, format, ## args)
|
|
|
|
#else
|
|
|
|
#define DEBUG(format,args...)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
#define DEBUGRECV(format,args...) fprintf(stderr, format, ## args)
|
|
|
|
#else
|
|
|
|
#define DEBUGRECV(format,args...)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
extern int verbose;
|
|
|
|
extern char * progname;
|
|
|
|
extern int do_cycles;
|
|
|
|
|
|
|
|
static unsigned char command_sequence = 1;
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value);
|
|
|
|
static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value);
|
|
|
|
static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p);
|
|
|
|
static int stk500v2_is_page_empty(unsigned int address, int page_size,
|
|
|
|
const unsigned char *buf);
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
|
|
|
{
|
|
|
|
unsigned char buf[275 + 6]; // max MESSAGE_BODY of 275 bytes, 6 bytes overhead
|
|
|
|
int i;
|
|
|
|
|
|
|
|
buf[0] = MESSAGE_START;
|
|
|
|
buf[1] = command_sequence;
|
|
|
|
buf[2] = len / 256;
|
|
|
|
buf[3] = len % 256;
|
|
|
|
buf[4] = TOKEN;
|
|
|
|
memcpy(buf+5, data, len);
|
|
|
|
|
|
|
|
// calculate the XOR checksum
|
|
|
|
buf[5+len] = 0;
|
|
|
|
for (i=0;i<5+len;i++)
|
|
|
|
buf[5+len] ^= buf[i];
|
|
|
|
|
|
|
|
DEBUG("STK500V2: stk500v2_send(");
|
|
|
|
for (i=0;i<len+6;i++) DEBUG("0x%02x ",buf[i]);
|
|
|
|
DEBUG(", %d)\n",len+6);
|
|
|
|
|
|
|
|
if (serial_send(pgm->fd, buf, len+6) != 0) {
|
|
|
|
fprintf(stderr,"%s: stk500_send(): failed to send command to serial port\n",progname);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_drain(PROGRAMMER * pgm, int display)
|
|
|
|
{
|
|
|
|
return serial_drain(pgm->fd, display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) {
|
|
|
|
enum states { sINIT, sSTART, sSEQNUM, sSIZE1, sSIZE2, sTOKEN, sDATA, sCSUM, sDONE } state = sSTART;
|
|
|
|
int msglen = 0;
|
|
|
|
int curlen = 0;
|
|
|
|
int timeout = 0;
|
|
|
|
unsigned char c, checksum = 0;
|
|
|
|
|
|
|
|
long timeoutval = 5; // seconds
|
|
|
|
struct timeval tv;
|
|
|
|
double tstart, tnow;
|
|
|
|
|
|
|
|
DEBUG("STK500V2: stk500v2_recv(): ");
|
|
|
|
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
tstart = tv.tv_sec;
|
|
|
|
|
|
|
|
while ( (state != sDONE ) && (!timeout) ) {
|
2005-05-11 17:09:22 +00:00
|
|
|
if (serial_recv(pgm->fd, &c, 1) < 0)
|
|
|
|
goto timedout;
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
DEBUG("0x%02x ",c);
|
|
|
|
checksum ^= c;
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case sSTART:
|
|
|
|
DEBUGRECV("hoping for start token...");
|
|
|
|
if (c == MESSAGE_START) {
|
|
|
|
DEBUGRECV("got it\n");
|
|
|
|
checksum = MESSAGE_START;
|
|
|
|
state = sSEQNUM;
|
|
|
|
} else
|
|
|
|
DEBUGRECV("sorry\n");
|
|
|
|
break;
|
|
|
|
case sSEQNUM:
|
|
|
|
DEBUGRECV("hoping for sequence...\n");
|
|
|
|
if (c == command_sequence) {
|
|
|
|
DEBUGRECV("got it, incrementing\n");
|
|
|
|
state = sSIZE1;
|
|
|
|
command_sequence++;
|
|
|
|
} else {
|
|
|
|
DEBUGRECV("sorry\n");
|
|
|
|
state = sSTART;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case sSIZE1:
|
|
|
|
DEBUGRECV("hoping for size LSB\n");
|
|
|
|
msglen = c*256;
|
|
|
|
state = sSIZE2;
|
|
|
|
break;
|
|
|
|
case sSIZE2:
|
|
|
|
DEBUGRECV("hoping for size MSB...");
|
|
|
|
msglen += c;
|
|
|
|
DEBUG(" msg is %d bytes\n",msglen);
|
|
|
|
state = sTOKEN;
|
|
|
|
break;
|
|
|
|
case sTOKEN:
|
|
|
|
if (c == TOKEN) state = sDATA;
|
|
|
|
else state = sSTART;
|
|
|
|
break;
|
|
|
|
case sDATA:
|
|
|
|
if (curlen < maxsize) {
|
|
|
|
msg[curlen] = c;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "%s: stk500v2_recv(): buffer too small, received %d byte into %d byte buffer\n",
|
|
|
|
progname,curlen,maxsize);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if ((curlen == 0) && (msg[0] == ANSWER_CKSUM_ERROR)) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_recv(): previous packet sent with wrong checksum\n",
|
|
|
|
progname);
|
|
|
|
return -3;
|
|
|
|
}
|
|
|
|
curlen++;
|
|
|
|
if (curlen == msglen) state = sCSUM;
|
|
|
|
break;
|
|
|
|
case sCSUM:
|
|
|
|
if (checksum == 0) {
|
|
|
|
state = sDONE;
|
|
|
|
} else {
|
|
|
|
state = sSTART;
|
|
|
|
fprintf(stderr, "%s: stk500v2_recv(): checksum error\n",
|
|
|
|
progname);
|
|
|
|
return -4;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "%s: stk500v2_recv(): unknown state\n",
|
|
|
|
progname);
|
|
|
|
return -5;
|
|
|
|
} /* switch */
|
|
|
|
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
tnow = tv.tv_sec;
|
|
|
|
if (tnow-tstart > timeoutval) { // wuff - signed/unsigned/overflow
|
2005-05-11 17:09:22 +00:00
|
|
|
timedout:
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
fprintf(stderr, "%s: stk500_2_ReceiveMessage(): timeout\n",
|
|
|
|
progname);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* while */
|
|
|
|
DEBUG("\n");
|
|
|
|
|
|
|
|
return msglen+6;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_getsync(PROGRAMMER * pgm) {
|
|
|
|
int tries = 0;
|
|
|
|
unsigned char buf[1], resp[32];
|
|
|
|
int status;
|
|
|
|
|
|
|
|
DEBUG("STK500V2: stk500v2_getsync()\n");
|
|
|
|
|
|
|
|
retry:
|
|
|
|
tries++;
|
|
|
|
|
|
|
|
// send the sync command and see if we can get there
|
|
|
|
buf[0] = CMD_SIGN_ON;
|
|
|
|
stk500v2_send(pgm, buf, 1);
|
|
|
|
|
|
|
|
// try to get the response back and see where we got
|
|
|
|
status = stk500v2_recv(pgm, resp, sizeof(resp));
|
|
|
|
|
|
|
|
// if we got bytes returned, check to see what came back
|
|
|
|
if (status > 0) {
|
2005-07-26 02:56:29 +00:00
|
|
|
if ((resp[0] == CMD_SIGN_ON) && (resp[1] == STATUS_CMD_OK)) {
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
// success!
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
if (tries > 33) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: stk500v2_getsync(): can't communicate with device: resp=0x%02x\n",
|
|
|
|
progname, resp[0]);
|
|
|
|
return -6;
|
|
|
|
} else
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
// or if we got a timeout
|
|
|
|
} else if (status == -1) {
|
|
|
|
if (tries > 33) {
|
|
|
|
fprintf(stderr,"%s: stk500v2_getsync(): timeout communicating with programmer\n",
|
|
|
|
progname);
|
|
|
|
return -1;
|
|
|
|
} else
|
|
|
|
goto retry;
|
|
|
|
|
|
|
|
// or any other error
|
|
|
|
} else {
|
|
|
|
if (tries > 33) {
|
|
|
|
fprintf(stderr,"%s: stk500v2_getsync(): error communicating with programmer: (%d)\n",
|
|
|
|
progname,status);
|
|
|
|
} else
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int stk500v2_command(PROGRAMMER * pgm, char * buf, size_t len, size_t maxlen) {
|
|
|
|
int i;
|
|
|
|
int tries = 0;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
DEBUG("STK500V2: stk500v2_command(");
|
|
|
|
for (i=0;i<len;i++) DEBUG("0x%02hhx ",buf[i]);
|
|
|
|
DEBUG(", %d)\n",len);
|
|
|
|
|
|
|
|
retry:
|
|
|
|
tries++;
|
|
|
|
|
|
|
|
// send the command to the programmer
|
|
|
|
stk500v2_send(pgm,buf,len);
|
|
|
|
|
|
|
|
// attempt to read the status back
|
|
|
|
status = stk500v2_recv(pgm,buf,maxlen);
|
|
|
|
|
|
|
|
// if we got a successful readback, return
|
|
|
|
if (status > 0) {
|
|
|
|
DEBUG(" = %d\n",status);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise try to sync up again
|
|
|
|
status = stk500v2_getsync(pgm);
|
|
|
|
if (status != 0) {
|
|
|
|
if (tries > 33) {
|
|
|
|
fprintf(stderr,"%s: stk500v2_command(): failed miserably to execute command 0x%02x\n",
|
|
|
|
progname,buf[0]);
|
|
|
|
return -1;
|
|
|
|
} else
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG(" = 0\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int stk500v2_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
|
|
|
|
unsigned char res[4])
|
|
|
|
{
|
|
|
|
unsigned char buf[8];
|
|
|
|
int result;
|
|
|
|
|
|
|
|
DEBUG("STK500V2: stk500v2_cmd(%02x,%02x,%02x,%02x)\n",cmd[0],cmd[1],cmd[2],cmd[3]);
|
|
|
|
|
|
|
|
buf[0] = CMD_SPI_MULTI;
|
|
|
|
buf[1] = 4;
|
|
|
|
buf[2] = 4;
|
|
|
|
buf[3] = 0;
|
|
|
|
buf[4] = cmd[0];
|
|
|
|
buf[5] = cmd[1];
|
|
|
|
buf[6] = cmd[2];
|
|
|
|
buf[7] = cmd[3];
|
|
|
|
|
|
|
|
result = stk500v2_command(pgm, buf, 8, sizeof(buf));
|
|
|
|
if (buf[1] != STATUS_CMD_OK) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_cmd(): failed to send command\n",
|
|
|
|
progname);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
res[0] = buf[2];
|
|
|
|
res[1] = buf[3];
|
|
|
|
res[2] = buf[4];
|
|
|
|
res[3] = buf[5];
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* issue the 'chip erase' command to the AVR device
|
|
|
|
*/
|
|
|
|
static int stk500v2_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
|
|
|
{
|
|
|
|
int result;
|
|
|
|
unsigned char buf[16];
|
|
|
|
|
|
|
|
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_chip_erase: chip erase instruction not defined for part \"%s\"\n",
|
|
|
|
progname, p->desc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pgm->pgm_led(pgm, ON);
|
|
|
|
|
|
|
|
buf[0] = CMD_CHIP_ERASE_ISP;
|
|
|
|
buf[1] = p->chip_erase_delay / 1000;
|
|
|
|
buf[2] = 0; // use delay (?)
|
|
|
|
avr_set_bits(p->op[AVR_OP_CHIP_ERASE], buf+3);
|
|
|
|
result = stk500v2_command(pgm, buf, 7, sizeof(buf));
|
|
|
|
usleep(p->chip_erase_delay);
|
|
|
|
pgm->initialize(pgm, p);
|
|
|
|
|
|
|
|
pgm->pgm_led(pgm, OFF);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* issue the 'program enable' command to the AVR device
|
|
|
|
*/
|
|
|
|
static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
|
|
|
{
|
|
|
|
unsigned char buf[16];
|
|
|
|
|
|
|
|
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_program_enable(): program enable instruction not defined for part \"%s\"\n",
|
|
|
|
progname, p->desc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[0] = CMD_ENTER_PROGMODE_ISP;
|
|
|
|
buf[1] = p->timeout;
|
|
|
|
buf[2] = p->stabdelay;
|
|
|
|
buf[3] = p->cmdexedelay;
|
|
|
|
buf[4] = p->synchloops;
|
|
|
|
buf[5] = p->bytedelay;
|
|
|
|
buf[6] = p->pollvalue;
|
|
|
|
buf[7] = p->pollindex;
|
|
|
|
avr_set_bits(p->op[AVR_OP_PGM_ENABLE], buf+8);
|
|
|
|
|
|
|
|
return stk500v2_command(pgm, buf, 12, sizeof(buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* initialize the AVR device and prepare it to accept commands
|
|
|
|
*/
|
|
|
|
static int stk500v2_initialize(PROGRAMMER * pgm, AVRPART * p)
|
|
|
|
{
|
|
|
|
return pgm->program_enable(pgm, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void stk500v2_disable(PROGRAMMER * pgm)
|
|
|
|
{
|
|
|
|
unsigned char buf[16];
|
|
|
|
int result;
|
|
|
|
|
|
|
|
buf[0] = CMD_LEAVE_PROGMODE_ISP;
|
|
|
|
buf[1] = 1; // preDelay;
|
|
|
|
buf[2] = 1; // postDelay;
|
|
|
|
|
|
|
|
result = stk500v2_command(pgm, buf, 3, sizeof(buf));
|
|
|
|
|
|
|
|
if (buf[1] != STATUS_CMD_OK) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_disable(): failed to leave programming mode, got 0x%02x\n",
|
|
|
|
progname,buf[1]);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void stk500v2_enable(PROGRAMMER * pgm)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_open(PROGRAMMER * pgm, char * port)
|
|
|
|
{
|
|
|
|
DEBUG("STK500V2: stk500v2_open()\n");
|
|
|
|
|
|
|
|
strcpy(pgm->port, port);
|
|
|
|
if (pgm->baudrate)
|
|
|
|
pgm->fd = serial_open(port, pgm->baudrate);
|
|
|
|
else
|
|
|
|
pgm->fd = serial_open(port, 115200);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* drain any extraneous input
|
|
|
|
*/
|
|
|
|
stk500v2_drain(pgm, 0);
|
|
|
|
|
|
|
|
stk500v2_getsync(pgm);
|
|
|
|
|
|
|
|
stk500v2_drain(pgm, 0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void stk500v2_close(PROGRAMMER * pgm)
|
|
|
|
{
|
|
|
|
DEBUG("STK500V2: stk500v2_close()\n");
|
|
|
|
|
|
|
|
serial_close(pgm->fd);
|
|
|
|
pgm->fd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_loadaddr(PROGRAMMER * pgm, unsigned int addr)
|
|
|
|
{
|
|
|
|
unsigned char buf[16];
|
|
|
|
int result;
|
|
|
|
|
|
|
|
DEBUG("STK500V2: stk500v2_loadaddr(%d)\n",addr);
|
|
|
|
|
|
|
|
buf[0] = CMD_LOAD_ADDRESS;
|
|
|
|
buf[1] = (addr >> 24) & 0xff;
|
|
|
|
buf[2] = (addr >> 16) & 0xff;
|
|
|
|
buf[3] = (addr >> 8) & 0xff;
|
|
|
|
buf[4] = addr & 0xff;
|
|
|
|
|
|
|
|
result = stk500v2_command(pgm, buf, 5, sizeof(buf));
|
|
|
|
|
|
|
|
if (buf[1] != STATUS_CMD_OK) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_loadaddr(): failed to set load address, got 0x%02x\n",
|
|
|
|
progname,buf[1]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|
|
|
int page_size, int n_bytes)
|
|
|
|
{
|
2005-08-28 22:23:35 +00:00
|
|
|
int addr, block_size, last_addr;
|
|
|
|
int a_div=1;
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
unsigned char commandbuf[10];
|
|
|
|
unsigned char buf[266];
|
|
|
|
unsigned char cmds[4];
|
|
|
|
int result;
|
|
|
|
|
|
|
|
DEBUG("STK500V2: stk500v2_paged_write(..,%s,%d,%d)\n",m->desc,page_size,n_bytes);
|
|
|
|
|
|
|
|
if (page_size == 0) page_size = 256;
|
|
|
|
|
|
|
|
// determine which command is to be used
|
|
|
|
if (strcmp(m->desc, "flash") == 0) {
|
2005-08-28 22:23:35 +00:00
|
|
|
a_div=2;
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
commandbuf[0] = CMD_PROGRAM_FLASH_ISP;
|
|
|
|
} else if (strcmp(m->desc, "eeprom") == 0) {
|
|
|
|
commandbuf[0] = CMD_PROGRAM_EEPROM_ISP;
|
|
|
|
}
|
|
|
|
commandbuf[4] = m->delay;
|
|
|
|
|
|
|
|
// if the memory is paged, load the appropriate commands into the buffer
|
|
|
|
if (m->mode & 0x01) {
|
|
|
|
commandbuf[3] = m->mode | 0x80; // yes, write the stupid page to flash
|
|
|
|
|
|
|
|
if (m->op[AVR_OP_LOADPAGE_LO] == NULL) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_paged_write: loadpage instruction not defined for part \"%s\"\n",
|
|
|
|
progname, p->desc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
avr_set_bits(m->op[AVR_OP_LOADPAGE_LO], cmds);
|
|
|
|
commandbuf[5] = cmds[0];
|
|
|
|
|
|
|
|
if (m->op[AVR_OP_WRITEPAGE] == NULL) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_paged_write: write page instruction not defined for part \"%s\"\n",
|
|
|
|
progname, p->desc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
avr_set_bits(m->op[AVR_OP_WRITEPAGE], cmds);
|
|
|
|
commandbuf[6] = cmds[0];
|
|
|
|
|
|
|
|
// otherwise, we need to load different commands in
|
|
|
|
} else {
|
|
|
|
commandbuf[3] = m->mode | 0x80; // yes, write the stupid words to flash
|
|
|
|
|
|
|
|
if (m->op[AVR_OP_WRITE_LO] == NULL) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_paged_write: write instruction not defined for part \"%s\"\n",
|
|
|
|
progname, p->desc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
avr_set_bits(m->op[AVR_OP_WRITE_LO], cmds);
|
2005-08-28 22:23:35 +00:00
|
|
|
commandbuf[5] = cmds[0];
|
|
|
|
commandbuf[6] = 0;
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// the read command is common to both methods
|
|
|
|
if (m->op[AVR_OP_READ_LO] == NULL) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_paged_write: read instruction not defined for part \"%s\"\n",
|
|
|
|
progname, p->desc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
avr_set_bits(m->op[AVR_OP_READ_LO], cmds);
|
|
|
|
commandbuf[7] = cmds[0];
|
|
|
|
|
|
|
|
commandbuf[8] = m->readback[0];
|
|
|
|
commandbuf[9] = m->readback[1];
|
|
|
|
|
2005-08-28 22:23:35 +00:00
|
|
|
last_addr=-1;
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
|
|
|
|
for (addr=0; addr < n_bytes; addr += page_size) {
|
|
|
|
report_progress(addr,n_bytes,NULL);
|
|
|
|
|
|
|
|
if ((n_bytes-addr) < page_size)
|
|
|
|
block_size = n_bytes - addr;
|
|
|
|
else
|
|
|
|
block_size = page_size;
|
2005-08-28 22:23:35 +00:00
|
|
|
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
DEBUG("block_size at addr %d is %d\n",addr,block_size);
|
|
|
|
|
2005-08-28 22:23:35 +00:00
|
|
|
if(commandbuf[0] == CMD_PROGRAM_FLASH_ISP){
|
|
|
|
if (stk500v2_is_page_empty(addr, block_size, m->buf)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
memcpy(buf,commandbuf,sizeof(commandbuf));
|
|
|
|
|
|
|
|
buf[1] = block_size >> 8;
|
|
|
|
buf[2] = block_size & 0xff;
|
|
|
|
|
2005-08-28 22:23:35 +00:00
|
|
|
if((last_addr==-1)||(last_addr+block_size != addr)){
|
|
|
|
stk500v2_loadaddr(pgm, addr/a_div);
|
|
|
|
}
|
|
|
|
last_addr=addr;
|
|
|
|
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
memcpy(buf+10,m->buf+addr, block_size);
|
|
|
|
|
|
|
|
result = stk500v2_command(pgm,buf,block_size+10, sizeof(buf));
|
|
|
|
if (buf[1] != STATUS_CMD_OK) {
|
|
|
|
fprintf(stderr,"%s: stk500v2_paged_write: write command failed with %d\n",
|
|
|
|
progname,buf[1]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return n_bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int stk500v2_is_page_empty(unsigned int address, int page_size,
|
|
|
|
const unsigned char *buf)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < page_size; i++) {
|
|
|
|
if(buf[address + i] != 0xFF) {
|
|
|
|
/* Page is not empty. */
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Page is empty. */
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int stk500v2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|
|
|
int page_size, int n_bytes)
|
|
|
|
{
|
|
|
|
int addr, block_size;
|
|
|
|
unsigned char commandbuf[4];
|
|
|
|
unsigned char buf[275]; // max buffer size for stk500v2 at this point
|
|
|
|
unsigned char cmds[4];
|
2005-08-28 22:23:35 +00:00
|
|
|
int result;
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
|
|
|
|
DEBUG("STK500V2: stk500v2_paged_load(..,%s,%d,%d)\n",m->desc,page_size,n_bytes);
|
|
|
|
|
|
|
|
page_size = m->readsize;
|
|
|
|
|
|
|
|
// determine which command is to be used
|
|
|
|
if (strcmp(m->desc, "flash") == 0) {
|
|
|
|
commandbuf[0] = CMD_READ_FLASH_ISP;
|
|
|
|
} else if (strcmp(m->desc, "eeprom") == 0) {
|
|
|
|
commandbuf[0] = CMD_READ_EEPROM_ISP;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the read command is common to both methods
|
|
|
|
if (m->op[AVR_OP_READ_LO] == NULL) {
|
2005-08-28 22:23:35 +00:00
|
|
|
fprintf(stderr, "%s: stk500v2_paged_load: read instruction not defined for part \"%s\"\n",
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
progname, p->desc);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
avr_set_bits(m->op[AVR_OP_READ_LO], cmds);
|
|
|
|
commandbuf[3] = cmds[0];
|
|
|
|
|
|
|
|
stk500v2_loadaddr(pgm, 0);
|
|
|
|
|
|
|
|
for (addr=0; addr < n_bytes; addr += page_size) {
|
|
|
|
report_progress(addr, n_bytes,NULL);
|
|
|
|
|
|
|
|
if ((n_bytes-addr) < page_size)
|
|
|
|
block_size = n_bytes - addr;
|
|
|
|
else
|
|
|
|
block_size = page_size;
|
|
|
|
DEBUG("block_size at addr %d is %d\n",addr,block_size);
|
|
|
|
|
|
|
|
memcpy(buf,commandbuf,sizeof(commandbuf));
|
|
|
|
|
|
|
|
buf[1] = block_size >> 8;
|
|
|
|
buf[2] = block_size & 0xff;
|
|
|
|
|
|
|
|
result = stk500v2_command(pgm,buf,4,sizeof(buf));
|
|
|
|
if (buf[1] != STATUS_CMD_OK) {
|
2005-08-28 22:23:35 +00:00
|
|
|
fprintf(stderr,"%s: stk500v2_paged_load: read command failed with %d\n",
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
progname,buf[1]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
for (i=0;i<page_size;i++) {
|
|
|
|
fprintf(stderr,"%02X",buf[2+i]);
|
|
|
|
if (i%16 == 15) fprintf(stderr,"\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
memcpy(&m->buf[addr], &buf[2], block_size);
|
|
|
|
}
|
|
|
|
|
2005-08-28 22:23:35 +00:00
|
|
|
return n_bytes;
|
Mega-commit to bring in both, the STK500v2 support from Erik
Walthinsen, as well as JTAG ICE mkII support (by me).
Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).
The JTAG ICE mkII support should be considered alpha to beta quality
at this point. Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required. Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).
Note that for the JTAG ICE, I did change a few things in the internal
API. Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation). Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character. The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery. The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@451 81a1dc3b-b13d-400b-aceb-764788c761c2
2005-05-10 19:17:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_set_vtarget(PROGRAMMER * pgm, double v)
|
|
|
|
{
|
|
|
|
unsigned char uaref, utarg;
|
|
|
|
|
|
|
|
utarg = (unsigned)((v + 0.049) * 10);
|
|
|
|
|
|
|
|
if (stk500v2_getparm(pgm, PARAM_VADJUST, &uaref) != 0) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: stk500v2_set_vtarget(): cannot obtain V[aref]\n",
|
|
|
|
progname);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uaref > utarg) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: stk500v2_set_vtarget(): reducing V[aref] from %.1f to %.1f\n",
|
|
|
|
progname, uaref / 10.0, v);
|
|
|
|
if (stk500v2_setparm(pgm, PARAM_VADJUST, utarg)
|
|
|
|
!= 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return stk500v2_setparm(pgm, PARAM_VTARGET, utarg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_set_varef(PROGRAMMER * pgm, double v)
|
|
|
|
{
|
|
|
|
unsigned char uaref, utarg;
|
|
|
|
|
|
|
|
uaref = (unsigned)((v + 0.049) * 10);
|
|
|
|
|
|
|
|
if (stk500v2_getparm(pgm, PARAM_VTARGET, &utarg) != 0) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: stk500v2_set_varef(): cannot obtain V[target]\n",
|
|
|
|
progname);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uaref > utarg) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: stk500v2_set_varef(): V[aref] must not be greater than "
|
|
|
|
"V[target] = %.1f\n",
|
|
|
|
progname, utarg / 10.0);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return stk500v2_setparm(pgm, PARAM_VADJUST, uaref);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_set_fosc(PROGRAMMER * pgm, double v)
|
|
|
|
{
|
|
|
|
int fosc;
|
|
|
|
unsigned char prescale, cmatch;
|
|
|
|
static unsigned ps[] = {
|
|
|
|
1, 8, 32, 64, 128, 256, 1024
|
|
|
|
};
|
|
|
|
int idx, rc;
|
|
|
|
|
|
|
|
prescale = cmatch = 0;
|
|
|
|
if (v > 0.0) {
|
|
|
|
if (v > STK500V2_XTAL / 2) {
|
|
|
|
const char *unit;
|
|
|
|
if (v > 1e6) {
|
|
|
|
v /= 1e6;
|
|
|
|
unit = "MHz";
|
|
|
|
} else if (v > 1e3) {
|
|
|
|
v /= 1e3;
|
|
|
|
unit = "kHz";
|
|
|
|
} else
|
|
|
|
unit = "Hz";
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: stk500v2_set_fosc(): f = %.3f %s too high, using %.3f MHz\n",
|
|
|
|
progname, v, unit, STK500V2_XTAL / 2e6);
|
|
|
|
fosc = STK500V2_XTAL / 2;
|
|
|
|
} else
|
|
|
|
fosc = (unsigned)v;
|
|
|
|
|
|
|
|
for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) {
|
|
|
|
if (fosc >= STK500V2_XTAL / (256 * ps[idx] * 2)) {
|
|
|
|
/* this prescaler value can handle our frequency */
|
|
|
|
prescale = idx + 1;
|
|
|
|
cmatch = (unsigned)(STK500V2_XTAL / (2 * fosc * ps[idx])) - 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (idx == sizeof(ps) / sizeof(ps[0])) {
|
|
|
|
fprintf(stderr, "%s: stk500v2_set_fosc(): f = %u Hz too low, %u Hz min\n",
|
|
|
|
progname, fosc, STK500V2_XTAL / (256 * 1024 * 2));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((rc = stk500v2_setparm(pgm, PARAM_OSC_PSCALE, prescale)) != 0
|
|
|
|
|| (rc = stk500v2_setparm(pgm, PARAM_OSC_CMATCH, cmatch)) != 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* This code assumes that each count of the SCK duration parameter
|
|
|
|
represents 8/f, where f is the clock frequency of the STK500V2 master
|
|
|
|
processors (not the target). This number comes from Atmel
|
|
|
|
application note AVR061. It appears that the STK500V2 bit bangs SCK.
|
|
|
|
For small duration values, the actual SCK width is larger than
|
|
|
|
expected. As the duration value increases, the SCK width error
|
|
|
|
diminishes. */
|
|
|
|
static int stk500v2_set_sck_period(PROGRAMMER * pgm, double v)
|
|
|
|
{
|
|
|
|
unsigned char dur;
|
|
|
|
double min, max;
|
|
|
|
|
|
|
|
min = 8.0 / STK500V2_XTAL;
|
|
|
|
max = 255 * min;
|
|
|
|
dur = v / min + 0.5;
|
|
|
|
|
|
|
|
if (v < min) {
|
|
|
|
dur = 1;
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: stk500v2_set_sck_period(): p = %.1f us too small, using %.1f us\n",
|
|
|
|
progname, v / 1e-6, dur * min / 1e-6);
|
|
|
|
} else if (v > max) {
|
|
|
|
dur = 255;
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: stk500v2_set_sck_period(): p = %.1f us too large, using %.1f us\n",
|
|
|
|
progname, v / 1e-6, dur * min / 1e-6);
|
|
|
|
}
|
|
|
|
|
|
|
|
return stk500v2_setparm(pgm, PARAM_SCK_DURATION, dur);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value)
|
|
|
|
{
|
|
|
|
unsigned char buf[32];
|
|
|
|
|
|
|
|
buf[0] = CMD_GET_PARAMETER;
|
|
|
|
buf[1] = parm;
|
|
|
|
|
|
|
|
if (stk500v2_command(pgm, buf, 2, sizeof(buf)) < 0) {
|
|
|
|
fprintf(stderr,"%s: stk500v2_getparm(): failed to get parameter 0x%02x\n",
|
|
|
|
progname, parm);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*value = buf[2];
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value)
|
|
|
|
{
|
|
|
|
unsigned char buf[32];
|
|
|
|
|
|
|
|
buf[0] = CMD_SET_PARAMETER;
|
|
|
|
buf[1] = parm;
|
|
|
|
buf[2] = value;
|
|
|
|
|
|
|
|
if (stk500v2_command(pgm, buf, 3, sizeof(buf)) < 0) {
|
|
|
|
fprintf(stderr, "\n%s: stk500v2_setparm(): failed to set parameter 0x%02x\n",
|
|
|
|
progname, parm);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void stk500v2_display(PROGRAMMER * pgm, char * p)
|
|
|
|
{
|
|
|
|
unsigned char maj, min, hdw, topcard;
|
|
|
|
const char *topcard_name;
|
|
|
|
|
|
|
|
stk500v2_getparm(pgm, PARAM_HW_VER, &hdw);
|
|
|
|
stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
|
|
|
|
stk500v2_getparm(pgm, PARAM_SW_MINOR, &min);
|
|
|
|
stk500v2_getparm(pgm, PARAM_TOPCARD_DETECT, &topcard);
|
|
|
|
|
|
|
|
fprintf(stderr, "%sHardware Version: %d\n", p, hdw);
|
|
|
|
fprintf(stderr, "%sFirmware Version: %d.%d\n", p, maj, min);
|
|
|
|
|
|
|
|
if (1) { // should check to see if it's a stk500 first
|
|
|
|
switch (topcard) {
|
|
|
|
case 0xAA: topcard_name = "STK501"; break;
|
|
|
|
case 0x55: topcard_name = "STK502"; break;
|
|
|
|
case 0xFA: topcard_name = "STK503"; break;
|
|
|
|
case 0xEE: topcard_name = "STK504"; break;
|
|
|
|
case 0xE4: topcard_name = "STK505"; break;
|
|
|
|
case 0xDD: topcard_name = "STK520"; break;
|
|
|
|
default: topcard_name = "Unknown"; break;
|
|
|
|
}
|
|
|
|
fprintf(stderr, "%sTopcard : %s\n", p, topcard_name);
|
|
|
|
}
|
|
|
|
stk500v2_print_parms1(pgm, p);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p)
|
|
|
|
{
|
|
|
|
unsigned char vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
|
|
|
|
|
|
|
|
stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
|
|
|
|
stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust);
|
|
|
|
stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale);
|
|
|
|
stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch);
|
|
|
|
stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
|
|
|
|
|
|
|
|
fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0);
|
|
|
|
fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0);
|
|
|
|
fprintf(stderr, "%sOscillator : ", p);
|
|
|
|
if (osc_pscale == 0)
|
|
|
|
fprintf(stderr, "Off\n");
|
|
|
|
else {
|
|
|
|
int prescale = 1;
|
|
|
|
double f = STK500V2_XTAL / 2;
|
|
|
|
const char *unit;
|
|
|
|
|
|
|
|
switch (osc_pscale) {
|
|
|
|
case 2: prescale = 8; break;
|
|
|
|
case 3: prescale = 32; break;
|
|
|
|
case 4: prescale = 64; break;
|
|
|
|
case 5: prescale = 128; break;
|
|
|
|
case 6: prescale = 256; break;
|
|
|
|
case 7: prescale = 1024; break;
|
|
|
|
}
|
|
|
|
f /= prescale;
|
|
|
|
f /= (osc_cmatch + 1);
|
|
|
|
if (f > 1e6) {
|
|
|
|
f /= 1e6;
|
|
|
|
unit = "MHz";
|
|
|
|
} else if (f > 1e3) {
|
|
|
|
f /= 1000;
|
|
|
|
unit = "kHz";
|
|
|
|
} else
|
|
|
|
unit = "Hz";
|
|
|
|
fprintf(stderr, "%.3f %s\n", f, unit);
|
|
|
|
}
|
|
|
|
fprintf(stderr, "%sSCK period : %.1f us\n", p,
|
|
|
|
sck_duration * 8.0e6 / STK500V2_XTAL + 0.05);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void stk500v2_print_parms(PROGRAMMER * pgm)
|
|
|
|
{
|
|
|
|
stk500v2_print_parms1(pgm, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void stk500v2_initpgm(PROGRAMMER * pgm)
|
|
|
|
{
|
|
|
|
strcpy(pgm->type, "STK500V2");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* mandatory functions
|
|
|
|
*/
|
|
|
|
pgm->initialize = stk500v2_initialize;
|
|
|
|
pgm->display = stk500v2_display;
|
|
|
|
pgm->enable = stk500v2_enable;
|
|
|
|
pgm->disable = stk500v2_disable;
|
|
|
|
pgm->program_enable = stk500v2_program_enable;
|
|
|
|
pgm->chip_erase = stk500v2_chip_erase;
|
|
|
|
pgm->cmd = stk500v2_cmd;
|
|
|
|
pgm->open = stk500v2_open;
|
|
|
|
pgm->close = stk500v2_close;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* optional functions
|
|
|
|
*/
|
|
|
|
pgm->paged_write = stk500v2_paged_write;
|
|
|
|
pgm->paged_load = stk500v2_paged_load;
|
|
|
|
pgm->print_parms = stk500v2_print_parms;
|
|
|
|
pgm->set_vtarget = stk500v2_set_vtarget;
|
|
|
|
pgm->set_varef = stk500v2_set_varef;
|
|
|
|
pgm->set_fosc = stk500v2_set_fosc;
|
|
|
|
pgm->set_sck_period = stk500v2_set_sck_period;
|
|
|
|
pgm->page_size = 256;
|
|
|
|
}
|