Contributed by dcm@mit.edu: add support for the

AVRISP mkII device. (Savannah patch #4789.)
* serial.h: Declare usb_serdev_frame device descriptor.
* stk500v2.c: Implementation of the AVRISP mkII handling.
* usb_libusb.c: Add USB handling for short-frame delimited
AVRISP mkII USB protocol; add distinction of different
devices in usbdev_open().
* jtagmkII.c: Tell usbdev_open() to search for the JTAG ICE mkII.
* usbdevs.h: (New file.)
* Makefile.am: Add usbdevs.h, as well as some other forgotten
files "make distcheck" complained about.
* avrdude.conf.in: Add more aliases for the AVRISP mkII.
* avrdude.1: Document how to use the AVRISP mkII.
* doc/avrdude.texi: (Ditto.)


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@564 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Joerg Wunsch 2006-01-12 23:13:50 +00:00
parent d5965b20b9
commit d98636cfad
10 changed files with 368 additions and 43 deletions

View File

@ -1,3 +1,20 @@
2006-01-13 Joerg Wunsch <j@uriah.heep.sax.de>
Contributed by dcm@mit.edu: add support for the
AVRISP mkII device. (Savannah patch #4789.)
* serial.h: Declare usb_serdev_frame device descriptor.
* stk500v2.c: Implementation of the AVRISP mkII handling.
* usb_libusb.c: Add USB handling for short-frame delimited
AVRISP mkII USB protocol; add distinction of different
devices in usbdev_open().
* jtagmkII.c: Tell usbdev_open() to search for the JTAG ICE mkII.
* usbdevs.h: (New file.)
* Makefile.am: Add usbdevs.h, as well as some other forgotten
files "make distcheck" complained about.
* avrdude.conf.in: Add more aliases for the AVRISP mkII.
* avrdude.1: Document how to use the AVRISP mkII.
* doc/avrdude.texi: (Ditto.)
2006-01-12 Joerg Wunsch <j@uriah.heep.sax.de>
* avrdude.conf.in: Add EEPROM page instructions for the

View File

@ -22,6 +22,7 @@
#
EXTRA_DIST = \
ChangeLog \
ChangeLog-2001 \
ChangeLog-2002 \
ChangeLog-2003 \
@ -69,6 +70,7 @@ avrdude_SOURCES = \
crc16.h \
fileio.c \
fileio.h \
freebsd_ppi.h \
jtagmkI.c \
jtagmkI.h \
jtagmkI_private.h \
@ -95,6 +97,7 @@ avrdude_SOURCES = \
serbb_win32.c \
ser_posix.c \
ser_win32.c \
solaris_ecpp.h \
stk500.c \
stk500.h \
stk500_private.h \
@ -103,6 +106,7 @@ avrdude_SOURCES = \
stk500v2_private.h \
term.c \
term.h \
usbdevs.h \
usb_libusb.c
man_MANS = avrdude.1

View File

@ -55,6 +55,7 @@ is a program for downloading code and data to Atmel AVR
microcontrollers.
.Nm Avrdude
supports Atmel's STK500 programmer,
Atmel's AVRISP and AVRISP mkII devices,
Atmel's JTAG ICE (both mkI and mkII),
programmers complying to AppNote AVR910 and AVR109 (including the Butterfly),
as well as a simple hard-wired
@ -352,6 +353,9 @@ from any JTAG ICE mkII found on USB.
The match is done after stripping any existing colons from the given
serial number, and right-to-left, so only the least significant bytes
from the serial number need to be given.
.Pp
As the AVRISP mkII device can only be talked to over USB, the very
same method of specifying the port is required there.
.It Fl q
Disable (or quell) output of the progress bar while reading or writing
to the device. Specify it a second time for even quieter operation.

View File

@ -233,6 +233,18 @@ programmer
type = stk500v2;
;
programmer
id = "avrispmkII";
desc = "Atmel AVR ISP mkII";
type = stk500v2;
;
programmer
id = "avrisp2";
desc = "Atmel AVR ISP mkII";
type = stk500v2;
;
programmer
id = "stk500";
desc = "Atmel STK500";

View File

@ -135,7 +135,8 @@ from the contents of a file, while interactive mode is useful for
exploring memory contents, modifing individual bytes of eeprom,
programming fuse/lock bits, etc.
AVRDUDE supports six basic programmer types: Atmel's STK500,
AVRDUDE supports the following basic programmer types: Atmel's STK500,
Atmel's AVRISP and AVRISP mkII devices,
Atmel's JTAG ICE (both mkI and mkII), appnote
avr910, appnote avr109 (including the AVR Butterfly),
serial bit-bang adapters,
@ -430,7 +431,16 @@ Atmel Low Cost Serial Programmer
Atmel AppNote AVR911 AVROSP (an alias for avr109)
@itemx avrisp
Atmel AVR ISP
Atmel AVR ISP (an alias for stk500)
@itemx avrispv2
Atmel AVR ISP, running a version 2.x firmware (an alias for stk500v2)
@itemx avrispmkII
Atmel AVR ISP mkII (alias for stk500v2)
@itemx avrispmk2
Atmel AVR ISP mkII (alias for stk500v2)
@itemx bascom
Bascom SAMPLE programming cable
@ -480,7 +490,7 @@ STK200
Atmel STK500
@itemx stk500v2
Atmel STK500, running a verrsion 2.x firmware
Atmel STK500, running a version 2.x firmware
@end table
@ -579,6 +589,9 @@ bytes from the serial number need to be given.
For a trick how to find out the serial numbers of all JTAG ICEs
attached to USB, see @ref{Example Command Line Invocations}.
As the AVRISP mkII device can only be talked to over USB, the very
same method of specifying the port is required there.
@item -q
Disable (or quell) output of the progress bar while reading or writing
to the device. Specify it a second time for even quieter operation.

View File

@ -1,6 +1,6 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2005 Joerg Wunsch <j@uriah.heep.sax.de>
* Copyright (C) 2005,2006 Joerg Wunsch <j@uriah.heep.sax.de>
*
* Derived from stk500 code which is:
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
@ -43,6 +43,7 @@
#include "pgm.h"
#include "jtagmkII_private.h"
#include "serial.h"
#include "usbdevs.h"
extern int verbose;
@ -1044,26 +1045,34 @@ static void jtagmkII_enable(PROGRAMMER * pgm)
static int jtagmkII_open(PROGRAMMER * pgm, char * port)
{
long baud;
if (verbose >= 2)
fprintf(stderr, "%s: jtagmkII_open()\n", progname);
#if defined(HAVE_LIBUSB)
/*
* If the port name starts with "usb", divert the serial routines
* to the USB ones.
*/
if (strncmp(port, "usb", 3) == 0)
serdev = &usb_serdev;
#endif
strcpy(pgm->port, port);
/*
* The JTAG ICE mkII always starts with a baud rate of 19200 Bd upon
* attaching. If the config file or command-line parameters specify
* a higher baud rate, we switch to it later on, after establishing
* the connection with the ICE.
*/
pgm->fd = serial_open(port, 19200);
baud = 19200;
#if defined(HAVE_LIBUSB)
/*
* If the port name starts with "usb", divert the serial routines
* to the USB ones. The serial_open() function for USB overrides
* the meaning of the "baud" parameter to be the USB device ID to
* search for.
*/
if (strncmp(port, "usb", 3) == 0) {
serdev = &usb_serdev;
baud = USB_DEVICE_JTAGICEMKII;
}
#endif
strcpy(pgm->port, port);
pgm->fd = serial_open(port, baud);
/*
* drain any extraneous input

View File

@ -44,7 +44,7 @@ struct serial_device
};
extern struct serial_device *serdev;
extern struct serial_device serial_serdev, usb_serdev;
extern struct serial_device serial_serdev, usb_serdev, usb_serdev_frame;
#define serial_open (serdev->open)
#define serial_setspeed (serdev->setspeed)

View File

@ -2,6 +2,7 @@
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2005 Erik Walthinsen
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
* Copyright (C) 2006 dcm@mit.edu
*
* 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
@ -24,6 +25,10 @@
/*
* avrdude interface for Atmel STK500V2 programmer
*
* As the AVRISP mkII device is basically an STK500v2 one that can
* only talk across USB, and that misses any kind of framing protocol,
* this is handled here as well.
*
* 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".
@ -45,6 +50,7 @@
#include "stk500_private.h" // temp until all code converted
#include "stk500v2_private.h"
#include "serial.h"
#include "usbdevs.h"
#define STK500V2_XTAL 7372800U
@ -66,6 +72,7 @@ extern char * progname;
extern int do_cycles;
static unsigned char command_sequence = 1;
static int is_mk2; /* Is the device an AVRISP mkII? */
static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value);
@ -74,12 +81,26 @@ 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_set_sck_period_mk2(PROGRAMMER * pgm, double v);
static int stk500v2_send_mk2(PROGRAMMER * pgm, unsigned char * data, size_t len)
{
if (serial_send(pgm->fd, data, len) != 0) {
fprintf(stderr,"%s: stk500_send_mk2(): failed to send command to serial port\n",progname);
exit(1);
}
return 0;
}
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;
if (is_mk2)
return stk500v2_send_mk2(pgm, data, len);
buf[0] = MESSAGE_START;
buf[1] = command_sequence;
buf[2] = len / 256;
@ -110,6 +131,19 @@ static int stk500v2_drain(PROGRAMMER * pgm, int display)
return serial_drain(pgm->fd, display);
}
static int stk500v2_recv_mk2(PROGRAMMER * pgm, unsigned char msg[],
size_t maxsize)
{
int rv;
rv = serial_recv(pgm->fd, msg, maxsize);
if (rv < 0) {
fprintf(stderr, "%s: stk500v2_recv_mk2: error in USB receive\n", progname);
return -1;
}
return rv;
}
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;
@ -122,6 +156,9 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize)
struct timeval tv;
double tstart, tnow;
if (is_mk2)
return stk500v2_recv_mk2(pgm, msg, maxsize);
DEBUG("STK500V2: stk500v2_recv(): ");
gettimeofday(&tv, NULL);
@ -437,13 +474,30 @@ static void stk500v2_enable(PROGRAMMER * pgm)
static int stk500v2_open(PROGRAMMER * pgm, char * port)
{
long baud = 115200;
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);
baud = pgm->baudrate;
#if defined(HAVE_LIBUSB)
/*
* If the port name starts with "usb", divert the serial routines
* to the USB ones. The serial_open() function for USB overrides
* the meaning of the "baud" parameter to be the USB device ID to
* search for.
*/
if (strncmp(port, "usb", 3) == 0) {
serdev = &usb_serdev_frame;
baud = USB_DEVICE_AVRISPMKII;
is_mk2 = 1;
pgm->set_sck_period = stk500v2_set_sck_period_mk2;
}
#endif
strcpy(pgm->port, port);
pgm->fd = serial_open(port, baud);
/*
* drain any extraneous input
@ -797,6 +851,44 @@ static int stk500v2_set_fosc(PROGRAMMER * pgm, double v)
return 0;
}
/* The list of SCK frequencies supported by the AVRISP mkII, as listed
* in AVR069 */
double avrispmkIIfreqs[] = {
8000000, 4000000, 2000000, 1000000, 500000, 250000, 125000,
96386, 89888, 84211, 79208, 74767, 70797, 67227, 64000,
61069, 58395, 55945, 51613, 49690, 47905, 46243, 43244,
41885, 39409, 38278, 36200, 34335, 32654, 31129, 29740,
28470, 27304, 25724, 24768, 23461, 22285, 21221, 20254,
19371, 18562, 17583, 16914, 16097, 15356, 14520, 13914,
13224, 12599, 12031, 11511, 10944, 10431, 9963, 9468,
9081, 8612, 8239, 7851, 7498, 7137, 6809, 6478, 6178,
5879, 5607, 5359, 5093, 4870, 4633, 4418, 4209, 4019,
3823, 3645, 3474, 3310, 3161, 3011, 2869, 2734, 2611,
2484, 2369, 2257, 2152, 2052, 1956, 1866, 1779, 1695,
1615, 1539, 1468, 1398, 1333, 1271, 1212, 1155, 1101,
1049, 1000, 953, 909, 866, 826, 787, 750, 715, 682,
650, 619, 590, 563, 536, 511, 487, 465, 443, 422,
402, 384, 366, 349, 332, 317, 302, 288, 274, 261,
249, 238, 226, 216, 206, 196, 187, 178, 170, 162,
154, 147, 140, 134, 128, 122, 116, 111, 105, 100,
95.4, 90.9, 86.6, 82.6, 78.7, 75.0, 71.5, 68.2,
65.0, 61.9, 59.0, 56.3, 53.6, 51.1
};
static int stk500v2_set_sck_period_mk2(PROGRAMMER * pgm, double v)
{
int i;
for (i = 0; i < sizeof(avrispmkIIfreqs); i++) {
if (1 / avrispmkIIfreqs[i] >= v)
break;
}
fprintf(stderr, "Using p = %.2f us for SCK (param = %d)\n",
1000000 / avrispmkIIfreqs[i], i);
return stk500v2_setparm(pgm, PARAM_SCK_DURATION, i);
}
/* This code assumes that each count of the SCK duration parameter
represents 8/f, where f is the clock frequency of the STK500V2 master
@ -938,7 +1030,11 @@ static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p)
unit = "Hz";
fprintf(stderr, "%.3f %s\n", f, unit);
}
fprintf(stderr, "%sSCK period : %.1f us\n", p,
if (is_mk2)
fprintf(stderr, "%sSCK period : %.2f us\n", p,
(float) 1000000 / avrispmkIIfreqs[sck_duration]);
else
fprintf(stderr, "%sSCK period : %.1f us\n", p,
sck_duration * 8.0e6 / STK500V2_XTAL + 0.05);
return;

View File

@ -1,6 +1,7 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2005 Joerg Wunsch
* Copyright (C) 2005,2006 Joerg Wunsch
* Copyright (C) 2006 dcm@mit.edu
*
* 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
@ -38,28 +39,24 @@
#include <usb.h>
#include "serial.h"
#include "usbdevs.h"
extern char *progname;
extern int verbose;
#define USB_VENDOR_ATMEL 1003
#define USB_DEVICE_JTAGICEMKII 0x2103
/*
* Should we query the endpoint number and max transfer size from USB?
* After all, the JTAG ICE mkII docs document these values.
*/
#define JTAGICE_BULK_EP_WRITE 0x02
#define JTAGICE_BULK_EP_READ 0x82
#define JTAGICE_MAX_XFER 64
static char usbbuf[JTAGICE_MAX_XFER];
static char usbbuf[USBDEV_MAX_XFER];
static int buflen = -1, bufptr;
static int usb_interface;
/*
* The "baud" parameter is meaningless for USB devices, so we reuse it
* to pass the desired USB device ID.
*/
static int usbdev_open(char * port, long baud)
{
char string[256];
char product[256];
struct usb_bus *bus;
struct usb_device *dev;
usb_dev_handle *udev;
@ -110,7 +107,7 @@ static int usbdev_open(char * port, long baud)
if (udev)
{
if (dev->descriptor.idVendor == USB_VENDOR_ATMEL &&
dev->descriptor.idProduct == USB_DEVICE_JTAGICEMKII)
dev->descriptor.idProduct == (unsigned short)baud)
{
/* yeah, we found something */
if (usb_get_string_simple(udev,
@ -133,10 +130,20 @@ static int usbdev_open(char * port, long baud)
strcpy(string, "[unknown]");
}
if (usb_get_string_simple(udev,
dev->descriptor.iProduct,
product, sizeof(product)) < 0)
{
fprintf(stderr,
"%s: usb_open(): cannot read product name \"%s\"\n",
progname, usb_strerror());
strcpy(product, "[unnamed product]");
}
if (verbose)
fprintf(stderr,
"%s: usbdev_open(): Found JTAG ICE, serno: %s\n",
progname, string);
"%s: usbdev_open(): Found %s, serno: %s\n",
progname, product, string);
if (serno != NULL)
{
/*
@ -205,6 +212,13 @@ static void usbdev_close(int fd)
usb_dev_handle *udev = (usb_dev_handle *)fd;
(void)usb_release_interface(udev, usb_interface);
/*
* Without this reset, the AVRISP mkII seems to stall the second
* time we try to connect to it.
*/
usb_reset(udev);
usb_close(udev);
}
@ -213,13 +227,48 @@ static int usbdev_send(int fd, unsigned char *bp, size_t mlen)
{
usb_dev_handle *udev = (usb_dev_handle *)fd;
size_t rv;
int i = mlen;
unsigned char * p = bp;
int tx_size;
rv = usb_bulk_write(udev, JTAGICE_BULK_EP_WRITE, (char *)bp, mlen, 5000);
if (rv != mlen)
/*
* Split the frame into multiple packets. It's important to make
* sure we finish with a short packet, or else the device won't know
* the frame is finished. For example, if we need to send 64 bytes,
* we must send a packet of length 64 followed by a packet of length
* 0.
*/
do {
tx_size = (mlen < USBDEV_MAX_XFER)? mlen: USBDEV_MAX_XFER;
rv = usb_bulk_write(udev, USBDEV_BULK_EP_WRITE, (char *)bp, tx_size, 5000);
if (rv != tx_size)
{
fprintf(stderr, "%s: usbdev_send(): wrote %d out of %d bytes, err = %s\n",
progname, rv, tx_size, usb_strerror());
return -1;
}
bp += tx_size;
mlen -= tx_size;
} while (tx_size == USBDEV_MAX_XFER);
if (verbose > 3)
{
fprintf(stderr, "%s: usbdev_send(): wrote %d out of %d bytes, err = %s\n",
progname, rv, mlen, usb_strerror());
return -1;
fprintf(stderr, "%s: Sent: ", progname);
while (i) {
unsigned char c = *p;
if (isprint(c)) {
fprintf(stderr, "%c ", c);
}
else {
fprintf(stderr, ". ");
}
fprintf(stderr, "[%02x] ", c);
p++;
i--;
}
fprintf(stderr, "\n");
}
return 0;
}
@ -237,7 +286,7 @@ usb_fill_buf(usb_dev_handle *udev)
{
int rv;
rv = usb_bulk_read(udev, JTAGICE_BULK_EP_READ, usbbuf, JTAGICE_MAX_XFER, 5000);
rv = usb_bulk_read(udev, USBDEV_BULK_EP_READ, usbbuf, USBDEV_MAX_XFER, 5000);
if (rv < 0)
{
if (verbose > 1)
@ -295,6 +344,71 @@ static int usbdev_recv(int fd, unsigned char *buf, size_t nbytes)
return 0;
}
/*
* This version of recv keeps reading packets until we receive a short
* packet. Then, the entire frame is assembled and returned to the
* user. The length will be unknown in advance, so we return the
* length as the return value of this function, or -1 in case of an
* error.
*
* This is used for the AVRISP mkII device.
*/
static int usbdev_recv_frame(int fd, unsigned char *buf, size_t nbytes)
{
usb_dev_handle *udev = (usb_dev_handle *)fd;
int rv, n;
int i;
unsigned char * p = buf;
n = 0;
do
{
rv = usb_bulk_read(udev, USBDEV_BULK_EP_READ, usbbuf,
USBDEV_MAX_XFER, 10000);
if (rv < 0)
{
if (verbose > 1)
fprintf(stderr, "%s: usbdev_recv_frame(): usb_bulk_read(): %s\n",
progname, usb_strerror());
return -1;
}
if (rv <= nbytes)
{
memcpy (buf, usbbuf, rv);
buf += rv;
}
n += rv;
nbytes -= rv;
}
while (rv == USBDEV_MAX_XFER);
if (nbytes < 0)
return -1;
if (verbose > 3)
{
i = n;
fprintf(stderr, "%s: Recv: ", progname);
while (i) {
unsigned char c = *p;
if (isprint(c)) {
fprintf(stderr, "%c ", c);
}
else {
fprintf(stderr, ". ");
}
fprintf(stderr, "[%02x] ", c);
p++;
i--;
}
fprintf(stderr, "\n");
}
return n;
}
static int usbdev_drain(int fd, int display)
{
@ -302,7 +416,7 @@ static int usbdev_drain(int fd, int display)
int rv;
do {
rv = usb_bulk_read(udev, JTAGICE_BULK_EP_READ, usbbuf, JTAGICE_MAX_XFER, 100);
rv = usb_bulk_read(udev, USBDEV_BULK_EP_READ, usbbuf, USBDEV_MAX_XFER, 100);
if (rv > 0 && verbose >= 4)
fprintf(stderr, "%s: usbdev_drain(): flushed %d characters\n",
progname, rv);
@ -311,6 +425,9 @@ static int usbdev_drain(int fd, int display)
return 0;
}
/*
* Device descriptor for the JTAG ICE mkII.
*/
struct serial_device usb_serdev =
{
.open = usbdev_open,
@ -321,4 +438,17 @@ struct serial_device usb_serdev =
.drain = usbdev_drain,
};
/*
* Device descriptor for the AVRISP mkII.
*/
struct serial_device usb_serdev_frame =
{
.open = usbdev_open,
.setspeed = usbdev_setspeed,
.close = usbdev_close,
.send = usbdev_send,
.recv = usbdev_recv_frame,
.drain = usbdev_drain,
};
#endif /* HAVE_LIBUSB */

40
usbdevs.h Normal file
View File

@ -0,0 +1,40 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2006 Joerg Wunsch
*
* 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
*/
/* $Id$ */
/*
* defines for the USB interface
*/
#ifndef usbdevs_h
#define usbdevs_h
#define USB_VENDOR_ATMEL 1003
#define USB_DEVICE_JTAGICEMKII 0x2103
#define USB_DEVICE_AVRISPMKII 0x2104
/*
* Should we query the endpoint number and max transfer size from USB?
* After all, the JTAG ICE mkII docs document these values.
*/
#define USBDEV_BULK_EP_WRITE 0x02
#define USBDEV_BULK_EP_READ 0x82
#define USBDEV_MAX_XFER 64
#endif /* usbdevs_h */