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:
parent
d5965b20b9
commit
d98636cfad
17
ChangeLog
17
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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.
|
||||
|
|
33
jtagmkII.c
33
jtagmkII.c
|
@ -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
|
||||
|
|
2
serial.h
2
serial.h
|
@ -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)
|
||||
|
|
106
stk500v2.c
106
stk500v2.c
|
@ -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;
|
||||
|
|
174
usb_libusb.c
174
usb_libusb.c
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
Loading…
Reference in New Issue