Implement the Atmel EDBG/CMSIS-DAP driver protocol for JTAGICE3
(running firmware 3.x) and XplainedPro boards. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1278 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
7f2079731b
commit
e59df50eeb
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2014-02-26 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||
|
||||
* jtag3_private.h: Add EDBG/CMSIS-DAP specific constants.
|
||||
* jtag3.c: Add EDBG/CMSIS-DAP protocol implementation.
|
||||
* serial.h: (Dito.)
|
||||
* usbdevs.h: (Dito.)
|
||||
* usb_libusb.c: (Dito.)
|
||||
* configure.ac: (Dito.)
|
||||
* avrdude.conf.in: Add JTAGICE3 and XplainedPro entries using
|
||||
EDBG.
|
||||
* configure.ac: Bump version date.
|
||||
|
||||
2014-02-22 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||
|
||||
* usb_libusb.c (usbdev_recv_frame): Fix a bug where a new recv
|
||||
|
|
2
NEWS
2
NEWS
|
@ -8,7 +8,7 @@ Approximate change log for AVRDUDE by version.
|
|||
Current:
|
||||
|
||||
* Major changes compared to the previous version:
|
||||
- ...
|
||||
- Atmel EDBG protocol support added (JTAGICE3, XplainedPro)
|
||||
|
||||
* New devices supported:
|
||||
- ...
|
||||
|
|
|
@ -994,6 +994,7 @@ programmer
|
|||
desc = "Atmel AVR JTAGICE3 in JTAG mode";
|
||||
type = "jtagice3";
|
||||
connection_type = usb;
|
||||
usbpid = 0x2110;
|
||||
;
|
||||
|
||||
programmer
|
||||
|
@ -1001,6 +1002,7 @@ programmer
|
|||
desc = "Atmel AVR JTAGICE3 in PDI mode";
|
||||
type = "jtagice3_pdi";
|
||||
connection_type = usb;
|
||||
usbpid = 0x2110;
|
||||
;
|
||||
|
||||
programmer
|
||||
|
@ -1008,6 +1010,7 @@ programmer
|
|||
desc = "Atmel AVR JTAGICE3 in debugWIRE mode";
|
||||
type = "jtagice3_dw";
|
||||
connection_type = usb;
|
||||
usbpid = 0x2110;
|
||||
;
|
||||
|
||||
programmer
|
||||
|
@ -1015,6 +1018,47 @@ programmer
|
|||
desc = "Atmel AVR JTAGICE3 in ISP mode";
|
||||
type = "jtagice3_isp";
|
||||
connection_type = usb;
|
||||
usbpid = 0x2110;
|
||||
;
|
||||
|
||||
programmer
|
||||
id = "jtag3edbg";
|
||||
desc = "Atmel AVR JTAGICE3 in JTAG mode, EDBG protocol";
|
||||
type = "jtagice3";
|
||||
connection_type = usb;
|
||||
usbpid = 0x2140;
|
||||
;
|
||||
|
||||
programmer
|
||||
id = "jtag3pdi_edbg";
|
||||
desc = "Atmel AVR JTAGICE3 in PDI mode, EDBG protocol";
|
||||
type = "jtagice3_pdi";
|
||||
connection_type = usb;
|
||||
usbpid = 0x2140;
|
||||
;
|
||||
|
||||
programmer
|
||||
id = "jtag3dw_edbg";
|
||||
desc = "Atmel AVR JTAGICE3 in debugWIRE mode, EDBG protocol";
|
||||
type = "jtagice3_dw";
|
||||
connection_type = usb;
|
||||
usbpid = 0x2140;
|
||||
;
|
||||
|
||||
programmer
|
||||
id = "jtag3isp_edbg";
|
||||
desc = "Atmel AVR JTAGICE3 in ISP mode, EDBG protocol";
|
||||
type = "jtagice3_isp";
|
||||
connection_type = usb;
|
||||
usbpid = 0x2140;
|
||||
;
|
||||
|
||||
programmer
|
||||
id = "xplainedpro";
|
||||
desc = "Atmel AVR XplainedPro in JTAG mode";
|
||||
type = "jtagice3";
|
||||
connection_type = usb;
|
||||
usbpid = 0x2111;
|
||||
;
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.60)
|
||||
AC_INIT(avrdude, 6.1-svn-20131205, avrdude-dev@nongnu.org)
|
||||
AC_INIT(avrdude, 6.1-svn-20140226, avrdude-dev@nongnu.org)
|
||||
|
||||
AC_CANONICAL_BUILD
|
||||
AC_CANONICAL_HOST
|
||||
|
|
329
jtag3.c
329
jtag3.c
|
@ -84,8 +84,13 @@ struct pdata
|
|||
#define PGM_FL_IS_DW (0x0001)
|
||||
#define PGM_FL_IS_PDI (0x0002)
|
||||
#define PGM_FL_IS_JTAG (0x0004)
|
||||
#define PGM_FL_IS_EDBG (0x0008)
|
||||
|
||||
static int jtag3_open(PROGRAMMER * pgm, char * port);
|
||||
static int jtag3_edbg_prepare(PROGRAMMER * pgm);
|
||||
static int jtag3_edbg_signoff(PROGRAMMER * pgm);
|
||||
static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len);
|
||||
static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg);
|
||||
|
||||
static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p);
|
||||
static int jtag3_chip_erase(PROGRAMMER * pgm, AVRPART * p);
|
||||
|
@ -399,6 +404,9 @@ int jtag3_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
|||
{
|
||||
unsigned char *buf;
|
||||
|
||||
if (pgm->flag & PGM_FL_IS_EDBG)
|
||||
return jtag3_edbg_send(pgm, data, len);
|
||||
|
||||
if (verbose >= 3)
|
||||
fprintf(stderr, "\n%s: jtag3_send(): sending %lu bytes\n",
|
||||
progname, (unsigned long)len);
|
||||
|
@ -419,7 +427,7 @@ int jtag3_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
|||
fprintf(stderr,
|
||||
"%s: jtag3_send(): failed to send command to serial port\n",
|
||||
progname);
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
@ -427,6 +435,193 @@ int jtag3_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
||||
{
|
||||
unsigned char buf[USBDEV_MAX_XFER_3];
|
||||
unsigned char status[USBDEV_MAX_XFER_3];
|
||||
int rv;
|
||||
|
||||
if (verbose >= 4)
|
||||
{
|
||||
memset(buf, 0, pgm->fd.usb.max_xfer);
|
||||
memset(status, 0, pgm->fd.usb.max_xfer);
|
||||
}
|
||||
|
||||
if (verbose >= 3)
|
||||
fprintf(stderr, "\n%s: jtag3_edbg_send(): sending %lu bytes\n",
|
||||
progname, (unsigned long)len);
|
||||
|
||||
if (len + 8 > pgm->fd.usb.max_xfer)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_send(): Fragmentation not (yet) implemented!\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
buf[0] = EDBG_VENDOR_AVR_CMD;
|
||||
buf[1] = (1 << 4) | 1; /* first out of a total of 1 fragments */
|
||||
buf[2] = (len + 4) >> 8;
|
||||
buf[3] = (len + 4) & 0xff;
|
||||
buf[4] = TOKEN;
|
||||
buf[5] = 0; /* dummy */
|
||||
u16_to_b2(buf + 6, PDATA(pgm)->command_sequence);
|
||||
memcpy(buf + 8, data, len);
|
||||
|
||||
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_send(): failed to send command to serial port\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
|
||||
|
||||
if (rv < 0) {
|
||||
/* timeout in receive */
|
||||
if (verbose > 1)
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_send(): Timeout receiving packet\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
if (status[0] != EDBG_VENDOR_AVR_CMD || status[1] != 0x01)
|
||||
{
|
||||
/* what to do in this case? */
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_send(): Unexpected response 0x%02x, 0x%02x\n",
|
||||
progname, status[0], status[1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send out all the CMSIS-DAP stuff needed to prepare the ICE.
|
||||
*/
|
||||
static int jtag3_edbg_prepare(PROGRAMMER * pgm)
|
||||
{
|
||||
unsigned char buf[USBDEV_MAX_XFER_3];
|
||||
unsigned char status[USBDEV_MAX_XFER_3];
|
||||
int rv;
|
||||
|
||||
if (verbose >= 3)
|
||||
fprintf(stderr, "\n%s: jtag3_edbg_prepare()\n",
|
||||
progname);
|
||||
|
||||
if (verbose >= 4)
|
||||
memset(buf, 0, USBDEV_MAX_XFER_3);
|
||||
|
||||
buf[0] = CMSISDAP_CMD_CONNECT;
|
||||
buf[1] = CMSISDAP_CONN_SWD;
|
||||
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_prepare(): failed to send command to serial port\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
|
||||
if (rv != USBDEV_MAX_XFER_3) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_prepare(): failed to read from serial port (%d)\n",
|
||||
progname, rv);
|
||||
return -1;
|
||||
}
|
||||
if (status[0] != CMSISDAP_CMD_CONNECT ||
|
||||
status[1] == 0)
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_prepare(): unexpected response 0x%02x, 0x%02x\n",
|
||||
progname, status[0], status[1]);
|
||||
if (verbose >= 2)
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_prepare(): connection status 0x%02x\n",
|
||||
progname, status[1]);
|
||||
|
||||
buf[0] = CMSISDAP_CMD_LED;
|
||||
buf[1] = CMSISDAP_LED_CONNECT;
|
||||
buf[2] = 1;
|
||||
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_prepare(): failed to send command to serial port\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
|
||||
if (rv != USBDEV_MAX_XFER_3) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_prepare(): failed to read from serial port (%d)\n",
|
||||
progname, rv);
|
||||
return -1;
|
||||
}
|
||||
if (status[0] != CMSISDAP_CMD_LED ||
|
||||
status[1] != 0)
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_prepare(): unexpected response 0x%02x, 0x%02x\n",
|
||||
progname, status[0], status[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send out all the CMSIS-DAP stuff when signing off.
|
||||
*/
|
||||
static int jtag3_edbg_signoff(PROGRAMMER * pgm)
|
||||
{
|
||||
unsigned char buf[USBDEV_MAX_XFER_3];
|
||||
unsigned char status[USBDEV_MAX_XFER_3];
|
||||
int rv;
|
||||
|
||||
if (verbose >= 3)
|
||||
fprintf(stderr, "\n%s: jtag3_edbg_signoff()\n",
|
||||
progname);
|
||||
|
||||
if (verbose >= 4)
|
||||
memset(buf, 0, USBDEV_MAX_XFER_3);
|
||||
|
||||
buf[0] = CMSISDAP_CMD_LED;
|
||||
buf[1] = CMSISDAP_LED_CONNECT;
|
||||
buf[2] = 0;
|
||||
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_signoff(): failed to send command to serial port\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
|
||||
if (rv != USBDEV_MAX_XFER_3) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n",
|
||||
progname, rv);
|
||||
return -1;
|
||||
}
|
||||
if (status[0] != CMSISDAP_CMD_LED ||
|
||||
status[1] != 0)
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_signoff(): unexpected response 0x%02x, 0x%02x\n",
|
||||
progname, status[0], status[1]);
|
||||
|
||||
buf[0] = CMSISDAP_CMD_DISCONNECT;
|
||||
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_signoff(): failed to send command to serial port\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
|
||||
if (rv != USBDEV_MAX_XFER_3) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n",
|
||||
progname, rv);
|
||||
return -1;
|
||||
}
|
||||
if (status[0] != CMSISDAP_CMD_DISCONNECT ||
|
||||
status[1] != 0)
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_signoff(): unexpected response 0x%02x, 0x%02x\n",
|
||||
progname, status[0], status[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int jtag3_drain(PROGRAMMER * pgm, int display)
|
||||
{
|
||||
|
@ -446,6 +641,9 @@ static int jtag3_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
|
|||
int rv;
|
||||
unsigned char *buf = NULL;
|
||||
|
||||
if (pgm->flag & PGM_FL_IS_EDBG)
|
||||
return jtag3_edbg_recv_frame(pgm, msg);
|
||||
|
||||
if (verbose >= 4)
|
||||
fprintf(stderr, "%s: jtag3_recv():\n", progname);
|
||||
|
||||
|
@ -454,6 +652,8 @@ static int jtag3_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
|
|||
progname);
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 4)
|
||||
memset(buf, 0, pgm->fd.usb.max_xfer);
|
||||
|
||||
rv = serial_recv(&pgm->fd, buf, pgm->fd.usb.max_xfer);
|
||||
|
||||
|
@ -472,6 +672,62 @@ static int jtag3_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
|
|||
return rv;
|
||||
}
|
||||
|
||||
static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
|
||||
int rv, len;
|
||||
unsigned char *buf = NULL;
|
||||
|
||||
if (verbose >= 4)
|
||||
fprintf(stderr, "%s: jtag3_edbg_recv():\n", progname);
|
||||
|
||||
if ((buf = malloc(pgm->fd.usb.max_xfer)) == NULL) {
|
||||
fprintf(stderr, "%s: jtag3_edbg_recv(): out of memory\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[0] = EDBG_VENDOR_AVR_RSP;
|
||||
|
||||
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_recv(): error sending CMSIS-DAP vendor command\n",
|
||||
progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = serial_recv(&pgm->fd, buf, pgm->fd.usb.max_xfer);
|
||||
|
||||
if (rv < 0) {
|
||||
/* timeout in receive */
|
||||
if (verbose > 1)
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_recv(): Timeout receiving packet\n",
|
||||
progname);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buf[0] != EDBG_VENDOR_AVR_RSP ||
|
||||
buf[1] != ((1 << 4) | 1)) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_recv(): Unexpected response 0x%02x, 0x%02x\n",
|
||||
progname, buf[0], buf[1]);
|
||||
return -1;
|
||||
}
|
||||
/* calculate length from response; CMSIS-DAP response might be larger */
|
||||
len = (buf[2] << 8) | buf[3];
|
||||
if (len > rv + 4) {
|
||||
fprintf(stderr,
|
||||
"%s: jtag3_edbg_recv(): Unexpected length value (%d > %d)\n",
|
||||
progname, len, rv + 4);
|
||||
len = rv + 4;
|
||||
}
|
||||
memmove(buf, buf + 4, len);
|
||||
|
||||
*msg = buf;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg) {
|
||||
unsigned short r_seqno;
|
||||
int rv;
|
||||
|
@ -562,6 +818,11 @@ int jtag3_getsync(PROGRAMMER * pgm, int mode) {
|
|||
if (verbose >= 3)
|
||||
fprintf(stderr, "%s: jtag3_getsync()\n", progname);
|
||||
|
||||
if (pgm->flag & PGM_FL_IS_EDBG) {
|
||||
if (jtag3_edbg_prepare(pgm) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the sign-on information. */
|
||||
buf[0] = SCOPE_GENERAL;
|
||||
buf[1] = CMD3_SIGN_ON;
|
||||
|
@ -1034,9 +1295,15 @@ static int jtag3_open(PROGRAMMER * pgm, char * port)
|
|||
if (strncmp(port, "usb", 3) == 0) {
|
||||
#if defined(HAVE_LIBUSB)
|
||||
serdev = &usb_serdev_frame;
|
||||
pinfo.usbinfo.vid = USB_VENDOR_ATMEL;
|
||||
if (pgm->usbvid)
|
||||
pinfo.usbinfo.vid = pgm->usbvid;
|
||||
else
|
||||
pinfo.usbinfo.vid = USB_VENDOR_ATMEL;
|
||||
pinfo.usbinfo.flags = 0;
|
||||
pinfo.usbinfo.pid = USB_DEVICE_JTAGICE3;
|
||||
if (pgm->usbpid)
|
||||
pinfo.usbinfo.pid = pgm->usbpid;
|
||||
else
|
||||
pinfo.usbinfo.pid = USB_DEVICE_JTAGICE3;
|
||||
pgm->fd.usb.max_xfer = USBDEV_MAX_XFER_3;
|
||||
pgm->fd.usb.rep = USBDEV_BULK_EP_READ_3;
|
||||
pgm->fd.usb.wep = USBDEV_BULK_EP_WRITE_3;
|
||||
|
@ -1052,6 +1319,17 @@ static int jtag3_open(PROGRAMMER * pgm, char * port)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (pgm->fd.usb.eep == 0)
|
||||
{
|
||||
/* The event EP has been deleted by usb_open(), so we are
|
||||
running on a CMSIS-DAP device, using EDBG protocol */
|
||||
pgm->flag |= PGM_FL_IS_EDBG;
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
"%s: Found CMSIS-DAP compliant device, using EDBG protocol\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
*/
|
||||
|
@ -1078,9 +1356,15 @@ static int jtag3_open_dw(PROGRAMMER * pgm, char * port)
|
|||
if (strncmp(port, "usb", 3) == 0) {
|
||||
#if defined(HAVE_LIBUSB)
|
||||
serdev = &usb_serdev_frame;
|
||||
pinfo.usbinfo.vid = USB_VENDOR_ATMEL;
|
||||
if (pgm->usbvid)
|
||||
pinfo.usbinfo.vid = pgm->usbvid;
|
||||
else
|
||||
pinfo.usbinfo.vid = USB_VENDOR_ATMEL;
|
||||
pinfo.usbinfo.flags = 0;
|
||||
pinfo.usbinfo.pid = USB_DEVICE_JTAGICE3;
|
||||
if (pgm->usbpid)
|
||||
pinfo.usbinfo.pid = pgm->usbpid;
|
||||
else
|
||||
pinfo.usbinfo.pid = USB_DEVICE_JTAGICE3;
|
||||
pgm->fd.usb.max_xfer = USBDEV_MAX_XFER_3;
|
||||
pgm->fd.usb.rep = USBDEV_BULK_EP_READ_3;
|
||||
pgm->fd.usb.wep = USBDEV_BULK_EP_WRITE_3;
|
||||
|
@ -1096,6 +1380,17 @@ static int jtag3_open_dw(PROGRAMMER * pgm, char * port)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (pgm->fd.usb.eep == 0)
|
||||
{
|
||||
/* The event EP has been deleted by usb_open(), so we are
|
||||
running on a CMSIS-DAP device, using EDBG protocol */
|
||||
pgm->flag |= PGM_FL_IS_EDBG;
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
"%s: Found CMSIS-DAP compliant device, using EDBG protocol\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
*/
|
||||
|
@ -1122,9 +1417,15 @@ static int jtag3_open_pdi(PROGRAMMER * pgm, char * port)
|
|||
if (strncmp(port, "usb", 3) == 0) {
|
||||
#if defined(HAVE_LIBUSB)
|
||||
serdev = &usb_serdev_frame;
|
||||
pinfo.usbinfo.vid = USB_VENDOR_ATMEL;
|
||||
if (pgm->usbvid)
|
||||
pinfo.usbinfo.vid = pgm->usbvid;
|
||||
else
|
||||
pinfo.usbinfo.vid = USB_VENDOR_ATMEL;
|
||||
pinfo.usbinfo.flags = 0;
|
||||
pinfo.usbinfo.pid = USB_DEVICE_JTAGICE3;
|
||||
if (pgm->usbpid)
|
||||
pinfo.usbinfo.pid = pgm->usbpid;
|
||||
else
|
||||
pinfo.usbinfo.pid = USB_DEVICE_JTAGICE3;
|
||||
pgm->fd.usb.max_xfer = USBDEV_MAX_XFER_3;
|
||||
pgm->fd.usb.rep = USBDEV_BULK_EP_READ_3;
|
||||
pgm->fd.usb.wep = USBDEV_BULK_EP_WRITE_3;
|
||||
|
@ -1140,6 +1441,17 @@ static int jtag3_open_pdi(PROGRAMMER * pgm, char * port)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (pgm->fd.usb.eep == 0)
|
||||
{
|
||||
/* The event EP has been deleted by usb_open(), so we are
|
||||
running on a CMSIS-DAP device, using EDBG protocol */
|
||||
pgm->flag |= PGM_FL_IS_EDBG;
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
"%s: Found CMSIS-DAP compliant device, using EDBG protocol\n",
|
||||
progname);
|
||||
}
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
*/
|
||||
|
@ -1172,6 +1484,9 @@ void jtag3_close(PROGRAMMER * pgm)
|
|||
if (jtag3_command(pgm, buf, 4, &resp, "sign-off") >= 0)
|
||||
free(resp);
|
||||
|
||||
if (pgm->flag & PGM_FL_IS_EDBG)
|
||||
jtag3_edbg_signoff(pgm);
|
||||
|
||||
serial_close(&pgm->fd);
|
||||
pgm->fd.ifd = -1;
|
||||
}
|
||||
|
|
|
@ -222,6 +222,47 @@
|
|||
#define XMEGA_ERASE_EEPROM_PAGE 0x06
|
||||
#define XMEGA_ERASE_USERSIG 0x07
|
||||
|
||||
/* EDBG vendor commands */
|
||||
#define EDBG_VENDOR_AVR_CMD 0x80
|
||||
#define EDBG_VENDOR_AVR_RSP 0x81
|
||||
#define EDBG_VENDOR_AVR_EVT 0x82
|
||||
|
||||
/* CMSIS-DAP commands */
|
||||
#define CMSISDAP_CMD_INFO 0x00 /* get info, followed by INFO byte */
|
||||
# define CMSISDAP_INFO_VID 0x01 /* vendor ID (string) */
|
||||
# define CMSISDAP_INFO_PID 0x02 /* product ID (string) */
|
||||
# define CMSISDAP_INFO_SERIAL 0x03 /* serial number (string) */
|
||||
# define CMSISDAP_INFO_FIRMWARE 0x04 /* firmware version (string) */
|
||||
# define CMSISDAP_INFO_TARGET_VENDOR 0x05 /* target device vendor (string) */
|
||||
# define CMSISDAP_INFO_TARGET_NAME 0x06 /* target device name (string) */
|
||||
# define CMSISDAP_INFO_CAPABILITIES 0xF0 /* debug unit capabilities (byte) */
|
||||
# define CMSISDAP_INFO_PACKET_COUNT 0xFE /* packet count (byte) (which packets, anyway?) */
|
||||
# define CMSISDAP_INFO_PACKET_SIZE 0xFF /* packet size (short) */
|
||||
|
||||
#define CMSISDAP_CMD_LED 0x01 /* LED control, followed by LED number and on/off byte */
|
||||
# define CMSISDAP_LED_CONNECT 0x00 /* connect LED */
|
||||
# define CMSISDAP_LED_RUNNING 0x01 /* running LED */
|
||||
|
||||
#define CMSISDAP_CMD_CONNECT 0x02 /* connect to target, followed by DAP mode */
|
||||
# define CMSISDAP_CONN_DEFAULT 0x00
|
||||
# define CMSISDAP_CONN_SWD 0x01 /* serial wire debug */
|
||||
# define CMSISDAP_CONN_JTAG 0x02 /* JTAG mode */
|
||||
|
||||
#define CMSISDAP_CMD_DISCONNECT 0x03 /* disconnect from target */
|
||||
|
||||
#define CMSISDAP_XFR_CONFIGURE 0x04 /* configure transfers; idle cycles (byte);
|
||||
wait retry (short); match retry (short) */
|
||||
|
||||
#define CMSISDAP_CMD_WRITEAPBORT 0x08 /* write to CoreSight ABORT register of target */
|
||||
|
||||
#define CMSISDAP_CMD_DELAY 0x09 /* delay for number of microseconds (short) */
|
||||
|
||||
#define CMSISDAP_CMD_RESET 0x0A /* reset target */
|
||||
|
||||
#define CMSISDAP_CMD_SWJ_CLOCK 0x11 /* SWD/JTAG clock, (word) */
|
||||
|
||||
#define CMSISDAP_CMD_SWD_CONFIGURE 0x13 /* configure SWD protocol; (byte) */
|
||||
|
||||
#if !defined(JTAG3_PRIVATE_EXPORTED)
|
||||
|
||||
struct mega_device_desc {
|
||||
|
|
2
serial.h
2
serial.h
|
@ -41,6 +41,7 @@ union filedescriptor
|
|||
int wep; /* bulk write endpoint */
|
||||
int eep; /* event read endpoint */
|
||||
int max_xfer; /* max transfer size */
|
||||
int use_interrupt_xfer; /* device uses interrupt transfers */
|
||||
} usb;
|
||||
};
|
||||
|
||||
|
@ -52,6 +53,7 @@ union pinfo
|
|||
unsigned short vid;
|
||||
unsigned short pid;
|
||||
unsigned short flags;
|
||||
#define PINFO_FL_USEHID 0x0001
|
||||
} usbinfo;
|
||||
};
|
||||
|
||||
|
|
157
usb_libusb.c
157
usb_libusb.c
|
@ -70,6 +70,7 @@ static int usbdev_open(char * port, union pinfo pinfo, union filedescriptor *fd)
|
|||
usb_dev_handle *udev;
|
||||
char *serno, *cp2;
|
||||
int i;
|
||||
int iface;
|
||||
size_t x;
|
||||
|
||||
/*
|
||||
|
@ -151,6 +152,21 @@ static int usbdev_open(char * port, union pinfo pinfo, union filedescriptor *fd)
|
|||
progname, usb_strerror());
|
||||
strcpy(product, "[unnamed product]");
|
||||
}
|
||||
/*
|
||||
* The CMSIS-DAP specification mandates the string
|
||||
* "CMSIS-DAP" must be present somewhere in the
|
||||
* product name string for a device compliant to
|
||||
* that protocol. Use this for the decisision
|
||||
* whether we have to search for a HID interface
|
||||
* below.
|
||||
*/
|
||||
if(strstr(product, "CMSIS-DAP") != NULL)
|
||||
{
|
||||
pinfo.usbinfo.flags |= PINFO_FL_USEHID;
|
||||
/* The JTAGICE3 running the CMSIS-DAP firmware doesn't
|
||||
* use a separate endpoint for event reception. */
|
||||
fd->usb.eep = 0;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr,
|
||||
|
@ -186,66 +202,102 @@ static int usbdev_open(char * port, union pinfo pinfo, union filedescriptor *fd)
|
|||
if (usb_set_configuration(udev, dev->config[0].bConfigurationValue))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): error setting configuration %d: %s\n",
|
||||
"%s: usbdev_open(): WARNING: failed to set configuration %d: %s\n",
|
||||
progname, dev->config[0].bConfigurationValue,
|
||||
usb_strerror());
|
||||
goto trynext;
|
||||
/* let's hope it has already been configured */
|
||||
// goto trynext;
|
||||
}
|
||||
|
||||
usb_interface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber;
|
||||
if (usb_claim_interface(udev, usb_interface))
|
||||
for (iface = 0; iface < dev->config[0].bNumInterfaces; iface++)
|
||||
{
|
||||
usb_interface = dev->config[0].interface[iface].altsetting[0].bInterfaceNumber;
|
||||
#ifdef LIBUSB_HAS_GET_DRIVER_NP
|
||||
/*
|
||||
* Many Linux systems attach the usbhid driver
|
||||
* by default to any HID-class device. On
|
||||
* those, the driver needs to be detached before
|
||||
* we can claim the interface.
|
||||
*/
|
||||
(void)usb_detach_kernel_driver_np(udev, usb_interface);
|
||||
#endif
|
||||
if (usb_claim_interface(udev, usb_interface))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): error claiming interface %d: %s\n",
|
||||
progname, usb_interface, usb_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pinfo.usbinfo.flags & PINFO_FL_USEHID)
|
||||
{
|
||||
/* only consider an interface that is of class HID */
|
||||
if (dev->config[0].interface[iface].altsetting[0].bInterfaceClass !=
|
||||
USB_CLASS_HID)
|
||||
continue;
|
||||
fd->usb.use_interrupt_xfer = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iface == dev->config[0].bNumInterfaces)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): error claiming interface %d: %s\n",
|
||||
progname, usb_interface, usb_strerror());
|
||||
"%s: usbdev_open(): no usable interface found\n",
|
||||
progname);
|
||||
goto trynext;
|
||||
}
|
||||
|
||||
fd->usb.handle = udev;
|
||||
if (fd->usb.rep == 0)
|
||||
{
|
||||
/* Try finding out what our read endpoint is. */
|
||||
for (i = 0; i < dev->config[0].interface[0].altsetting[0].bNumEndpoints; i++)
|
||||
{
|
||||
int possible_ep = dev->config[0].interface[0].altsetting[0].
|
||||
endpoint[i].bEndpointAddress;
|
||||
/* Try finding out what our read endpoint is. */
|
||||
for (i = 0; i < dev->config[0].interface[iface].altsetting[0].bNumEndpoints; i++)
|
||||
{
|
||||
int possible_ep = dev->config[0].interface[iface].altsetting[0].
|
||||
endpoint[i].bEndpointAddress;
|
||||
|
||||
if ((possible_ep & USB_ENDPOINT_DIR_MASK) != 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
if ((possible_ep & USB_ENDPOINT_DIR_MASK) != 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): using read endpoint 0x%02x\n",
|
||||
progname, possible_ep);
|
||||
}
|
||||
fd->usb.rep = possible_ep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fd->usb.rep == 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): using read endpoint 0x%02x\n",
|
||||
progname, possible_ep);
|
||||
"%s: usbdev_open(): cannot find a read endpoint, using 0x%02x\n",
|
||||
progname, USBDEV_BULK_EP_READ_MKII);
|
||||
fd->usb.rep = USBDEV_BULK_EP_READ_MKII;
|
||||
}
|
||||
fd->usb.rep = possible_ep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fd->usb.rep == 0)
|
||||
for (i = 0; i < dev->config[0].interface[iface].altsetting[0].bNumEndpoints; i++)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: usbdev_open(): cannot find a read endpoint, using 0x%02x\n",
|
||||
progname, USBDEV_BULK_EP_READ_MKII);
|
||||
fd->usb.rep = USBDEV_BULK_EP_READ_MKII;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < dev->config[0].interface[0].altsetting[0].bNumEndpoints; i++)
|
||||
{
|
||||
if ((dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress == fd->usb.rep ||
|
||||
dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress == fd->usb.wep) &&
|
||||
dev->config[0].interface[0].altsetting[0].endpoint[i].wMaxPacketSize < fd->usb.max_xfer)
|
||||
if ((dev->config[0].interface[iface].altsetting[0].endpoint[i].bEndpointAddress == fd->usb.rep ||
|
||||
dev->config[0].interface[iface].altsetting[0].endpoint[i].bEndpointAddress == fd->usb.wep) &&
|
||||
dev->config[0].interface[iface].altsetting[0].endpoint[i].wMaxPacketSize < fd->usb.max_xfer)
|
||||
{
|
||||
if (verbose != 0)
|
||||
fprintf(stderr,
|
||||
"%s: max packet size expected %d, but found %d due to EP 0x%02x's wMaxPacketSize\n",
|
||||
progname,
|
||||
fd->usb.max_xfer,
|
||||
dev->config[0].interface[0].altsetting[0].endpoint[i].wMaxPacketSize,
|
||||
dev->config[0].interface[0].altsetting[0].endpoint[i].bEndpointAddress);
|
||||
fd->usb.max_xfer = dev->config[0].interface[0].altsetting[0].endpoint[i].wMaxPacketSize;
|
||||
dev->config[0].interface[iface].altsetting[0].endpoint[i].wMaxPacketSize,
|
||||
dev->config[0].interface[iface].altsetting[0].endpoint[i].bEndpointAddress);
|
||||
fd->usb.max_xfer = dev->config[0].interface[iface].altsetting[0].endpoint[i].wMaxPacketSize;
|
||||
}
|
||||
}
|
||||
if (pinfo.usbinfo.flags & PINFO_FL_USEHID)
|
||||
{
|
||||
if (usb_control_msg(udev, 0x21, 0x0a /* SET_IDLE */, 0, 0, NULL, 0, 100) < 0)
|
||||
fprintf(stderr, "%s: usbdev_open(): SET_IDLE failed\n", progname);
|
||||
}
|
||||
return 0;
|
||||
trynext:
|
||||
usb_close(udev);
|
||||
|
@ -299,7 +351,10 @@ static int usbdev_send(union filedescriptor *fd, unsigned char *bp, size_t mlen)
|
|||
*/
|
||||
do {
|
||||
tx_size = (mlen < fd->usb.max_xfer)? mlen: fd->usb.max_xfer;
|
||||
rv = usb_bulk_write(udev, fd->usb.wep, (char *)bp, tx_size, 10000);
|
||||
if (fd->usb.use_interrupt_xfer)
|
||||
rv = usb_interrupt_write(udev, fd->usb.wep, (char *)bp, tx_size, 10000);
|
||||
else
|
||||
rv = usb_bulk_write(udev, fd->usb.wep, (char *)bp, tx_size, 10000);
|
||||
if (rv != tx_size)
|
||||
{
|
||||
fprintf(stderr, "%s: usbdev_send(): wrote %d out of %d bytes, err = %s\n",
|
||||
|
@ -341,16 +396,20 @@ static int usbdev_send(union filedescriptor *fd, unsigned char *bp, size_t mlen)
|
|||
* empty and more data are requested.
|
||||
*/
|
||||
static int
|
||||
usb_fill_buf(usb_dev_handle *udev, int maxsize, int ep)
|
||||
usb_fill_buf(usb_dev_handle *udev, int maxsize, int ep, int use_interrupt_xfer)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = usb_bulk_read(udev, ep, usbbuf, maxsize, 10000);
|
||||
if (use_interrupt_xfer)
|
||||
rv = usb_interrupt_read(udev, ep, usbbuf, maxsize, 10000);
|
||||
else
|
||||
rv = usb_bulk_read(udev, ep, usbbuf, maxsize, 10000);
|
||||
if (rv < 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
fprintf(stderr, "%s: usb_fill_buf(): usb_bulk_read() error %s\n",
|
||||
progname, usb_strerror());
|
||||
fprintf(stderr, "%s: usb_fill_buf(): usb_%s_read() error %s\n",
|
||||
progname, (use_interrupt_xfer? "interrupt": "bulk"),
|
||||
usb_strerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -370,7 +429,7 @@ static int usbdev_recv(union filedescriptor *fd, unsigned char *buf, size_t nbyt
|
|||
{
|
||||
if (buflen <= bufptr)
|
||||
{
|
||||
if (usb_fill_buf(udev, fd->usb.max_xfer, fd->usb.rep) < 0)
|
||||
if (usb_fill_buf(udev, fd->usb.max_xfer, fd->usb.rep, fd->usb.use_interrupt_xfer) < 0)
|
||||
return -1;
|
||||
}
|
||||
amnt = buflen - bufptr > nbytes? nbytes: buflen - bufptr;
|
||||
|
@ -441,13 +500,18 @@ static int usbdev_recv_frame(union filedescriptor *fd, unsigned char *buf, size_
|
|||
n = 0;
|
||||
do
|
||||
{
|
||||
rv = usb_bulk_read(udev, fd->usb.rep, usbbuf,
|
||||
fd->usb.max_xfer, 10000);
|
||||
if (fd->usb.use_interrupt_xfer)
|
||||
rv = usb_interrupt_read(udev, fd->usb.rep, usbbuf,
|
||||
fd->usb.max_xfer, 10000);
|
||||
else
|
||||
rv = usb_bulk_read(udev, fd->usb.rep, usbbuf,
|
||||
fd->usb.max_xfer, 10000);
|
||||
if (rv < 0)
|
||||
{
|
||||
if (verbose > 1)
|
||||
fprintf(stderr, "%s: usbdev_recv_frame(): usb_bulk_read(): %s\n",
|
||||
progname, usb_strerror());
|
||||
fprintf(stderr, "%s: usbdev_recv_frame(): usb_%s_read(): %s\n",
|
||||
progname, (fd->usb.use_interrupt_xfer? "interrupt": "bulk"),
|
||||
usb_strerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -495,7 +559,10 @@ static int usbdev_drain(union filedescriptor *fd, int display)
|
|||
int rv;
|
||||
|
||||
do {
|
||||
rv = usb_bulk_read(udev, fd->usb.rep, usbbuf, fd->usb.max_xfer, 100);
|
||||
if (fd->usb.use_interrupt_xfer)
|
||||
rv = usb_interrupt_read(udev, fd->usb.rep, usbbuf, fd->usb.max_xfer, 100);
|
||||
else
|
||||
rv = usb_bulk_read(udev, fd->usb.rep, usbbuf, fd->usb.max_xfer, 100);
|
||||
if (rv > 0 && verbose >= 4)
|
||||
fprintf(stderr, "%s: usbdev_drain(): flushed %d characters\n",
|
||||
progname, rv);
|
||||
|
|
Loading…
Reference in New Issue