diff --git a/ChangeLog b/ChangeLog index 578448b9..fd44f144 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-11-29 Joerg Wunsch + + * jtag3.c: Handle events returned by the ICE + * usbdevs.h: Add defines that mark an event in return + from usb_recv_frame(). + * usb_libusb.c: (Dito.) + 2012-11-29 Joerg Wunsch * avrdude.conf.in: Remove "has_jtag" from Xmega A4 and D4 diff --git a/jtag3.c b/jtag3.c index e946a78e..5040061f 100644 --- a/jtag3.c +++ b/jtag3.c @@ -145,17 +145,6 @@ b4_to_u32(unsigned char *b) return l; } -static unsigned long -b4_to_u32r(unsigned char *b) -{ - unsigned long l; - l = b[3]; - l += (unsigned)b[2] << 8; - l += (unsigned)b[1] << 16; - l += (unsigned)b[0] << 24; - - return l; -} static void u32_to_b4(unsigned char *b, unsigned long l) @@ -165,14 +154,6 @@ u32_to_b4(unsigned char *b, unsigned long l) b[2] = (l >> 16) & 0xff; b[3] = (l >> 24) & 0xff; } -static void -u32_to_b4r(unsigned char *b, unsigned long l) -{ - b[3] = l & 0xff; - b[2] = (l >> 8) & 0xff; - b[1] = (l >> 16) & 0xff; - b[0] = (l >> 24) & 0xff; -} static unsigned short b2_to_u16(unsigned char *b) @@ -320,12 +301,56 @@ static void jtag3_prmsg(PROGRAMMER * pgm, unsigned char * data, size_t len) } break; -#if 0 - case EVT_BREAK: - fprintf(stderr, "BREAK event"); - if (len >= 6) { - fprintf(stderr, ", PC = 0x%lx, reason ", b4_to_u32(data + 1)); - switch (data[5]) { + default: + fprintf(stderr, "unknown message 0x%02x\n", data[1]); + } +} + +static void jtag3_prevent(PROGRAMMER * pgm, unsigned char * data, size_t len) +{ + int i; + + if (verbose >= 4) { + fprintf(stderr, "Raw event:\n"); + + for (i = 0; i < len; i++) { + fprintf(stderr, "%02x ", data[i]); + if (i % 16 == 15) + putc('\n', stderr); + else + putchar(' '); + } + if (i % 16 != 0) + putc('\n', stderr); + } + + fprintf(stderr, "Event serial 0x%04x, ", + (data[3] << 8) | data[2]); + + switch (data[4]) { + case SCOPE_INFO: + fprintf(stderr, "[info] "); + break; + + case SCOPE_GENERAL: + fprintf(stderr, "[general] "); + break; + + case SCOPE_AVR: + fprintf(stderr, "[AVR] "); + break; + + default: + fprintf(stderr, "[scope 0x%02x] ", data[0]); + break; + } + + switch (data[5]) { + case EVT3_BREAK: + fprintf(stderr, "BREAK"); + if (len >= 11) { + fprintf(stderr, ", PC = 0x%lx, reason ", b4_to_u32(data + 6)); + switch (data[10]) { case 0x00: fprintf(stderr, "unspecified"); break; @@ -339,21 +364,40 @@ static void jtag3_prmsg(PROGRAMMER * pgm, unsigned char * data, size_t len) fprintf(stderr, "data break PDMSB"); break; default: - fprintf(stderr, "unknown: 0x%02x", data[5]); + fprintf(stderr, "unknown: 0x%02x", data[10]); } + /* There are two more bytes of data which always appear to be + * 0x01, 0x00. Purpose unknown. */ } - putc('\n', stderr); break; - putc('\n', stderr); -#endif + case EVT3_SLEEP: + if (len >= 8 && data[7] == 0) + fprintf(stderr, "sleeping"); + else if (len >= 8 && data[7] == 1) + fprintf(stderr, "wakeup"); + else + fprintf(stderr, "unknown SLEEP event"); + break; + + case EVT3_POWER: + if (len >= 8 && data[7] == 0) + fprintf(stderr, "power-down"); + else if (len >= 8 && data[7] == 1) + fprintf(stderr, "power-up"); + else + fprintf(stderr, "unknown POWER event"); + break; default: - fprintf(stderr, "unknown message 0x%02x\n", data[1]); + fprintf(stderr, "UNKNOWN 0x%02x", data[5]); + break; } + putc('\n', stderr); } + int jtag3_send(PROGRAMMER * pgm, unsigned char * data, size_t len) { unsigned char *buf; @@ -439,6 +483,15 @@ int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg) { if ((rv = jtag3_recv_frame(pgm, msg)) <= 0) return rv; + if ((rv & USB_RECV_FLAG_EVENT) != 0) { + if (verbose >= 3) + jtag3_prevent(pgm, *msg, rv & USB_RECV_LENGTH_MASK); + + free(*msg); + continue; + } + + rv &= USB_RECV_LENGTH_MASK; r_seqno = ((*msg)[2] << 8) | (*msg)[1]; if (verbose >= 3) fprintf(stderr, "%s: jtag3_recv(): " @@ -457,16 +510,11 @@ int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg) { return rv; } - if (r_seqno == 0xffff) { - if (verbose >= 3) - fprintf(stderr, "%s: jtag3_recv(): got asynchronous event\n", - progname); - } else { - if (verbose >= 2) - fprintf(stderr, "%s: jtag3_recv(): " - "got wrong sequence number, %u != %u\n", - progname, r_seqno, PDATA(pgm)->command_sequence); - } + if (verbose >= 2) + fprintf(stderr, "%s: jtag3_recv(): " + "got wrong sequence number, %u != %u\n", + progname, r_seqno, PDATA(pgm)->command_sequence); + free(*msg); } } @@ -662,7 +710,7 @@ static int jtag3_program_disable(PROGRAMMER * pgm) buf[1] = CMD3_LEAVE_PROGMODE; buf[2] = 0; - if (jtag3_command(pgm, buf, 3, &resp, "enter progmode") < 0) + if (jtag3_command(pgm, buf, 3, &resp, "leave progmode") < 0) return -1; free(resp); diff --git a/usb_libusb.c b/usb_libusb.c index 35bdbfa4..51e3c0fa 100644 --- a/usb_libusb.c +++ b/usb_libusb.c @@ -406,22 +406,15 @@ static int usbdev_recv_frame(union filedescriptor *fd, unsigned char *buf, size_ fd->usb.max_xfer, 1); if (rv > 4) { - if (verbose >= 3) - { - unsigned short evtserial = (usbbuf[3] << 8) | usbbuf[2]; - fprintf(stderr, "Event serial # 0x%04x, replaced by 0xffff\n", - evtserial); - } - usbbuf[3] = usbbuf[2] = 0xff; - memcpy(buf, usbbuf + 2, rv - 2); - n = rv - 2; + memcpy(buf, usbbuf, rv); + n = rv; + n |= USB_RECV_FLAG_EVENT; goto printout; } else if (rv > 0) { fprintf(stderr, "Short event len = %d, ignored.\n", rv); - n = rv; - goto printout; + /* fallthrough */ } } @@ -455,7 +448,7 @@ static int usbdev_recv_frame(union filedescriptor *fd, unsigned char *buf, size_ printout: if (verbose > 3) { - i = n; + i = n & USB_RECV_LENGTH_MASK; fprintf(stderr, "%s: Recv: ", progname); while (i) { diff --git a/usbdevs.h b/usbdevs.h index e4523324..62b02d74 100644 --- a/usbdevs.h +++ b/usbdevs.h @@ -43,4 +43,13 @@ #define USBDEV_EVT_EP_READ_3 0x83 #define USBDEV_MAX_XFER_3 512 +/* + * When operating on the JTAGICE3, usbdev_recv_frame() returns an + * indication in the upper bits of the return value whether the + * message has been received from the event endpoint rather than the + * normal conversation endpoint. + */ +#define USB_RECV_LENGTH_MASK 0x0fff /* up to 4 KiB */ +#define USB_RECV_FLAG_EVENT 0x1000 + #endif /* usbdevs_h */