patch #8435: Implementing mEDBG CMSIS-DAP protocol
* usb_libusb.c: Add endpoint IDs for Xplained Mini, correctly transfer trailing ZLP when needed * avrdude.conf.in (xplainedmini, xplainedmini_dw): New entries. * jtag3.c (jtag3_edbg_send, jtag3_edbg_recv_frame): Implement fragmentation needed for the 64-byte EP size of the Xplained Mini git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1369 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
de02ef96ee
commit
a94e7b1325
|
@ -0,0 +1,9 @@
|
||||||
|
2016-02-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||||
|
|
||||||
|
patch #8435: Implementing mEDBG CMSIS-DAP protocol
|
||||||
|
* usb_libusb.c: Add endpoint IDs for Xplained Mini, correctly
|
||||||
|
transfer trailing ZLP when needed
|
||||||
|
* avrdude.conf.in (xplainedmini, xplainedmini_dw): New entries.
|
||||||
|
* jtag3.c (jtag3_edbg_send, jtag3_edbg_recv_frame): Implement
|
||||||
|
fragmentation needed for the 64-byte EP size of the Xplained Mini
|
||||||
|
|
4
NEWS
4
NEWS
|
@ -18,8 +18,12 @@ Current:
|
||||||
|
|
||||||
* New programmers supported:
|
* New programmers supported:
|
||||||
|
|
||||||
|
- Atmel mEDBG: xplainedmini, xplainedmini_dw
|
||||||
|
|
||||||
* Bugfixes
|
* Bugfixes
|
||||||
|
|
||||||
|
- patch #8435: Implementing mEDBG CMSIS-DAP protocol
|
||||||
|
|
||||||
* Internals:
|
* Internals:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1094,6 +1094,22 @@ programmer
|
||||||
usbpid = 0x2111;
|
usbpid = 0x2111;
|
||||||
;
|
;
|
||||||
|
|
||||||
|
programmer
|
||||||
|
id = "xplainedmini";
|
||||||
|
desc = "Atmel AVR XplainedMini in ISP mode";
|
||||||
|
type = "jtagice3_isp";
|
||||||
|
connection_type = usb;
|
||||||
|
usbpid = 0x2145;
|
||||||
|
;
|
||||||
|
|
||||||
|
programmer
|
||||||
|
id = "xplainedmini_dw";
|
||||||
|
desc = "Atmel AVR XplainedMini in debugWIRE mode";
|
||||||
|
type = "jtagice3_dw";
|
||||||
|
connection_type = usb;
|
||||||
|
usbpid = 0x2145;
|
||||||
|
;
|
||||||
|
|
||||||
programmer
|
programmer
|
||||||
id = "atmelice";
|
id = "atmelice";
|
||||||
desc = "Atmel-ICE (ARM/AVR) in JTAG mode";
|
desc = "Atmel-ICE (ARM/AVR) in JTAG mode";
|
||||||
|
|
184
jtag3.c
184
jtag3.c
|
@ -446,27 +446,50 @@ static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
||||||
avrdude_message(MSG_DEBUG, "\n%s: jtag3_edbg_send(): sending %lu bytes\n",
|
avrdude_message(MSG_DEBUG, "\n%s: jtag3_edbg_send(): sending %lu bytes\n",
|
||||||
progname, (unsigned long)len);
|
progname, (unsigned long)len);
|
||||||
|
|
||||||
if (len + 8 > USBDEV_MAX_XFER_3)
|
/* 4 bytes overhead for CMD, fragment #, and length info */
|
||||||
|
int max_xfer = pgm->fd.usb.max_xfer;
|
||||||
|
int nfragments = (len + max_xfer - 1) / max_xfer;
|
||||||
|
if (nfragments > 1)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): Fragmentation not (yet) implemented!\n",
|
avrdude_message(MSG_DEBUG, "%s: jtag3_edbg_send(): fragmenting into %d packets\n",
|
||||||
progname);
|
progname, nfragments);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
int frag;
|
||||||
|
for (frag = 0; frag < nfragments; frag++)
|
||||||
|
{
|
||||||
|
int this_len;
|
||||||
|
|
||||||
|
/* All fragments have the (CMSIS-DAP layer) CMD, the fragment
|
||||||
|
* identifier, and the length field. */
|
||||||
buf[0] = EDBG_VENDOR_AVR_CMD;
|
buf[0] = EDBG_VENDOR_AVR_CMD;
|
||||||
buf[1] = (1 << 4) | 1; /* first out of a total of 1 fragments */
|
buf[1] = ((frag + 1) << 4) | nfragments;
|
||||||
buf[2] = (len + 4) >> 8;
|
|
||||||
buf[3] = (len + 4) & 0xff;
|
if (frag == 0)
|
||||||
|
{
|
||||||
|
/* Only first fragment has TOKEN and seq#, thus four bytes
|
||||||
|
* less payload than subsequent fragments. */
|
||||||
|
this_len = len < max_xfer - 8? len: max_xfer - 8;
|
||||||
|
buf[2] = (this_len + 4) >> 8;
|
||||||
|
buf[3] = (this_len + 4) & 0xff;
|
||||||
buf[4] = TOKEN;
|
buf[4] = TOKEN;
|
||||||
buf[5] = 0; /* dummy */
|
buf[5] = 0; /* dummy */
|
||||||
u16_to_b2(buf + 6, PDATA(pgm)->command_sequence);
|
u16_to_b2(buf + 6, PDATA(pgm)->command_sequence);
|
||||||
memcpy(buf + 8, data, len);
|
memcpy(buf + 8, data, this_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this_len = len < max_xfer - 4? len: max_xfer - 4;
|
||||||
|
buf[2] = (this_len) >> 8;
|
||||||
|
buf[3] = (this_len) & 0xff;
|
||||||
|
memcpy(buf + 4, data, this_len);
|
||||||
|
}
|
||||||
|
|
||||||
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
|
if (serial_send(&pgm->fd, buf, max_xfer) != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): failed to send command to serial port\n",
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): failed to send command to serial port\n",
|
||||||
progname);
|
progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
|
rv = serial_recv(&pgm->fd, status, max_xfer);
|
||||||
|
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
/* timeout in receive */
|
/* timeout in receive */
|
||||||
|
@ -474,12 +497,16 @@ static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
||||||
progname);
|
progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (status[0] != EDBG_VENDOR_AVR_CMD || status[1] != 0x01)
|
if (status[0] != EDBG_VENDOR_AVR_CMD ||
|
||||||
|
(frag == nfragments - 1 && status[1] != 0x01))
|
||||||
{
|
{
|
||||||
/* what to do in this case? */
|
/* what to do in this case? */
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): Unexpected response 0x%02x, 0x%02x\n",
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): Unexpected response 0x%02x, 0x%02x\n",
|
||||||
progname, status[0], status[1]);
|
progname, status[0], status[1]);
|
||||||
}
|
}
|
||||||
|
data += this_len;
|
||||||
|
len -= this_len;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -501,13 +528,13 @@ static int jtag3_edbg_prepare(PROGRAMMER * pgm)
|
||||||
|
|
||||||
buf[0] = CMSISDAP_CMD_CONNECT;
|
buf[0] = CMSISDAP_CMD_CONNECT;
|
||||||
buf[1] = CMSISDAP_CONN_SWD;
|
buf[1] = CMSISDAP_CONN_SWD;
|
||||||
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
|
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to send command to serial port\n",
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to send command to serial port\n",
|
||||||
progname);
|
progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
|
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
|
||||||
if (rv != USBDEV_MAX_XFER_3) {
|
if (rv != pgm->fd.usb.max_xfer) {
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to read from serial port (%d)\n",
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to read from serial port (%d)\n",
|
||||||
progname, rv);
|
progname, rv);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -522,13 +549,13 @@ static int jtag3_edbg_prepare(PROGRAMMER * pgm)
|
||||||
buf[0] = CMSISDAP_CMD_LED;
|
buf[0] = CMSISDAP_CMD_LED;
|
||||||
buf[1] = CMSISDAP_LED_CONNECT;
|
buf[1] = CMSISDAP_LED_CONNECT;
|
||||||
buf[2] = 1;
|
buf[2] = 1;
|
||||||
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
|
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to send command to serial port\n",
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to send command to serial port\n",
|
||||||
progname);
|
progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
|
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
|
||||||
if (rv != USBDEV_MAX_XFER_3) {
|
if (rv != pgm->fd.usb.max_xfer) {
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to read from serial port (%d)\n",
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to read from serial port (%d)\n",
|
||||||
progname, rv);
|
progname, rv);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -560,13 +587,13 @@ static int jtag3_edbg_signoff(PROGRAMMER * pgm)
|
||||||
buf[0] = CMSISDAP_CMD_LED;
|
buf[0] = CMSISDAP_CMD_LED;
|
||||||
buf[1] = CMSISDAP_LED_CONNECT;
|
buf[1] = CMSISDAP_LED_CONNECT;
|
||||||
buf[2] = 0;
|
buf[2] = 0;
|
||||||
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
|
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to send command to serial port\n",
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to send command to serial port\n",
|
||||||
progname);
|
progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
|
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
|
||||||
if (rv != USBDEV_MAX_XFER_3) {
|
if (rv != pgm->fd.usb.max_xfer) {
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n",
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n",
|
||||||
progname, rv);
|
progname, rv);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -577,13 +604,13 @@ static int jtag3_edbg_signoff(PROGRAMMER * pgm)
|
||||||
progname, status[0], status[1]);
|
progname, status[0], status[1]);
|
||||||
|
|
||||||
buf[0] = CMSISDAP_CMD_DISCONNECT;
|
buf[0] = CMSISDAP_CMD_DISCONNECT;
|
||||||
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
|
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to send command to serial port\n",
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to send command to serial port\n",
|
||||||
progname);
|
progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
|
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
|
||||||
if (rv != USBDEV_MAX_XFER_3) {
|
if (rv != pgm->fd.usb.max_xfer) {
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n",
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n",
|
||||||
progname, rv);
|
progname, rv);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -644,8 +671,9 @@ static int jtag3_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
|
static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
|
||||||
int rv, len;
|
int rv, len = 0;
|
||||||
unsigned char *buf = NULL;
|
unsigned char *buf = NULL;
|
||||||
|
unsigned char *request;
|
||||||
|
|
||||||
avrdude_message(MSG_TRACE, "%s: jtag3_edbg_recv():\n", progname);
|
avrdude_message(MSG_TRACE, "%s: jtag3_edbg_recv():\n", progname);
|
||||||
|
|
||||||
|
@ -654,42 +682,92 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
|
||||||
progname);
|
progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if ((request = malloc(pgm->fd.usb.max_xfer)) == NULL) {
|
||||||
buf[0] = EDBG_VENDOR_AVR_RSP;
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): out of memory\n",
|
||||||
|
|
||||||
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): error sending CMSIS-DAP vendor command\n",
|
|
||||||
progname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = serial_recv(&pgm->fd, buf, USBDEV_MAX_XFER_3);
|
|
||||||
|
|
||||||
if (rv < 0) {
|
|
||||||
/* timeout in receive */
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_recv(): Timeout receiving packet\n",
|
|
||||||
progname);
|
progname);
|
||||||
free(buf);
|
free(buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[0] != EDBG_VENDOR_AVR_RSP ||
|
|
||||||
buf[1] != ((1 << 4) | 1)) {
|
|
||||||
avrdude_message(MSG_INFO, "%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) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected length value (%d > %d)\n",
|
|
||||||
progname, len, rv + 4);
|
|
||||||
len = rv + 4;
|
|
||||||
}
|
|
||||||
memmove(buf, buf + 4, len);
|
|
||||||
|
|
||||||
*msg = buf;
|
*msg = buf;
|
||||||
|
|
||||||
|
int nfrags = 0;
|
||||||
|
int thisfrag = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
request[0] = EDBG_VENDOR_AVR_RSP;
|
||||||
|
|
||||||
|
if (serial_send(&pgm->fd, request, pgm->fd.usb.max_xfer) != 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): error sending CMSIS-DAP vendor command\n",
|
||||||
|
progname);
|
||||||
|
free(request);
|
||||||
|
free(*msg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = serial_recv(&pgm->fd, buf, pgm->fd.usb.max_xfer);
|
||||||
|
|
||||||
|
if (rv < 0) {
|
||||||
|
/* timeout in receive */
|
||||||
|
avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_recv(): Timeout receiving packet\n",
|
||||||
|
progname);
|
||||||
|
free(*msg);
|
||||||
|
free(request);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf[0] != EDBG_VENDOR_AVR_RSP) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected response 0x%02x\n",
|
||||||
|
progname, buf[0]);
|
||||||
|
free(*msg);
|
||||||
|
free(request);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate fragment information */
|
||||||
|
if (thisfrag == 0) {
|
||||||
|
/* first fragment */
|
||||||
|
nfrags = buf[1] & 0x0F;
|
||||||
|
thisfrag = 1;
|
||||||
|
} else {
|
||||||
|
if (nfrags != (buf[1] & 0x0F)) {
|
||||||
|
avrdude_message(MSG_INFO,
|
||||||
|
"%s: jtag3_edbg_recv(): "
|
||||||
|
"Inconsistent # of fragments; had %d, now %d\n",
|
||||||
|
progname, nfrags, (buf[1] & 0x0F));
|
||||||
|
free(*msg);
|
||||||
|
free(request);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (thisfrag != ((buf[1] >> 4) & 0x0F)) {
|
||||||
|
avrdude_message(MSG_INFO,
|
||||||
|
"%s: jtag3_edbg_recv(): "
|
||||||
|
"Inconsistent fragment number; expect %d, got %d\n",
|
||||||
|
progname, thisfrag, ((buf[1] >> 4) & 0x0F));
|
||||||
|
free(*msg);
|
||||||
|
free(request);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int thislen = (buf[2] << 8) | buf[3];
|
||||||
|
if (thislen > rv + 4) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected length value (%d > %d)\n",
|
||||||
|
progname, thislen, rv + 4);
|
||||||
|
thislen = rv + 4;
|
||||||
|
}
|
||||||
|
if (len + thislen > USBDEV_MAX_XFER_3) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Length exceeds max size (%d > %d)\n",
|
||||||
|
progname, len + thislen, USBDEV_MAX_XFER_3);
|
||||||
|
thislen = USBDEV_MAX_XFER_3 - len;
|
||||||
|
}
|
||||||
|
memmove(buf, buf + 4, thislen);
|
||||||
|
thisfrag++;
|
||||||
|
len += thislen;
|
||||||
|
buf += thislen;
|
||||||
|
} while (thisfrag <= nfrags);
|
||||||
|
|
||||||
|
free(request);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,13 @@ static int usbdev_open(char * port, union pinfo pinfo, union filedescriptor *fd)
|
||||||
fd->usb.eep = 0;
|
fd->usb.eep = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(strstr(product, "mEDBG") != NULL)
|
||||||
|
{
|
||||||
|
/* The AVR Xplained Mini uses different endpoints. */
|
||||||
|
fd->usb.rep = 0x81;
|
||||||
|
fd->usb.wep = 0x02;
|
||||||
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE, "%s: usbdev_open(): Found %s, serno: %s\n",
|
avrdude_message(MSG_NOTICE, "%s: usbdev_open(): Found %s, serno: %s\n",
|
||||||
progname, product, string);
|
progname, product, string);
|
||||||
if (serno != NULL)
|
if (serno != NULL)
|
||||||
|
@ -353,7 +360,7 @@ static int usbdev_send(union filedescriptor *fd, const unsigned char *bp, size_t
|
||||||
}
|
}
|
||||||
bp += tx_size;
|
bp += tx_size;
|
||||||
mlen -= tx_size;
|
mlen -= tx_size;
|
||||||
} while (tx_size == fd->usb.max_xfer);
|
} while (mlen > 0);
|
||||||
|
|
||||||
if (verbose > 3)
|
if (verbose > 3)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue